Auto merge of #78001 - Dylan-DPC:rollup-zq3kxth, r=Dylan-DPC
Rollup of 14 pull requests Successful merges: - #75023 (ensure arguments are included in count mismatch span) - #75265 (Add `str::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive}::as_str` methods) - #75675 (mangling: mangle impl params w/ v0 scheme) - #76084 (Refactor io/buffered.rs into submodules) - #76119 (Stabilize move_ref_pattern) - #77493 (ICEs should always print the top of the query stack) - #77619 (Use futex-based thread-parker for Wasm32.) - #77646 (For backtrace, use StaticMutex instead of a raw sys Mutex.) - #77648 (Static mutex is static) - #77657 (Cleanup cloudabi mutexes and condvars) - #77672 (Simplify doc-cfg rendering based on the current context) - #77780 (rustc_parse: fix spans on cast and range exprs with attrs) - #77935 (BTreeMap: make PartialCmp/PartialEq explicit and tested) - #77980 (Fix intra doc link for needs_drop) Failed merges: r? `@ghost`
This commit is contained in:
commit
b6e2dc6cde
@ -1258,9 +1258,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
// If backtraces are enabled, also print the query stack
|
||||
let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
|
||||
|
||||
if backtrace {
|
||||
TyCtxt::try_print_query_stack(&handler);
|
||||
}
|
||||
let num_frames = if backtrace { None } else { Some(2) };
|
||||
|
||||
TyCtxt::try_print_query_stack(&handler, num_frames);
|
||||
|
||||
#[cfg(windows)]
|
||||
unsafe {
|
||||
|
@ -1,3 +1,5 @@
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
This error indicates that the bindings in a match arm would require a value to
|
||||
be moved into more than one location, thus violating unique ownership. Code
|
||||
like the following is invalid as it requires the entire `Option<String>` to be
|
||||
@ -6,11 +8,13 @@ inner `String` to be moved into a variable called `s`.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0007
|
||||
```compile_fail,E0382
|
||||
#![feature(bindings_after_at)]
|
||||
|
||||
let x = Some("s".to_string());
|
||||
|
||||
match x {
|
||||
op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
|
||||
op_string @ Some(s) => {}, // error: use of moved value
|
||||
None => {},
|
||||
}
|
||||
```
|
||||
|
@ -270,6 +270,9 @@ declare_features! (
|
||||
(accepted, track_caller, "1.46.0", Some(47809), None),
|
||||
/// Allows `#[doc(alias = "...")]`.
|
||||
(accepted, doc_alias, "1.48.0", Some(50146), None),
|
||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||
(accepted, move_ref_pattern, "1.48.0", Some(68354), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: accepted features
|
||||
|
@ -526,10 +526,6 @@ declare_features! (
|
||||
/// For example, you can write `x @ Some(y)`.
|
||||
(active, bindings_after_at, "1.41.0", Some(65490), None),
|
||||
|
||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||
(active, move_ref_pattern, "1.42.0", Some(68354), None),
|
||||
|
||||
/// Allows `impl const Trait for T` syntax.
|
||||
(active, const_trait_impl, "1.42.0", Some(67792), None),
|
||||
|
||||
|
@ -2742,4 +2742,32 @@ impl<'hir> Node<'hir> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hir_id(&self) -> Option<HirId> {
|
||||
match self {
|
||||
Node::Item(Item { hir_id, .. })
|
||||
| Node::ForeignItem(ForeignItem { hir_id, .. })
|
||||
| Node::TraitItem(TraitItem { hir_id, .. })
|
||||
| Node::ImplItem(ImplItem { hir_id, .. })
|
||||
| Node::Field(StructField { hir_id, .. })
|
||||
| Node::AnonConst(AnonConst { hir_id, .. })
|
||||
| Node::Expr(Expr { hir_id, .. })
|
||||
| Node::Stmt(Stmt { hir_id, .. })
|
||||
| Node::Ty(Ty { hir_id, .. })
|
||||
| Node::Binding(Pat { hir_id, .. })
|
||||
| Node::Pat(Pat { hir_id, .. })
|
||||
| Node::Arm(Arm { hir_id, .. })
|
||||
| Node::Block(Block { hir_id, .. })
|
||||
| Node::Local(Local { hir_id, .. })
|
||||
| Node::MacroDef(MacroDef { hir_id, .. })
|
||||
| Node::Lifetime(Lifetime { hir_id, .. })
|
||||
| Node::Param(Param { hir_id, .. })
|
||||
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
|
||||
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
|
||||
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
|
||||
Node::Variant(Variant { id, .. }) => Some(*id),
|
||||
Node::Ctor(variant) => variant.ctor_hir_id(),
|
||||
Node::Crate(_) | Node::Visibility(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +291,17 @@ impl<'tcx> Instance<'tcx> {
|
||||
}
|
||||
|
||||
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
|
||||
Instance::new(def_id, tcx.empty_substs_for_def_id(def_id))
|
||||
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
||||
ty::GenericParamDefKind::Type { .. } => {
|
||||
bug!("Instance::mono: {:?} has type parameters", def_id)
|
||||
}
|
||||
ty::GenericParamDefKind::Const { .. } => {
|
||||
bug!("Instance::mono: {:?} has const parameters", def_id)
|
||||
}
|
||||
});
|
||||
|
||||
Instance::new(def_id, substs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -124,20 +124,23 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_print_query_stack(handler: &Handler) {
|
||||
pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
|
||||
eprintln!("query stack during panic:");
|
||||
|
||||
// Be careful reyling on global state here: this code is called from
|
||||
// a panic hook, which means that the global `Handler` may be in a weird
|
||||
// state if it was responsible for triggering the panic.
|
||||
let mut i = 0;
|
||||
ty::tls::with_context_opt(|icx| {
|
||||
if let Some(icx) = icx {
|
||||
let query_map = icx.tcx.queries.try_collect_active_jobs();
|
||||
|
||||
let mut current_query = icx.query;
|
||||
let mut i = 0;
|
||||
|
||||
while let Some(query) = current_query {
|
||||
if Some(i) == num_frames {
|
||||
break;
|
||||
}
|
||||
let query_info =
|
||||
if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) {
|
||||
info
|
||||
@ -163,7 +166,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
});
|
||||
|
||||
eprintln!("end of query stack");
|
||||
if num_frames == None || num_frames >= Some(i) {
|
||||
eprintln!("end of query stack");
|
||||
} else {
|
||||
eprintln!("we're just showing a limited slice of the query stack");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,9 @@ use crate::mir::interpret::{sign_extend, truncate};
|
||||
use crate::ty::fold::TypeFolder;
|
||||
use crate::ty::layout::IntegerExt;
|
||||
use crate::ty::query::TyCtxtAt;
|
||||
use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
|
||||
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
||||
use crate::ty::TyKind::*;
|
||||
use crate::ty::{self, DefIdTree, GenericParamDefKind, List, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_apfloat::Float as _;
|
||||
use rustc_ast as ast;
|
||||
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
|
||||
@ -509,20 +509,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
Some(ty::Binder::bind(env_ty))
|
||||
}
|
||||
|
||||
/// Given the `DefId` of some item that has no type or const parameters, make
|
||||
/// a suitable "empty substs" for it.
|
||||
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> SubstsRef<'tcx> {
|
||||
InternalSubsts::for_item(self, item_def_id, |param, _| match param.kind {
|
||||
GenericParamDefKind::Lifetime => self.lifetimes.re_erased.into(),
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
|
||||
}
|
||||
GenericParamDefKind::Const { .. } => {
|
||||
bug!("empty_substs_for_def_id: {:?} has const parameters", item_def_id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
||||
pub fn is_static(self, def_id: DefId) -> bool {
|
||||
self.static_mutability(def_id).is_some()
|
||||
|
@ -71,13 +71,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
|
||||
hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
|
||||
};
|
||||
self.check_irrefutable(&loc.pat, msg, sp);
|
||||
self.check_patterns(false, &loc.pat);
|
||||
self.check_patterns(&loc.pat);
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||
intravisit::walk_param(self, param);
|
||||
self.check_irrefutable(¶m.pat, "function argument", None);
|
||||
self.check_patterns(false, ¶m.pat);
|
||||
self.check_patterns(¶m.pat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,10 +119,7 @@ impl PatCtxt<'_, '_> {
|
||||
}
|
||||
|
||||
impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||
fn check_patterns(&mut self, has_guard: bool, pat: &Pat<'_>) {
|
||||
if !self.tcx.features().move_ref_pattern {
|
||||
check_legality_of_move_bindings(self, has_guard, pat);
|
||||
}
|
||||
fn check_patterns(&mut self, pat: &Pat<'_>) {
|
||||
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
||||
if !self.tcx.features().bindings_after_at {
|
||||
check_legality_of_bindings_in_at_patterns(self, pat);
|
||||
@ -165,7 +162,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||
) {
|
||||
for arm in arms {
|
||||
// Check the arm for some things unrelated to exhaustiveness.
|
||||
self.check_patterns(arm.guard.is_some(), &arm.pat);
|
||||
self.check_patterns(&arm.pat);
|
||||
}
|
||||
|
||||
let mut cx = self.new_cx(scrut.hir_id);
|
||||
@ -601,65 +598,6 @@ fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> b
|
||||
!cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env)
|
||||
}
|
||||
|
||||
/// Check the legality of legality of by-move bindings.
|
||||
fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat<'_>) {
|
||||
let sess = cx.tcx.sess;
|
||||
let typeck_results = cx.typeck_results;
|
||||
|
||||
// Find all by-ref spans.
|
||||
let mut by_ref_spans = Vec::new();
|
||||
pat.each_binding(|_, hir_id, span, _| {
|
||||
if let Some(ty::BindByReference(_)) =
|
||||
typeck_results.extract_binding_mode(sess, hir_id, span)
|
||||
{
|
||||
by_ref_spans.push(span);
|
||||
}
|
||||
});
|
||||
|
||||
// Find bad by-move spans:
|
||||
let by_move_spans = &mut Vec::new();
|
||||
let mut check_move = |p: &Pat<'_>, sub: Option<&Pat<'_>>| {
|
||||
// Check legality of moving out of the enum.
|
||||
//
|
||||
// `x @ Foo(..)` is legal, but `x @ Foo(y)` isn't.
|
||||
if sub.map_or(false, |p| p.contains_bindings()) {
|
||||
struct_span_err!(sess, p.span, E0007, "cannot bind by-move with sub-bindings")
|
||||
.span_label(p.span, "binds an already bound by-move value by moving it")
|
||||
.emit();
|
||||
} else if !has_guard && !by_ref_spans.is_empty() {
|
||||
by_move_spans.push(p.span);
|
||||
}
|
||||
};
|
||||
pat.walk_always(|p| {
|
||||
if let hir::PatKind::Binding(.., sub) = &p.kind {
|
||||
if let Some(ty::BindByValue(_)) =
|
||||
typeck_results.extract_binding_mode(sess, p.hir_id, p.span)
|
||||
{
|
||||
if is_binding_by_move(cx, p.hir_id, p.span) {
|
||||
check_move(p, sub.as_deref());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Found some bad by-move spans, error!
|
||||
if !by_move_spans.is_empty() {
|
||||
let mut err = feature_err(
|
||||
&sess.parse_sess,
|
||||
sym::move_ref_pattern,
|
||||
by_move_spans.clone(),
|
||||
"binding by-move and by-ref in the same pattern is unstable",
|
||||
);
|
||||
for span in by_ref_spans.iter() {
|
||||
err.span_label(*span, "by-ref pattern here");
|
||||
}
|
||||
for span in by_move_spans.iter() {
|
||||
err.span_label(*span, "by-move pattern here");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
|
||||
///
|
||||
/// For example, this would reject:
|
||||
|
@ -246,11 +246,7 @@ impl<'a> Parser<'a> {
|
||||
this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
||||
})?;
|
||||
|
||||
// Make sure that the span of the parent node is larger than the span of lhs and rhs,
|
||||
// including the attributes.
|
||||
let lhs_span =
|
||||
lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer).map_or(lhs_span, |a| a.span);
|
||||
let span = lhs_span.to(rhs.span);
|
||||
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
||||
lhs = match op {
|
||||
AssocOp::Add
|
||||
| AssocOp::Subtract
|
||||
@ -411,7 +407,7 @@ impl<'a> Parser<'a> {
|
||||
None
|
||||
};
|
||||
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
||||
let span = lhs.span.to(rhs_span);
|
||||
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
|
||||
let limits =
|
||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
||||
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new()))
|
||||
@ -571,7 +567,11 @@ impl<'a> Parser<'a> {
|
||||
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let mk_expr = |this: &mut Self, rhs: P<Ty>| {
|
||||
this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), AttrVec::new())
|
||||
this.mk_expr(
|
||||
this.mk_expr_sp(&lhs, lhs_span, rhs.span),
|
||||
expr_kind(lhs, rhs),
|
||||
AttrVec::new(),
|
||||
)
|
||||
};
|
||||
|
||||
// Save the state of the parser before parsing type normally, in case there is a
|
||||
@ -2324,4 +2324,14 @@ impl<'a> Parser<'a> {
|
||||
pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
|
||||
self.mk_expr(span, ExprKind::Err, AttrVec::new())
|
||||
}
|
||||
|
||||
/// Create expression span ensuring the span of the parent node
|
||||
/// is larger than the span of lhs and rhs, including the attributes.
|
||||
fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
|
||||
lhs.attrs
|
||||
.iter()
|
||||
.find(|a| a.style == AttrStyle::Outer)
|
||||
.map_or(lhs_span, |a| a.span)
|
||||
.to(rhs_span)
|
||||
}
|
||||
}
|
||||
|
@ -1744,7 +1744,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
let span = lo.to(self.token.span);
|
||||
let span = lo.until(self.token.span);
|
||||
|
||||
Ok(Param {
|
||||
attrs: attrs.into(),
|
||||
|
@ -115,7 +115,6 @@ fn get_symbol_hash<'tcx>(
|
||||
}
|
||||
|
||||
// also include any type parameters (for generic items)
|
||||
assert!(!substs.has_erasable_regions());
|
||||
substs.hash_stable(&mut hcx, &mut hasher);
|
||||
|
||||
if let Some(instantiating_crate) = instantiating_crate {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{Instance, TyCtxt};
|
||||
use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
|
||||
@ -36,8 +36,11 @@ impl SymbolNamesTest<'tcx> {
|
||||
let def_id = tcx.hir().local_def_id(hir_id);
|
||||
for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
|
||||
if tcx.sess.check_name(attr, SYMBOL_NAME) {
|
||||
// for now, can only use on monomorphic names
|
||||
let instance = Instance::mono(tcx, def_id.to_def_id());
|
||||
let def_id = def_id.to_def_id();
|
||||
let instance = Instance::new(
|
||||
def_id,
|
||||
tcx.erase_regions(&InternalSubsts::identity_for_item(tcx, def_id)),
|
||||
);
|
||||
let mangled = tcx.symbol_name(instance);
|
||||
tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled));
|
||||
if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) {
|
||||
|
@ -259,7 +259,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
}
|
||||
|
||||
fn print_impl_path(
|
||||
self,
|
||||
mut self,
|
||||
impl_def_id: DefId,
|
||||
substs: &'tcx [GenericArg<'tcx>],
|
||||
mut self_ty: Ty<'tcx>,
|
||||
@ -284,12 +284,37 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.path_append_impl(
|
||||
|cx| cx.print_def_path(parent_def_id, &[]),
|
||||
&key.disambiguated_data,
|
||||
self_ty,
|
||||
impl_trait_ref,
|
||||
)
|
||||
self.push(match impl_trait_ref {
|
||||
Some(_) => "X",
|
||||
None => "M",
|
||||
});
|
||||
|
||||
// Encode impl generic params if the substitutions contain parameters (implying
|
||||
// polymorphization is enabled) and this isn't an inherent impl.
|
||||
if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
|
||||
self = self.path_generic_args(
|
||||
|this| {
|
||||
this.path_append_ns(
|
||||
|cx| cx.print_def_path(parent_def_id, &[]),
|
||||
'I',
|
||||
key.disambiguated_data.disambiguator as u64,
|
||||
"",
|
||||
)
|
||||
},
|
||||
substs,
|
||||
)?;
|
||||
} else {
|
||||
self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
|
||||
self = self.print_def_path(parent_def_id, &[])?;
|
||||
}
|
||||
|
||||
self = self_ty.print(self)?;
|
||||
|
||||
if let Some(trait_ref) = impl_trait_ref {
|
||||
self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn print_region(mut self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
|
||||
@ -538,6 +563,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
self.push_ident(&name);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
@ -552,24 +578,16 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
mut self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
self,
|
||||
_: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
_: &DisambiguatedDefPathData,
|
||||
_: Ty<'tcx>,
|
||||
_: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
self.push(match trait_ref {
|
||||
Some(_) => "X",
|
||||
None => "M",
|
||||
});
|
||||
self.push_disambiguator(disambiguated_data.disambiguator as u64);
|
||||
self = print_prefix(self)?;
|
||||
self = self_ty.print(self)?;
|
||||
if let Some(trait_ref) = trait_ref {
|
||||
self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
|
||||
}
|
||||
Ok(self)
|
||||
// Inlined into `print_impl_path`
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
@ -603,6 +621,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
name.as_ref().map_or("", |s| &s[..]),
|
||||
)
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
mut self,
|
||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||
|
@ -285,10 +285,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||
expected: Expectation<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let (fn_sig, def_span) = match *callee_ty.kind() {
|
||||
ty::FnDef(def_id, _) => {
|
||||
(callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id))
|
||||
}
|
||||
let (fn_sig, def_id) = match *callee_ty.kind() {
|
||||
ty::FnDef(def_id, _) => (callee_ty.fn_sig(self.tcx), Some(def_id)),
|
||||
ty::FnPtr(sig) => (sig, None),
|
||||
ref t => {
|
||||
let mut unit_variant = None;
|
||||
@ -427,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
arg_exprs,
|
||||
fn_sig.c_variadic,
|
||||
TupleArgumentsFlag::DontTupleArguments,
|
||||
def_span,
|
||||
def_id,
|
||||
);
|
||||
|
||||
fn_sig.output()
|
||||
|
@ -19,7 +19,7 @@ use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_span::{self, MultiSpan, Span};
|
||||
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
||||
|
||||
use std::mem::replace;
|
||||
@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
args_no_rcvr,
|
||||
method.sig.c_variadic,
|
||||
tuple_arguments,
|
||||
self.tcx.hir().span_if_local(method.def_id),
|
||||
Some(method.def_id),
|
||||
);
|
||||
method.sig.output()
|
||||
}
|
||||
@ -99,7 +99,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
args: &'tcx [hir::Expr<'tcx>],
|
||||
c_variadic: bool,
|
||||
tuple_arguments: TupleArgumentsFlag,
|
||||
def_span: Option<Span>,
|
||||
def_id: Option<DefId>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
// Grab the argument types, supplying fresh type variables
|
||||
@ -172,9 +172,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().guess_head_span(sp)) {
|
||||
err.span_label(def_s, "defined here");
|
||||
if let Some(def_id) = def_id {
|
||||
if let Some(node) = tcx.hir().get_if_local(def_id) {
|
||||
let mut spans: MultiSpan = node
|
||||
.ident()
|
||||
.map(|ident| ident.span)
|
||||
.unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap()))
|
||||
.into();
|
||||
|
||||
if let Some(id) = node.body_id() {
|
||||
let body = tcx.hir().body(id);
|
||||
for param in body.params {
|
||||
spans.push_span_label(param.span, String::new());
|
||||
}
|
||||
}
|
||||
|
||||
let def_kind = tcx.def_kind(def_id);
|
||||
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
|
||||
}
|
||||
}
|
||||
|
||||
if sugg_unit {
|
||||
let sugg_span = tcx.sess.source_map().end_point(expr.span);
|
||||
// remove closing `)` from the span
|
||||
|
@ -257,8 +257,13 @@ impl<K, V> Root<K, V> {
|
||||
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
|
||||
/// `NodeRef` could be pointing to either type of node.
|
||||
pub struct NodeRef<BorrowType, K, V, Type> {
|
||||
/// The number of levels below the node.
|
||||
/// The number of levels below the node, a property of the node that cannot be
|
||||
/// entirely described by `Type` and that the node does not store itself either.
|
||||
/// Unconstrained if `Type` is `LeafOrInternal`, must be zero if `Type` is `Leaf`,
|
||||
/// and must be non-zero if `Type` is `Internal`.
|
||||
height: usize,
|
||||
/// The pointer to the leaf or internal node. The definition of `InternalNode`
|
||||
/// ensures that the pointer is valid either way.
|
||||
node: NonNull<LeafNode<K, V>>,
|
||||
_marker: PhantomData<(BorrowType, Type)>,
|
||||
}
|
||||
@ -315,8 +320,8 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||
unsafe { usize::from((*self.as_leaf_ptr()).len) }
|
||||
}
|
||||
|
||||
/// Returns the height of this node in the whole tree. Zero height denotes the
|
||||
/// leaf level.
|
||||
/// Returns the height of this node with respect to the leaf level. Zero height means the
|
||||
/// node is a leaf itself.
|
||||
pub fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
@ -584,9 +589,11 @@ impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
|
||||
// to avoid aliasing with outstanding references to other elements,
|
||||
// in particular, those returned to the caller in earlier iterations.
|
||||
let leaf = self.node.as_ptr();
|
||||
let keys = unsafe { &raw const (*leaf).keys };
|
||||
let vals = unsafe { &raw mut (*leaf).vals };
|
||||
// We must coerce to unsized array pointers because of Rust issue #74679.
|
||||
let keys: *const [_] = unsafe { &raw const (*leaf).keys };
|
||||
let vals: *mut [_] = unsafe { &raw mut (*leaf).vals };
|
||||
let keys: *const [_] = keys;
|
||||
let vals: *mut [_] = vals;
|
||||
// SAFETY: The keys and values of a node must always be initialized up to length.
|
||||
let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() };
|
||||
let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() };
|
||||
@ -817,11 +824,25 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar
|
||||
}
|
||||
}
|
||||
|
||||
impl<BorrowType, K, V, NodeType> NodeRef<BorrowType, K, V, NodeType> {
|
||||
/// Could be a public implementation of PartialEq, but only used in this module.
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let Self { node, height, _marker: _ } = self;
|
||||
if *node == other.node {
|
||||
debug_assert_eq!(*height, other.height);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BorrowType, K, V, NodeType, HandleType> PartialEq
|
||||
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.node.node == other.node.node && self.idx == other.idx
|
||||
let Self { node, idx, _marker: _ } = self;
|
||||
node.eq(&other.node) && *idx == other.idx
|
||||
}
|
||||
}
|
||||
|
||||
@ -829,7 +850,8 @@ impl<BorrowType, K, V, NodeType, HandleType> PartialOrd
|
||||
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
if self.node.node == other.node.node { Some(self.idx.cmp(&other.idx)) } else { None }
|
||||
let Self { node, idx, _marker: _ } = self;
|
||||
if node.eq(&other.node) { Some(idx.cmp(&other.idx)) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use core::cmp::Ordering::*;
|
||||
|
||||
#[test]
|
||||
fn test_splitpoint() {
|
||||
@ -24,6 +25,38 @@ fn test_splitpoint() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_cmp_eq() {
|
||||
let mut root1: Root<i32, ()> = Root::new_leaf();
|
||||
let mut leaf1 = unsafe { root1.leaf_node_as_mut() };
|
||||
leaf1.push(1, ());
|
||||
root1.push_internal_level();
|
||||
let root2: Root<i32, ()> = Root::new_leaf();
|
||||
|
||||
let leaf_edge_1a = root1.node_as_ref().first_leaf_edge().forget_node_type();
|
||||
let leaf_edge_1b = root1.node_as_ref().last_leaf_edge().forget_node_type();
|
||||
let top_edge_1 = root1.node_as_ref().first_edge();
|
||||
let top_edge_2 = root2.node_as_ref().first_edge();
|
||||
|
||||
assert!(leaf_edge_1a == leaf_edge_1a);
|
||||
assert!(leaf_edge_1a != leaf_edge_1b);
|
||||
assert!(leaf_edge_1a != top_edge_1);
|
||||
assert!(leaf_edge_1a != top_edge_2);
|
||||
assert!(top_edge_1 == top_edge_1);
|
||||
assert!(top_edge_1 != top_edge_2);
|
||||
|
||||
assert_eq!(leaf_edge_1a.partial_cmp(&leaf_edge_1a), Some(Equal));
|
||||
assert_eq!(leaf_edge_1a.partial_cmp(&leaf_edge_1b), Some(Less));
|
||||
assert_eq!(leaf_edge_1a.partial_cmp(&top_edge_1), None);
|
||||
assert_eq!(leaf_edge_1a.partial_cmp(&top_edge_2), None);
|
||||
assert_eq!(top_edge_1.partial_cmp(&top_edge_1), Some(Equal));
|
||||
assert_eq!(top_edge_1.partial_cmp(&top_edge_2), None);
|
||||
|
||||
root1.pop_internal_level();
|
||||
unsafe { root1.into_ref().deallocate_and_ascend() };
|
||||
unsafe { root2.into_ref().deallocate_and_ascend() };
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn test_sizes() {
|
||||
|
@ -1082,7 +1082,7 @@ extern "rust-intrinsic" {
|
||||
/// If the actual type neither requires drop glue nor implements
|
||||
/// `Copy`, then the return value of this function is unspecified.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is [`needs_drop`].
|
||||
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
|
||||
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
|
||||
pub fn needs_drop<T>() -> bool;
|
||||
|
||||
|
@ -126,6 +126,8 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(str_split_as_str)]
|
||||
#![feature(str_split_inclusive_as_str)]
|
||||
#![feature(transparent_unions)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unsized_locals)]
|
||||
|
@ -690,6 +690,17 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_str(&self) -> &'a str {
|
||||
// `Self::get_end` doesn't change `self.start`
|
||||
if self.finished {
|
||||
return "";
|
||||
}
|
||||
|
||||
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
|
||||
unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
|
||||
}
|
||||
}
|
||||
|
||||
generate_pattern_iterators! {
|
||||
@ -710,6 +721,48 @@ generate_pattern_iterators! {
|
||||
delegate double ended;
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> Split<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_as_str)]
|
||||
/// let mut split = "Mary had a little lamb".split(' ');
|
||||
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), "had a little lamb");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> RSplit<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_as_str)]
|
||||
/// let mut split = "Mary had a little lamb".rsplit(' ');
|
||||
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), "Mary had a little");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
generate_pattern_iterators! {
|
||||
forward:
|
||||
/// Created with the method [`split_terminator`].
|
||||
@ -728,6 +781,48 @@ generate_pattern_iterators! {
|
||||
delegate double ended;
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_as_str)]
|
||||
/// let mut split = "A..B..".split_terminator('.');
|
||||
/// assert_eq!(split.as_str(), "A..B..");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), ".B..");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_as_str)]
|
||||
/// let mut split = "A..B..".rsplit_terminator('.');
|
||||
/// assert_eq!(split.as_str(), "A..B..");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), "A..B");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
derive_pattern_clone! {
|
||||
clone SplitNInternal
|
||||
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
|
||||
@ -784,6 +879,11 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_str(&self) -> &'a str {
|
||||
self.iter.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
generate_pattern_iterators! {
|
||||
@ -804,6 +904,48 @@ generate_pattern_iterators! {
|
||||
delegate single ended;
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitN<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_as_str)]
|
||||
/// let mut split = "Mary had a little lamb".splitn(3, ' ');
|
||||
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), "had a little lamb");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_as_str)]
|
||||
/// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
|
||||
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), "Mary had a little");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
derive_pattern_clone! {
|
||||
clone MatchIndicesInternal
|
||||
with |s| MatchIndicesInternal(s.0.clone())
|
||||
@ -1134,6 +1276,28 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
|
||||
#[unstable(feature = "split_inclusive", issue = "72360")]
|
||||
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
|
||||
|
||||
impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
|
||||
/// Returns remainder of the splitted string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(str_split_inclusive_as_str)]
|
||||
/// #![feature(split_inclusive)]
|
||||
/// let mut split = "Mary had a little lamb".split_inclusive(' ');
|
||||
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||
/// split.next();
|
||||
/// assert_eq!(split.as_str(), "had a little lamb");
|
||||
/// split.by_ref().for_each(drop);
|
||||
/// assert_eq!(split.as_str(), "");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator of [`u16`] over the string encoded as UTF-16.
|
||||
///
|
||||
/// This struct is created by the [`encode_utf16`] method on [`str`].
|
||||
|
@ -303,7 +303,8 @@ impl Backtrace {
|
||||
// Capture a backtrace which start just before the function addressed by
|
||||
// `ip`
|
||||
fn create(ip: usize) -> Backtrace {
|
||||
let _lock = lock();
|
||||
// SAFETY: We don't attempt to lock this reentrantly.
|
||||
let _lock = unsafe { lock() };
|
||||
let mut frames = Vec::new();
|
||||
let mut actual_start = None;
|
||||
unsafe {
|
||||
@ -408,7 +409,8 @@ impl Capture {
|
||||
// Use the global backtrace lock to synchronize this as it's a
|
||||
// requirement of the `backtrace` crate, and then actually resolve
|
||||
// everything.
|
||||
let _lock = lock();
|
||||
// SAFETY: We don't attempt to lock this reentrantly.
|
||||
let _lock = unsafe { lock() };
|
||||
for frame in self.frames.iter_mut() {
|
||||
let symbols = &mut frame.symbols;
|
||||
let frame = match &frame.frame {
|
||||
|
File diff suppressed because it is too large
Load Diff
423
library/std/src/io/buffered/bufreader.rs
Normal file
423
library/std/src/io/buffered/bufreader.rs
Normal file
@ -0,0 +1,423 @@
|
||||
use crate::cmp;
|
||||
use crate::fmt;
|
||||
use crate::io::{self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, DEFAULT_BUF_SIZE};
|
||||
|
||||
/// The `BufReader<R>` struct adds buffering to any reader.
|
||||
///
|
||||
/// It can be excessively inefficient to work directly with a [`Read`] instance.
|
||||
/// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`]
|
||||
/// results in a system call. A `BufReader<R>` performs large, infrequent reads on
|
||||
/// the underlying [`Read`] and maintains an in-memory buffer of the results.
|
||||
///
|
||||
/// `BufReader<R>` can improve the speed of programs that make *small* and
|
||||
/// *repeated* read calls to the same file or network socket. It does not
|
||||
/// help when reading very large amounts at once, or reading just one or a few
|
||||
/// times. It also provides no advantage when reading from a source that is
|
||||
/// already in memory, like a [`Vec`]`<u8>`.
|
||||
///
|
||||
/// When the `BufReader<R>` is dropped, the contents of its buffer will be
|
||||
/// discarded. Creating multiple instances of a `BufReader<R>` on the same
|
||||
/// stream can cause data loss. Reading from the underlying reader after
|
||||
/// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
|
||||
/// data loss.
|
||||
///
|
||||
/// [`TcpStream::read`]: Read::read
|
||||
/// [`TcpStream`]: crate::net::TcpStream
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::io::BufReader;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f = File::open("log.txt")?;
|
||||
/// let mut reader = BufReader::new(f);
|
||||
///
|
||||
/// let mut line = String::new();
|
||||
/// let len = reader.read_line(&mut line)?;
|
||||
/// println!("First line is {} bytes long", len);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufReader<R> {
|
||||
inner: R,
|
||||
buf: Box<[u8]>,
|
||||
pos: usize,
|
||||
cap: usize,
|
||||
}
|
||||
|
||||
impl<R: Read> BufReader<R> {
|
||||
/// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB,
|
||||
/// but may change in the future.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufReader;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f = File::open("log.txt")?;
|
||||
/// let reader = BufReader::new(f);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: R) -> BufReader<R> {
|
||||
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `BufReader<R>` with the specified buffer capacity.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Creating a buffer with ten bytes of capacity:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufReader;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f = File::open("log.txt")?;
|
||||
/// let reader = BufReader::with_capacity(10, f);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
|
||||
unsafe {
|
||||
let mut buffer = Vec::with_capacity(capacity);
|
||||
buffer.set_len(capacity);
|
||||
inner.initializer().initialize(&mut buffer);
|
||||
BufReader { inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> BufReader<R> {
|
||||
/// Gets a reference to the underlying reader.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying reader.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufReader;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f1 = File::open("log.txt")?;
|
||||
/// let reader = BufReader::new(f1);
|
||||
///
|
||||
/// let f2 = reader.get_ref();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &R {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying reader.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying reader.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufReader;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f1 = File::open("log.txt")?;
|
||||
/// let mut reader = BufReader::new(f1);
|
||||
///
|
||||
/// let f2 = reader.get_mut();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut R {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
/// Returns a reference to the internally buffered data.
|
||||
///
|
||||
/// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty.
|
||||
///
|
||||
/// [`fill_buf`]: BufRead::fill_buf
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::{BufReader, BufRead};
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f = File::open("log.txt")?;
|
||||
/// let mut reader = BufReader::new(f);
|
||||
/// assert!(reader.buffer().is_empty());
|
||||
///
|
||||
/// if reader.fill_buf()?.len() > 0 {
|
||||
/// assert!(!reader.buffer().is_empty());
|
||||
/// }
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buf[self.pos..self.cap]
|
||||
}
|
||||
|
||||
/// Returns the number of bytes the internal buffer can hold at once.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::{BufReader, BufRead};
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f = File::open("log.txt")?;
|
||||
/// let mut reader = BufReader::new(f);
|
||||
///
|
||||
/// let capacity = reader.capacity();
|
||||
/// let buffer = reader.fill_buf()?;
|
||||
/// assert!(buffer.len() <= capacity);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "buffered_io_capacity", since = "1.46.0")]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.buf.len()
|
||||
}
|
||||
|
||||
/// Unwraps this `BufReader<R>`, returning the underlying reader.
|
||||
///
|
||||
/// Note that any leftover data in the internal buffer is lost. Therefore,
|
||||
/// a following read from the underlying reader may lead to data loss.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufReader;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let f1 = File::open("log.txt")?;
|
||||
/// let reader = BufReader::new(f1);
|
||||
///
|
||||
/// let f2 = reader.into_inner();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> R {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Invalidates all data in the internal buffer.
|
||||
#[inline]
|
||||
fn discard_buffer(&mut self) {
|
||||
self.pos = 0;
|
||||
self.cap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Seek> BufReader<R> {
|
||||
/// Seeks relative to the current position. If the new position lies within the buffer,
|
||||
/// the buffer will not be flushed, allowing for more efficient seeks.
|
||||
/// This method does not return the location of the underlying reader, so the caller
|
||||
/// must track this information themselves if it is required.
|
||||
#[unstable(feature = "bufreader_seek_relative", issue = "31100")]
|
||||
pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
|
||||
let pos = self.pos as u64;
|
||||
if offset < 0 {
|
||||
if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
|
||||
self.pos = new_pos as usize;
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
if let Some(new_pos) = pos.checked_add(offset as u64) {
|
||||
if new_pos <= self.cap as u64 {
|
||||
self.pos = new_pos as usize;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
self.seek(SeekFrom::Current(offset)).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Read> Read for BufReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
// If we don't have any buffered data and we're doing a massive read
|
||||
// (larger than our internal buffer), bypass our internal buffer
|
||||
// entirely.
|
||||
if self.pos == self.cap && buf.len() >= self.buf.len() {
|
||||
self.discard_buffer();
|
||||
return self.inner.read(buf);
|
||||
}
|
||||
let nread = {
|
||||
let mut rem = self.fill_buf()?;
|
||||
rem.read(buf)?
|
||||
};
|
||||
self.consume(nread);
|
||||
Ok(nread)
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
|
||||
if self.pos == self.cap && total_len >= self.buf.len() {
|
||||
self.discard_buffer();
|
||||
return self.inner.read_vectored(bufs);
|
||||
}
|
||||
let nread = {
|
||||
let mut rem = self.fill_buf()?;
|
||||
rem.read_vectored(bufs)?
|
||||
};
|
||||
self.consume(nread);
|
||||
Ok(nread)
|
||||
}
|
||||
|
||||
fn is_read_vectored(&self) -> bool {
|
||||
self.inner.is_read_vectored()
|
||||
}
|
||||
|
||||
// we can't skip unconditionally because of the large buffer case in read.
|
||||
unsafe fn initializer(&self) -> Initializer {
|
||||
self.inner.initializer()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Read> BufRead for BufReader<R> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
// If we've reached the end of our internal buffer then we need to fetch
|
||||
// some more data from the underlying reader.
|
||||
// Branch using `>=` instead of the more correct `==`
|
||||
// to tell the compiler that the pos..cap slice is always valid.
|
||||
if self.pos >= self.cap {
|
||||
debug_assert!(self.pos == self.cap);
|
||||
self.cap = self.inner.read(&mut self.buf)?;
|
||||
self.pos = 0;
|
||||
}
|
||||
Ok(&self.buf[self.pos..self.cap])
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.pos = cmp::min(self.pos + amt, self.cap);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R> fmt::Debug for BufReader<R>
|
||||
where
|
||||
R: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("BufReader")
|
||||
.field("reader", &self.inner)
|
||||
.field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Seek> Seek for BufReader<R> {
|
||||
/// Seek to an offset, in bytes, in the underlying reader.
|
||||
///
|
||||
/// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
|
||||
/// position the underlying reader would be at if the `BufReader<R>` had no
|
||||
/// internal buffer.
|
||||
///
|
||||
/// Seeking always discards the internal buffer, even if the seek position
|
||||
/// would otherwise fall within it. This guarantees that calling
|
||||
/// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader
|
||||
/// at the same position.
|
||||
///
|
||||
/// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
|
||||
///
|
||||
/// See [`std::io::Seek`] for more details.
|
||||
///
|
||||
/// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
|
||||
/// where `n` minus the internal buffer length overflows an `i64`, two
|
||||
/// seeks will be performed instead of one. If the second seek returns
|
||||
/// [`Err`], the underlying reader will be left at the same position it would
|
||||
/// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
|
||||
///
|
||||
/// [`std::io::Seek`]: Seek
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
let result: u64;
|
||||
if let SeekFrom::Current(n) = pos {
|
||||
let remainder = (self.cap - self.pos) as i64;
|
||||
// it should be safe to assume that remainder fits within an i64 as the alternative
|
||||
// means we managed to allocate 8 exbibytes and that's absurd.
|
||||
// But it's not out of the realm of possibility for some weird underlying reader to
|
||||
// support seeking by i64::MIN so we need to handle underflow when subtracting
|
||||
// remainder.
|
||||
if let Some(offset) = n.checked_sub(remainder) {
|
||||
result = self.inner.seek(SeekFrom::Current(offset))?;
|
||||
} else {
|
||||
// seek backwards by our remainder, and then by the offset
|
||||
self.inner.seek(SeekFrom::Current(-remainder))?;
|
||||
self.discard_buffer();
|
||||
result = self.inner.seek(SeekFrom::Current(n))?;
|
||||
}
|
||||
} else {
|
||||
// Seeking with Start/End doesn't care about our buffer length.
|
||||
result = self.inner.seek(pos)?;
|
||||
}
|
||||
self.discard_buffer();
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Returns the current seek position from the start of the stream.
|
||||
///
|
||||
/// The value returned is equivalent to `self.seek(SeekFrom::Current(0))`
|
||||
/// but does not flush the internal buffer. Due to this optimization the
|
||||
/// function does not guarantee that calling `.into_inner()` immediately
|
||||
/// afterwards will yield the underlying reader at the same position. Use
|
||||
/// [`BufReader::seek`] instead if you require that guarantee.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the position of the inner reader is smaller
|
||||
/// than the amount of buffered data. That can happen if the inner reader
|
||||
/// has an incorrect implementation of [`Seek::stream_position`], or if the
|
||||
/// position has gone out of sync due to calling [`Seek::seek`] directly on
|
||||
/// the underlying reader.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(seek_convenience)]
|
||||
/// use std::{
|
||||
/// io::{self, BufRead, BufReader, Seek},
|
||||
/// fs::File,
|
||||
/// };
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let mut f = BufReader::new(File::open("foo.txt")?);
|
||||
///
|
||||
/// let before = f.stream_position()?;
|
||||
/// f.read_line(&mut String::new())?;
|
||||
/// let after = f.stream_position()?;
|
||||
///
|
||||
/// println!("The first line was {} bytes long", after - before);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn stream_position(&mut self) -> io::Result<u64> {
|
||||
let remainder = (self.cap - self.pos) as u64;
|
||||
self.inner.stream_position().map(|pos| {
|
||||
pos.checked_sub(remainder).expect(
|
||||
"overflow when subtracting remaining buffer size from inner stream position",
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
387
library/std/src/io/buffered/bufwriter.rs
Normal file
387
library/std/src/io/buffered/bufwriter.rs
Normal file
@ -0,0 +1,387 @@
|
||||
use crate::fmt;
|
||||
use crate::io::{
|
||||
self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
|
||||
};
|
||||
|
||||
/// Wraps a writer and buffers its output.
|
||||
///
|
||||
/// It can be excessively inefficient to work directly with something that
|
||||
/// implements [`Write`]. For example, every call to
|
||||
/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
|
||||
/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
|
||||
/// writer in large, infrequent batches.
|
||||
///
|
||||
/// `BufWriter<W>` can improve the speed of programs that make *small* and
|
||||
/// *repeated* write calls to the same file or network socket. It does not
|
||||
/// help when writing very large amounts at once, or writing just one or a few
|
||||
/// times. It also provides no advantage when writing to a destination that is
|
||||
/// in memory, like a [`Vec`]<u8>`.
|
||||
///
|
||||
/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
|
||||
/// dropping will attempt to flush the contents of the buffer, any errors
|
||||
/// that happen in the process of dropping will be ignored. Calling [`flush`]
|
||||
/// ensures that the buffer is empty and thus dropping will not even attempt
|
||||
/// file operations.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Let's write the numbers one through ten to a [`TcpStream`]:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
|
||||
///
|
||||
/// for i in 0..10 {
|
||||
/// stream.write(&[i+1]).unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Because we're not buffering, we write each one in turn, incurring the
|
||||
/// overhead of a system call per byte written. We can fix this with a
|
||||
/// `BufWriter<W>`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// for i in 0..10 {
|
||||
/// stream.write(&[i+1]).unwrap();
|
||||
/// }
|
||||
/// stream.flush().unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
|
||||
/// together by the buffer and will all be written out in one system call when
|
||||
/// the `stream` is flushed.
|
||||
///
|
||||
/// [`TcpStream::write`]: Write::write
|
||||
/// [`TcpStream`]: crate::net::TcpStream
|
||||
/// [`flush`]: Write::flush
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufWriter<W: Write> {
|
||||
inner: Option<W>,
|
||||
buf: Vec<u8>,
|
||||
// #30888: If the inner writer panics in a call to write, we don't want to
|
||||
// write the buffered data a second time in BufWriter's destructor. This
|
||||
// flag tells the Drop impl if it should skip the flush.
|
||||
panicked: bool,
|
||||
}
|
||||
|
||||
impl<W: Write> BufWriter<W> {
|
||||
/// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
|
||||
/// but may change in the future.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: W) -> BufWriter<W> {
|
||||
BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `BufWriter<W>` with the specified buffer capacity.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Creating a buffer with a buffer of a hundred bytes.
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
|
||||
/// let mut buffer = BufWriter::with_capacity(100, stream);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
|
||||
BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
|
||||
}
|
||||
|
||||
/// Send data in our local buffer into the inner writer, looping as
|
||||
/// necessary until either it's all been sent or an error occurs.
|
||||
///
|
||||
/// Because all the data in the buffer has been reported to our owner as
|
||||
/// "successfully written" (by returning nonzero success values from
|
||||
/// `write`), any 0-length writes from `inner` must be reported as i/o
|
||||
/// errors from this method.
|
||||
pub(super) fn flush_buf(&mut self) -> io::Result<()> {
|
||||
/// Helper struct to ensure the buffer is updated after all the writes
|
||||
/// are complete. It tracks the number of written bytes and drains them
|
||||
/// all from the front of the buffer when dropped.
|
||||
struct BufGuard<'a> {
|
||||
buffer: &'a mut Vec<u8>,
|
||||
written: usize,
|
||||
}
|
||||
|
||||
impl<'a> BufGuard<'a> {
|
||||
fn new(buffer: &'a mut Vec<u8>) -> Self {
|
||||
Self { buffer, written: 0 }
|
||||
}
|
||||
|
||||
/// The unwritten part of the buffer
|
||||
fn remaining(&self) -> &[u8] {
|
||||
&self.buffer[self.written..]
|
||||
}
|
||||
|
||||
/// Flag some bytes as removed from the front of the buffer
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.written += amt;
|
||||
}
|
||||
|
||||
/// true if all of the bytes have been written
|
||||
fn done(&self) -> bool {
|
||||
self.written >= self.buffer.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BufGuard<'_> {
|
||||
fn drop(&mut self) {
|
||||
if self.written > 0 {
|
||||
self.buffer.drain(..self.written);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut guard = BufGuard::new(&mut self.buf);
|
||||
let inner = self.inner.as_mut().unwrap();
|
||||
while !guard.done() {
|
||||
self.panicked = true;
|
||||
let r = inner.write(guard.remaining());
|
||||
self.panicked = false;
|
||||
|
||||
match r {
|
||||
Ok(0) => {
|
||||
return Err(Error::new(
|
||||
ErrorKind::WriteZero,
|
||||
"failed to write the buffered data",
|
||||
));
|
||||
}
|
||||
Ok(n) => guard.consume(n),
|
||||
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Buffer some data without flushing it, regardless of the size of the
|
||||
/// data. Writes as much as possible without exceeding capacity. Returns
|
||||
/// the number of bytes written.
|
||||
pub(super) fn write_to_buf(&mut self, buf: &[u8]) -> usize {
|
||||
let available = self.buf.capacity() - self.buf.len();
|
||||
let amt_to_buffer = available.min(buf.len());
|
||||
self.buf.extend_from_slice(&buf[..amt_to_buffer]);
|
||||
amt_to_buffer
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying writer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // we can use reference just like buffer
|
||||
/// let reference = buffer.get_ref();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &W {
|
||||
self.inner.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying writer.
|
||||
///
|
||||
/// It is inadvisable to directly write to the underlying writer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // we can use reference just like buffer
|
||||
/// let reference = buffer.get_mut();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut W {
|
||||
self.inner.as_mut().unwrap()
|
||||
}
|
||||
|
||||
/// Returns a reference to the internally buffered data.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // See how many bytes are currently buffered
|
||||
/// let bytes_buffered = buf_writer.buffer().len();
|
||||
/// ```
|
||||
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
/// Returns the number of bytes the internal buffer can hold without flushing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // Check the capacity of the inner buffer
|
||||
/// let capacity = buf_writer.capacity();
|
||||
/// // Calculate how many bytes can be written without flushing
|
||||
/// let without_flush = capacity - buf_writer.buffer().len();
|
||||
/// ```
|
||||
#[stable(feature = "buffered_io_capacity", since = "1.46.0")]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.buf.capacity()
|
||||
}
|
||||
|
||||
/// Unwraps this `BufWriter<W>`, returning the underlying writer.
|
||||
///
|
||||
/// The buffer is written out before returning the writer.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // unwrap the TcpStream and flush the buffer
|
||||
/// let stream = buffer.into_inner().unwrap();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
|
||||
match self.flush_buf() {
|
||||
Err(e) => Err(IntoInnerError::new(self, e)),
|
||||
Ok(()) => Ok(self.inner.take().unwrap()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Write for BufWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
if self.buf.len() + buf.len() > self.buf.capacity() {
|
||||
self.flush_buf()?;
|
||||
}
|
||||
// FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
|
||||
if buf.len() >= self.buf.capacity() {
|
||||
self.panicked = true;
|
||||
let r = self.get_mut().write(buf);
|
||||
self.panicked = false;
|
||||
r
|
||||
} else {
|
||||
self.buf.extend_from_slice(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
// Normally, `write_all` just calls `write` in a loop. We can do better
|
||||
// by calling `self.get_mut().write_all()` directly, which avoids
|
||||
// round trips through the buffer in the event of a series of partial
|
||||
// writes in some circumstances.
|
||||
if self.buf.len() + buf.len() > self.buf.capacity() {
|
||||
self.flush_buf()?;
|
||||
}
|
||||
// FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
|
||||
if buf.len() >= self.buf.capacity() {
|
||||
self.panicked = true;
|
||||
let r = self.get_mut().write_all(buf);
|
||||
self.panicked = false;
|
||||
r
|
||||
} else {
|
||||
self.buf.extend_from_slice(buf);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
|
||||
if self.buf.len() + total_len > self.buf.capacity() {
|
||||
self.flush_buf()?;
|
||||
}
|
||||
// FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
|
||||
if total_len >= self.buf.capacity() {
|
||||
self.panicked = true;
|
||||
let r = self.get_mut().write_vectored(bufs);
|
||||
self.panicked = false;
|
||||
r
|
||||
} else {
|
||||
bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
|
||||
Ok(total_len)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
self.get_ref().is_write_vectored()
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.flush_buf().and_then(|()| self.get_mut().flush())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> fmt::Debug for BufWriter<W>
|
||||
where
|
||||
W: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("BufWriter")
|
||||
.field("writer", &self.inner.as_ref().unwrap())
|
||||
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write + Seek> Seek for BufWriter<W> {
|
||||
/// Seek to the offset, in bytes, in the underlying writer.
|
||||
///
|
||||
/// Seeking always writes out the internal buffer before seeking.
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
self.flush_buf()?;
|
||||
self.get_mut().seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Drop for BufWriter<W> {
|
||||
fn drop(&mut self) {
|
||||
if self.inner.is_some() && !self.panicked {
|
||||
// dtors should not panic, so we ignore a failed flush
|
||||
let _r = self.flush_buf();
|
||||
}
|
||||
}
|
||||
}
|
232
library/std/src/io/buffered/linewriter.rs
Normal file
232
library/std/src/io/buffered/linewriter.rs
Normal file
@ -0,0 +1,232 @@
|
||||
use crate::fmt;
|
||||
use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSlice, Write};
|
||||
|
||||
/// Wraps a writer and buffers output to it, flushing whenever a newline
|
||||
/// (`0x0a`, `'\n'`) is detected.
|
||||
///
|
||||
/// The [`BufWriter`] struct wraps a writer and buffers its output.
|
||||
/// But it only does this batched write when it goes out of scope, or when the
|
||||
/// internal buffer is full. Sometimes, you'd prefer to write each line as it's
|
||||
/// completed, rather than the entire buffer at once. Enter `LineWriter`. It
|
||||
/// does exactly that.
|
||||
///
|
||||
/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
|
||||
/// `LineWriter` goes out of scope or when its internal buffer is full.
|
||||
///
|
||||
/// If there's still a partial line in the buffer when the `LineWriter` is
|
||||
/// dropped, it will flush those contents.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// We can use `LineWriter` to write one line at a time, significantly
|
||||
/// reducing the number of actual writes to the file.
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::{self, File};
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let road_not_taken = b"I shall be telling this with a sigh
|
||||
/// Somewhere ages and ages hence:
|
||||
/// Two roads diverged in a wood, and I -
|
||||
/// I took the one less traveled by,
|
||||
/// And that has made all the difference.";
|
||||
///
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let mut file = LineWriter::new(file);
|
||||
///
|
||||
/// file.write_all(b"I shall be telling this with a sigh")?;
|
||||
///
|
||||
/// // No bytes are written until a newline is encountered (or
|
||||
/// // the internal buffer is filled).
|
||||
/// assert_eq!(fs::read_to_string("poem.txt")?, "");
|
||||
/// file.write_all(b"\n")?;
|
||||
/// assert_eq!(
|
||||
/// fs::read_to_string("poem.txt")?,
|
||||
/// "I shall be telling this with a sigh\n",
|
||||
/// );
|
||||
///
|
||||
/// // Write the rest of the poem.
|
||||
/// file.write_all(b"Somewhere ages and ages hence:
|
||||
/// Two roads diverged in a wood, and I -
|
||||
/// I took the one less traveled by,
|
||||
/// And that has made all the difference.")?;
|
||||
///
|
||||
/// // The last line of the poem doesn't end in a newline, so
|
||||
/// // we have to flush or drop the `LineWriter` to finish
|
||||
/// // writing.
|
||||
/// file.flush()?;
|
||||
///
|
||||
/// // Confirm the whole poem was written.
|
||||
/// assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct LineWriter<W: Write> {
|
||||
inner: BufWriter<W>,
|
||||
}
|
||||
|
||||
impl<W: Write> LineWriter<W> {
|
||||
/// Creates a new `LineWriter`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let file = LineWriter::new(file);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new(inner: W) -> LineWriter<W> {
|
||||
// Lines typically aren't that long, don't use a giant buffer
|
||||
LineWriter::with_capacity(1024, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `LineWriter` with a specified capacity for the internal
|
||||
/// buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let file = LineWriter::with_capacity(100, file);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
|
||||
LineWriter { inner: BufWriter::with_capacity(capacity, inner) }
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying writer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let file = LineWriter::new(file);
|
||||
///
|
||||
/// let reference = file.get_ref();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &W {
|
||||
self.inner.get_ref()
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying writer.
|
||||
///
|
||||
/// Caution must be taken when calling methods on the mutable reference
|
||||
/// returned as extra writes could corrupt the output stream.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let mut file = LineWriter::new(file);
|
||||
///
|
||||
/// // we can use reference just like file
|
||||
/// let reference = file.get_mut();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut W {
|
||||
self.inner.get_mut()
|
||||
}
|
||||
|
||||
/// Unwraps this `LineWriter`, returning the underlying writer.
|
||||
///
|
||||
/// The internal buffer is written out before returning the writer.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
///
|
||||
/// let writer: LineWriter<File> = LineWriter::new(file);
|
||||
///
|
||||
/// let file: File = writer.into_inner()?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
|
||||
self.inner.into_inner().map_err(|err| err.new_wrapped(|inner| LineWriter { inner }))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Write for LineWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
LineWriterShim::new(&mut self.inner).write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
LineWriterShim::new(&mut self.inner).write_vectored(bufs)
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
self.inner.is_write_vectored()
|
||||
}
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
LineWriterShim::new(&mut self.inner).write_all(buf)
|
||||
}
|
||||
|
||||
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
|
||||
LineWriterShim::new(&mut self.inner).write_all_vectored(bufs)
|
||||
}
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
|
||||
LineWriterShim::new(&mut self.inner).write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> fmt::Debug for LineWriter<W>
|
||||
where
|
||||
W: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("LineWriter")
|
||||
.field("writer", &self.get_ref())
|
||||
.field(
|
||||
"buffer",
|
||||
&format_args!("{}/{}", self.inner.buffer().len(), self.inner.capacity()),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
270
library/std/src/io/buffered/linewritershim.rs
Normal file
270
library/std/src/io/buffered/linewritershim.rs
Normal file
@ -0,0 +1,270 @@
|
||||
use crate::io::{self, BufWriter, IoSlice, Write};
|
||||
use crate::memchr;
|
||||
|
||||
/// Private helper struct for implementing the line-buffered writing logic.
|
||||
/// This shim temporarily wraps a BufWriter, and uses its internals to
|
||||
/// implement a line-buffered writer (specifically by using the internal
|
||||
/// methods like write_to_buf and flush_buf). In this way, a more
|
||||
/// efficient abstraction can be created than one that only had access to
|
||||
/// `write` and `flush`, without needlessly duplicating a lot of the
|
||||
/// implementation details of BufWriter. This also allows existing
|
||||
/// `BufWriters` to be temporarily given line-buffering logic; this is what
|
||||
/// enables Stdout to be alternately in line-buffered or block-buffered mode.
|
||||
#[derive(Debug)]
|
||||
pub struct LineWriterShim<'a, W: Write> {
|
||||
buffer: &'a mut BufWriter<W>,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> LineWriterShim<'a, W> {
|
||||
pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
|
||||
Self { buffer }
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the inner writer (that is, the writer
|
||||
/// wrapped by the BufWriter). Be careful with this writer, as writes to
|
||||
/// it will bypass the buffer.
|
||||
fn inner_mut(&mut self) -> &mut W {
|
||||
self.buffer.get_mut()
|
||||
}
|
||||
|
||||
/// Get the content currently buffered in self.buffer
|
||||
fn buffered(&self) -> &[u8] {
|
||||
self.buffer.buffer()
|
||||
}
|
||||
|
||||
/// Flush the buffer iff the last byte is a newline (indicating that an
|
||||
/// earlier write only succeeded partially, and we want to retry flushing
|
||||
/// the buffered line before continuing with a subsequent write)
|
||||
fn flush_if_completed_line(&mut self) -> io::Result<()> {
|
||||
match self.buffered().last().copied() {
|
||||
Some(b'\n') => self.buffer.flush_buf(),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Write for LineWriterShim<'a, W> {
|
||||
/// Write some data into this BufReader with line buffering. This means
|
||||
/// that, if any newlines are present in the data, the data up to the last
|
||||
/// newline is sent directly to the underlying writer, and data after it
|
||||
/// is buffered. Returns the number of bytes written.
|
||||
///
|
||||
/// This function operates on a "best effort basis"; in keeping with the
|
||||
/// convention of `Write::write`, it makes at most one attempt to write
|
||||
/// new data to the underlying writer. If that write only reports a partial
|
||||
/// success, the remaining data will be buffered.
|
||||
///
|
||||
/// Because this function attempts to send completed lines to the underlying
|
||||
/// writer, it will also flush the existing buffer if it ends with a
|
||||
/// newline, even if the incoming data does not contain any newlines.
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let newline_idx = match memchr::memrchr(b'\n', buf) {
|
||||
// If there are no new newlines (that is, if this write is less than
|
||||
// one line), just do a regular buffered write (which may flush if
|
||||
// we exceed the inner buffer's size)
|
||||
None => {
|
||||
self.flush_if_completed_line()?;
|
||||
return self.buffer.write(buf);
|
||||
}
|
||||
// Otherwise, arrange for the lines to be written directly to the
|
||||
// inner writer.
|
||||
Some(newline_idx) => newline_idx + 1,
|
||||
};
|
||||
|
||||
// Flush existing content to prepare for our write. We have to do this
|
||||
// before attempting to write `buf` in order to maintain consistency;
|
||||
// if we add `buf` to the buffer then try to flush it all at once,
|
||||
// we're obligated to return Ok(), which would mean suppressing any
|
||||
// errors that occur during flush.
|
||||
self.buffer.flush_buf()?;
|
||||
|
||||
// This is what we're going to try to write directly to the inner
|
||||
// writer. The rest will be buffered, if nothing goes wrong.
|
||||
let lines = &buf[..newline_idx];
|
||||
|
||||
// Write `lines` directly to the inner writer. In keeping with the
|
||||
// `write` convention, make at most one attempt to add new (unbuffered)
|
||||
// data. Because this write doesn't touch the BufWriter state directly,
|
||||
// and the buffer is known to be empty, we don't need to worry about
|
||||
// self.buffer.panicked here.
|
||||
let flushed = self.inner_mut().write(lines)?;
|
||||
|
||||
// If buffer returns Ok(0), propagate that to the caller without
|
||||
// doing additional buffering; otherwise we're just guaranteeing
|
||||
// an "ErrorKind::WriteZero" later.
|
||||
if flushed == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// Now that the write has succeeded, buffer the rest (or as much of
|
||||
// the rest as possible). If there were any unwritten newlines, we
|
||||
// only buffer out to the last unwritten newline that fits in the
|
||||
// buffer; this helps prevent flushing partial lines on subsequent
|
||||
// calls to LineWriterShim::write.
|
||||
|
||||
// Handle the cases in order of most-common to least-common, under
|
||||
// the presumption that most writes succeed in totality, and that most
|
||||
// writes are smaller than the buffer.
|
||||
// - Is this a partial line (ie, no newlines left in the unwritten tail)
|
||||
// - If not, does the data out to the last unwritten newline fit in
|
||||
// the buffer?
|
||||
// - If not, scan for the last newline that *does* fit in the buffer
|
||||
let tail = if flushed >= newline_idx {
|
||||
&buf[flushed..]
|
||||
} else if newline_idx - flushed <= self.buffer.capacity() {
|
||||
&buf[flushed..newline_idx]
|
||||
} else {
|
||||
let scan_area = &buf[flushed..];
|
||||
let scan_area = &scan_area[..self.buffer.capacity()];
|
||||
match memchr::memrchr(b'\n', scan_area) {
|
||||
Some(newline_idx) => &scan_area[..newline_idx + 1],
|
||||
None => scan_area,
|
||||
}
|
||||
};
|
||||
|
||||
let buffered = self.buffer.write_to_buf(tail);
|
||||
Ok(flushed + buffered)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.buffer.flush()
|
||||
}
|
||||
|
||||
/// Write some vectored data into this BufReader with line buffering. This
|
||||
/// means that, if any newlines are present in the data, the data up to
|
||||
/// and including the buffer containing the last newline is sent directly
|
||||
/// to the inner writer, and the data after it is buffered. Returns the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// This function operates on a "best effort basis"; in keeping with the
|
||||
/// convention of `Write::write`, it makes at most one attempt to write
|
||||
/// new data to the underlying writer.
|
||||
///
|
||||
/// Because this function attempts to send completed lines to the underlying
|
||||
/// writer, it will also flush the existing buffer if it contains any
|
||||
/// newlines.
|
||||
///
|
||||
/// Because sorting through an array of `IoSlice` can be a bit convoluted,
|
||||
/// This method differs from write in the following ways:
|
||||
///
|
||||
/// - It attempts to write the full content of all the buffers up to and
|
||||
/// including the one containing the last newline. This means that it
|
||||
/// may attempt to write a partial line, that buffer has data past the
|
||||
/// newline.
|
||||
/// - If the write only reports partial success, it does not attempt to
|
||||
/// find the precise location of the written bytes and buffer the rest.
|
||||
///
|
||||
/// If the underlying vector doesn't support vectored writing, we instead
|
||||
/// simply write the first non-empty buffer with `write`. This way, we
|
||||
/// get the benefits of more granular partial-line handling without losing
|
||||
/// anything in efficiency
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
// If there's no specialized behavior for write_vectored, just use
|
||||
// write. This has the benefit of more granular partial-line handling.
|
||||
if !self.is_write_vectored() {
|
||||
return match bufs.iter().find(|buf| !buf.is_empty()) {
|
||||
Some(buf) => self.write(buf),
|
||||
None => Ok(0),
|
||||
};
|
||||
}
|
||||
|
||||
// Find the buffer containing the last newline
|
||||
let last_newline_buf_idx = bufs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.rev()
|
||||
.find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i));
|
||||
|
||||
// If there are no new newlines (that is, if this write is less than
|
||||
// one line), just do a regular buffered write
|
||||
let last_newline_buf_idx = match last_newline_buf_idx {
|
||||
// No newlines; just do a normal buffered write
|
||||
None => {
|
||||
self.flush_if_completed_line()?;
|
||||
return self.buffer.write_vectored(bufs);
|
||||
}
|
||||
Some(i) => i,
|
||||
};
|
||||
|
||||
// Flush existing content to prepare for our write
|
||||
self.buffer.flush_buf()?;
|
||||
|
||||
// This is what we're going to try to write directly to the inner
|
||||
// writer. The rest will be buffered, if nothing goes wrong.
|
||||
let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1);
|
||||
|
||||
// Write `lines` directly to the inner writer. In keeping with the
|
||||
// `write` convention, make at most one attempt to add new (unbuffered)
|
||||
// data. Because this write doesn't touch the BufWriter state directly,
|
||||
// and the buffer is known to be empty, we don't need to worry about
|
||||
// self.panicked here.
|
||||
let flushed = self.inner_mut().write_vectored(lines)?;
|
||||
|
||||
// If inner returns Ok(0), propagate that to the caller without
|
||||
// doing additional buffering; otherwise we're just guaranteeing
|
||||
// an "ErrorKind::WriteZero" later.
|
||||
if flushed == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// Don't try to reconstruct the exact amount written; just bail
|
||||
// in the event of a partial write
|
||||
let lines_len = lines.iter().map(|buf| buf.len()).sum();
|
||||
if flushed < lines_len {
|
||||
return Ok(flushed);
|
||||
}
|
||||
|
||||
// Now that the write has succeeded, buffer the rest (or as much of the
|
||||
// rest as possible)
|
||||
let buffered: usize = tail
|
||||
.iter()
|
||||
.filter(|buf| !buf.is_empty())
|
||||
.map(|buf| self.buffer.write_to_buf(buf))
|
||||
.take_while(|&n| n > 0)
|
||||
.sum();
|
||||
|
||||
Ok(flushed + buffered)
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
self.buffer.is_write_vectored()
|
||||
}
|
||||
|
||||
/// Write some data into this BufReader with line buffering. This means
|
||||
/// that, if any newlines are present in the data, the data up to the last
|
||||
/// newline is sent directly to the underlying writer, and data after it
|
||||
/// is buffered.
|
||||
///
|
||||
/// Because this function attempts to send completed lines to the underlying
|
||||
/// writer, it will also flush the existing buffer if it contains any
|
||||
/// newlines, even if the incoming data does not contain any newlines.
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
match memchr::memrchr(b'\n', buf) {
|
||||
// If there are no new newlines (that is, if this write is less than
|
||||
// one line), just do a regular buffered write (which may flush if
|
||||
// we exceed the inner buffer's size)
|
||||
None => {
|
||||
self.flush_if_completed_line()?;
|
||||
self.buffer.write_all(buf)
|
||||
}
|
||||
Some(newline_idx) => {
|
||||
let (lines, tail) = buf.split_at(newline_idx + 1);
|
||||
|
||||
if self.buffered().is_empty() {
|
||||
self.inner_mut().write_all(lines)?;
|
||||
} else {
|
||||
// If there is any buffered data, we add the incoming lines
|
||||
// to that buffer before flushing, which saves us at least
|
||||
// one write call. We can't really do this with `write`,
|
||||
// since we can't do this *and* not suppress errors *and*
|
||||
// report a consistent state to the caller in a return
|
||||
// value, but here in write_all it's fine.
|
||||
self.buffer.write_all(lines)?;
|
||||
self.buffer.flush_buf()?;
|
||||
}
|
||||
|
||||
self.buffer.write_all(tail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
151
library/std/src/io/buffered/mod.rs
Normal file
151
library/std/src/io/buffered/mod.rs
Normal file
@ -0,0 +1,151 @@
|
||||
//! Buffering wrappers for I/O traits
|
||||
|
||||
mod bufreader;
|
||||
mod bufwriter;
|
||||
mod linewriter;
|
||||
mod linewritershim;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::error;
|
||||
use crate::fmt;
|
||||
use crate::io::Error;
|
||||
|
||||
pub use bufreader::BufReader;
|
||||
pub use bufwriter::BufWriter;
|
||||
pub use linewriter::LineWriter;
|
||||
use linewritershim::LineWriterShim;
|
||||
|
||||
/// An error returned by [`BufWriter::into_inner`] which combines an error that
|
||||
/// happened while writing out the buffer, and the buffered writer object
|
||||
/// which may be used to recover from the condition.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // do stuff with the stream
|
||||
///
|
||||
/// // we want to get our `TcpStream` back, so let's try:
|
||||
///
|
||||
/// let stream = match stream.into_inner() {
|
||||
/// Ok(s) => s,
|
||||
/// Err(e) => {
|
||||
/// // Here, e is an IntoInnerError
|
||||
/// panic!("An error occurred");
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoInnerError<W>(W, Error);
|
||||
|
||||
impl<W> IntoInnerError<W> {
|
||||
/// Construct a new IntoInnerError
|
||||
fn new(writer: W, error: Error) -> Self {
|
||||
Self(writer, error)
|
||||
}
|
||||
|
||||
/// Helper to construct a new IntoInnerError; intended to help with
|
||||
/// adapters that wrap other adapters
|
||||
fn new_wrapped<W2>(self, f: impl FnOnce(W) -> W2) -> IntoInnerError<W2> {
|
||||
let Self(writer, error) = self;
|
||||
IntoInnerError::new(f(writer), error)
|
||||
}
|
||||
|
||||
/// Returns the error which caused the call to [`BufWriter::into_inner()`]
|
||||
/// to fail.
|
||||
///
|
||||
/// This error was returned when attempting to write the internal buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // do stuff with the stream
|
||||
///
|
||||
/// // we want to get our `TcpStream` back, so let's try:
|
||||
///
|
||||
/// let stream = match stream.into_inner() {
|
||||
/// Ok(s) => s,
|
||||
/// Err(e) => {
|
||||
/// // Here, e is an IntoInnerError, let's log the inner error.
|
||||
/// //
|
||||
/// // We'll just 'log' to stdout for this example.
|
||||
/// println!("{}", e.error());
|
||||
///
|
||||
/// panic!("An unexpected error occurred.");
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn error(&self) -> &Error {
|
||||
&self.1
|
||||
}
|
||||
|
||||
/// Returns the buffered writer instance which generated the error.
|
||||
///
|
||||
/// The returned object can be used for error recovery, such as
|
||||
/// re-inspecting the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // do stuff with the stream
|
||||
///
|
||||
/// // we want to get our `TcpStream` back, so let's try:
|
||||
///
|
||||
/// let stream = match stream.into_inner() {
|
||||
/// Ok(s) => s,
|
||||
/// Err(e) => {
|
||||
/// // Here, e is an IntoInnerError, let's re-examine the buffer:
|
||||
/// let buffer = e.into_inner();
|
||||
///
|
||||
/// // do stuff to try to recover
|
||||
///
|
||||
/// // afterwards, let's just return the stream
|
||||
/// buffer.into_inner().unwrap()
|
||||
/// }
|
||||
/// };
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> W {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W> From<IntoInnerError<W>> for Error {
|
||||
fn from(iie: IntoInnerError<W>) -> Error {
|
||||
iie.1
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
fn description(&self) -> &str {
|
||||
error::Error::description(self.error())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W> fmt::Display for IntoInnerError<W> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.error().fmt(f)
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::mem;
|
||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||
use crate::sys::cloudabi::abi;
|
||||
@ -12,7 +11,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
pub struct Condvar {
|
||||
condvar: UnsafeCell<AtomicU32>,
|
||||
condvar: AtomicU32,
|
||||
}
|
||||
|
||||
pub type MovableCondvar = Condvar;
|
||||
@ -20,29 +19,28 @@ pub type MovableCondvar = Condvar;
|
||||
unsafe impl Send for Condvar {}
|
||||
unsafe impl Sync for Condvar {}
|
||||
|
||||
const NEW: Condvar =
|
||||
Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
|
||||
|
||||
impl Condvar {
|
||||
pub const fn new() -> Condvar {
|
||||
NEW
|
||||
Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
|
||||
}
|
||||
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
pub unsafe fn notify_one(&self) {
|
||||
let condvar = self.condvar.get();
|
||||
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
||||
let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
|
||||
if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
||||
let ret = abi::condvar_signal(
|
||||
&self.condvar as *const AtomicU32 as *mut abi::condvar,
|
||||
abi::scope::PRIVATE,
|
||||
1,
|
||||
);
|
||||
assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn notify_all(&self) {
|
||||
let condvar = self.condvar.get();
|
||||
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
||||
if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
||||
let ret = abi::condvar_signal(
|
||||
condvar as *mut abi::condvar,
|
||||
&self.condvar as *const AtomicU32 as *mut abi::condvar,
|
||||
abi::scope::PRIVATE,
|
||||
abi::nthreads::MAX,
|
||||
);
|
||||
@ -53,20 +51,19 @@ impl Condvar {
|
||||
pub unsafe fn wait(&self, mutex: &Mutex) {
|
||||
let mutex = mutex::raw(mutex);
|
||||
assert_eq!(
|
||||
(*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
"This lock is not write-locked by this thread"
|
||||
);
|
||||
|
||||
// Call into the kernel to wait on the condition variable.
|
||||
let condvar = self.condvar.get();
|
||||
let subscription = abi::subscription {
|
||||
type_: abi::eventtype::CONDVAR,
|
||||
union: abi::subscription_union {
|
||||
condvar: abi::subscription_condvar {
|
||||
condvar: condvar as *mut abi::condvar,
|
||||
condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
|
||||
condvar_scope: abi::scope::PRIVATE,
|
||||
lock: mutex as *mut abi::lock,
|
||||
lock: mutex as *const AtomicU32 as *mut abi::lock,
|
||||
lock_scope: abi::scope::PRIVATE,
|
||||
},
|
||||
},
|
||||
@ -86,13 +83,12 @@ impl Condvar {
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
let mutex = mutex::raw(mutex);
|
||||
assert_eq!(
|
||||
(*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
"This lock is not write-locked by this thread"
|
||||
);
|
||||
|
||||
// Call into the kernel to wait on the condition variable.
|
||||
let condvar = self.condvar.get();
|
||||
let timeout =
|
||||
checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
|
||||
let subscriptions = [
|
||||
@ -100,9 +96,9 @@ impl Condvar {
|
||||
type_: abi::eventtype::CONDVAR,
|
||||
union: abi::subscription_union {
|
||||
condvar: abi::subscription_condvar {
|
||||
condvar: condvar as *mut abi::condvar,
|
||||
condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
|
||||
condvar_scope: abi::scope::PRIVATE,
|
||||
lock: mutex as *mut abi::lock,
|
||||
lock: mutex as *const AtomicU32 as *mut abi::lock,
|
||||
lock_scope: abi::scope::PRIVATE,
|
||||
},
|
||||
},
|
||||
@ -124,7 +120,7 @@ impl Condvar {
|
||||
let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
|
||||
let ret = abi::poll(
|
||||
subscriptions.as_ptr(),
|
||||
mem::MaybeUninit::first_ptr_mut(&mut events),
|
||||
mem::MaybeUninit::slice_as_mut_ptr(&mut events),
|
||||
2,
|
||||
nevents.as_mut_ptr(),
|
||||
);
|
||||
@ -144,9 +140,8 @@ impl Condvar {
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {
|
||||
let condvar = self.condvar.get();
|
||||
assert_eq!(
|
||||
(*condvar).load(Ordering::Relaxed),
|
||||
self.condvar.load(Ordering::Relaxed),
|
||||
abi::CONDVAR_HAS_NO_WAITERS.0,
|
||||
"Attempted to destroy a condition variable with blocked threads"
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::cell::Cell;
|
||||
use crate::mem;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||
@ -17,7 +17,7 @@ pub struct Mutex(RWLock);
|
||||
|
||||
pub type MovableMutex = Mutex;
|
||||
|
||||
pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
|
||||
pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
|
||||
rwlock::raw(&m.0)
|
||||
}
|
||||
|
||||
@ -50,28 +50,23 @@ impl Mutex {
|
||||
}
|
||||
|
||||
pub struct ReentrantMutex {
|
||||
lock: UnsafeCell<MaybeUninit<AtomicU32>>,
|
||||
recursion: UnsafeCell<MaybeUninit<u32>>,
|
||||
lock: AtomicU32,
|
||||
recursion: Cell<u32>,
|
||||
}
|
||||
|
||||
unsafe impl Send for ReentrantMutex {}
|
||||
unsafe impl Sync for ReentrantMutex {}
|
||||
|
||||
impl ReentrantMutex {
|
||||
pub const unsafe fn uninitialized() -> ReentrantMutex {
|
||||
ReentrantMutex {
|
||||
lock: UnsafeCell::new(MaybeUninit::uninit()),
|
||||
recursion: UnsafeCell::new(MaybeUninit::uninit()),
|
||||
}
|
||||
ReentrantMutex { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), recursion: Cell::new(0) }
|
||||
}
|
||||
|
||||
pub unsafe fn init(&self) {
|
||||
*self.lock.get() = MaybeUninit::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
|
||||
*self.recursion.get() = MaybeUninit::new(0);
|
||||
}
|
||||
pub unsafe fn init(&self) {}
|
||||
|
||||
pub unsafe fn try_lock(&self) -> bool {
|
||||
// Attempt to acquire the lock.
|
||||
let lock = (*self.lock.get()).as_mut_ptr();
|
||||
let recursion = (*self.recursion.get()).as_mut_ptr();
|
||||
if let Err(old) = (*lock).compare_exchange(
|
||||
if let Err(old) = self.lock.compare_exchange(
|
||||
abi::LOCK_UNLOCKED.0,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
Ordering::Acquire,
|
||||
@ -80,14 +75,14 @@ impl ReentrantMutex {
|
||||
// If we fail to acquire the lock, it may be the case
|
||||
// that we've already acquired it and may need to recurse.
|
||||
if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
|
||||
*recursion += 1;
|
||||
self.recursion.set(self.recursion.get() + 1);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
// Success.
|
||||
assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
|
||||
assert_eq!(self.recursion.get(), 0, "Mutex has invalid recursion count");
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -95,7 +90,7 @@ impl ReentrantMutex {
|
||||
pub unsafe fn lock(&self) {
|
||||
if !self.try_lock() {
|
||||
// Call into the kernel to acquire a write lock.
|
||||
let lock = self.lock.get();
|
||||
let lock = &self.lock as *const AtomicU32;
|
||||
let subscription = abi::subscription {
|
||||
type_: abi::eventtype::LOCK_WRLOCK,
|
||||
union: abi::subscription_union {
|
||||
@ -116,17 +111,17 @@ impl ReentrantMutex {
|
||||
}
|
||||
|
||||
pub unsafe fn unlock(&self) {
|
||||
let lock = (*self.lock.get()).as_mut_ptr();
|
||||
let recursion = (*self.recursion.get()).as_mut_ptr();
|
||||
assert_eq!(
|
||||
(*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
"This mutex is locked by a different thread"
|
||||
);
|
||||
|
||||
if *recursion > 0 {
|
||||
*recursion -= 1;
|
||||
} else if !(*lock)
|
||||
let r = self.recursion.get();
|
||||
if r > 0 {
|
||||
self.recursion.set(r - 1);
|
||||
} else if !self
|
||||
.lock
|
||||
.compare_exchange(
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
abi::LOCK_UNLOCKED.0,
|
||||
@ -137,19 +132,20 @@ impl ReentrantMutex {
|
||||
{
|
||||
// Lock is managed by kernelspace. Call into the kernel
|
||||
// to unblock waiting threads.
|
||||
let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
|
||||
let ret = abi::lock_unlock(
|
||||
&self.lock as *const AtomicU32 as *mut abi::lock,
|
||||
abi::scope::PRIVATE,
|
||||
);
|
||||
assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {
|
||||
let lock = (*self.lock.get()).as_mut_ptr();
|
||||
let recursion = (*self.recursion.get()).as_mut_ptr();
|
||||
assert_eq!(
|
||||
(*lock).load(Ordering::Relaxed),
|
||||
self.lock.load(Ordering::Relaxed),
|
||||
abi::LOCK_UNLOCKED.0,
|
||||
"Attempted to destroy locked mutex"
|
||||
);
|
||||
assert_eq!(*recursion, 0, "Recursion counter invalid");
|
||||
assert_eq!(self.recursion.get(), 0, "Recursion counter invalid");
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::mem;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||
@ -13,28 +12,25 @@ extern "C" {
|
||||
static mut RDLOCKS_ACQUIRED: u32 = 0;
|
||||
|
||||
pub struct RWLock {
|
||||
lock: UnsafeCell<AtomicU32>,
|
||||
lock: AtomicU32,
|
||||
}
|
||||
|
||||
pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
|
||||
r.lock.get()
|
||||
pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
|
||||
&r.lock
|
||||
}
|
||||
|
||||
unsafe impl Send for RWLock {}
|
||||
unsafe impl Sync for RWLock {}
|
||||
|
||||
const NEW: RWLock = RWLock { lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)) };
|
||||
|
||||
impl RWLock {
|
||||
pub const fn new() -> RWLock {
|
||||
NEW
|
||||
RWLock { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0) }
|
||||
}
|
||||
|
||||
pub unsafe fn try_read(&self) -> bool {
|
||||
let lock = self.lock.get();
|
||||
let mut old = abi::LOCK_UNLOCKED.0;
|
||||
while let Err(cur) =
|
||||
(*lock).compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
|
||||
self.lock.compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
|
||||
{
|
||||
if (cur & abi::LOCK_WRLOCKED.0) != 0 {
|
||||
// Another thread already has a write lock.
|
||||
@ -61,12 +57,11 @@ impl RWLock {
|
||||
pub unsafe fn read(&self) {
|
||||
if !self.try_read() {
|
||||
// Call into the kernel to acquire a read lock.
|
||||
let lock = self.lock.get();
|
||||
let subscription = abi::subscription {
|
||||
type_: abi::eventtype::LOCK_RDLOCK,
|
||||
union: abi::subscription_union {
|
||||
lock: abi::subscription_lock {
|
||||
lock: lock as *mut abi::lock,
|
||||
lock: &self.lock as *const AtomicU32 as *mut abi::lock,
|
||||
lock_scope: abi::scope::PRIVATE,
|
||||
},
|
||||
},
|
||||
@ -96,11 +91,10 @@ impl RWLock {
|
||||
assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
|
||||
let mut old = 1;
|
||||
loop {
|
||||
let lock = self.lock.get();
|
||||
if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
|
||||
// Last read lock while threads are waiting. Attempt to upgrade
|
||||
// to a write lock before calling into the kernel to unlock.
|
||||
if let Err(cur) = (*lock).compare_exchange_weak(
|
||||
if let Err(cur) = self.lock.compare_exchange_weak(
|
||||
old,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
|
||||
Ordering::Acquire,
|
||||
@ -109,7 +103,10 @@ impl RWLock {
|
||||
old = cur;
|
||||
} else {
|
||||
// Call into the kernel to unlock.
|
||||
let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
|
||||
let ret = abi::lock_unlock(
|
||||
&self.lock as *const AtomicU32 as *mut abi::lock,
|
||||
abi::scope::PRIVATE,
|
||||
);
|
||||
assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
|
||||
break;
|
||||
}
|
||||
@ -122,7 +119,7 @@ impl RWLock {
|
||||
0,
|
||||
"Attempted to read-unlock a write-locked rwlock"
|
||||
);
|
||||
if let Err(cur) = (*lock).compare_exchange_weak(
|
||||
if let Err(cur) = self.lock.compare_exchange_weak(
|
||||
old,
|
||||
old - 1,
|
||||
Ordering::Acquire,
|
||||
@ -140,8 +137,7 @@ impl RWLock {
|
||||
|
||||
pub unsafe fn try_write(&self) -> bool {
|
||||
// Attempt to acquire the lock.
|
||||
let lock = self.lock.get();
|
||||
if let Err(old) = (*lock).compare_exchange(
|
||||
if let Err(old) = self.lock.compare_exchange(
|
||||
abi::LOCK_UNLOCKED.0,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
Ordering::Acquire,
|
||||
@ -163,12 +159,11 @@ impl RWLock {
|
||||
pub unsafe fn write(&self) {
|
||||
if !self.try_write() {
|
||||
// Call into the kernel to acquire a write lock.
|
||||
let lock = self.lock.get();
|
||||
let subscription = abi::subscription {
|
||||
type_: abi::eventtype::LOCK_WRLOCK,
|
||||
union: abi::subscription_union {
|
||||
lock: abi::subscription_lock {
|
||||
lock: lock as *mut abi::lock,
|
||||
lock: &self.lock as *const AtomicU32 as *mut abi::lock,
|
||||
lock_scope: abi::scope::PRIVATE,
|
||||
},
|
||||
},
|
||||
@ -184,14 +179,14 @@ impl RWLock {
|
||||
}
|
||||
|
||||
pub unsafe fn write_unlock(&self) {
|
||||
let lock = self.lock.get();
|
||||
assert_eq!(
|
||||
(*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
"This rwlock is not write-locked by this thread"
|
||||
);
|
||||
|
||||
if !(*lock)
|
||||
if !self
|
||||
.lock
|
||||
.compare_exchange(
|
||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||
abi::LOCK_UNLOCKED.0,
|
||||
@ -202,15 +197,17 @@ impl RWLock {
|
||||
{
|
||||
// Lock is managed by kernelspace. Call into the kernel
|
||||
// to unblock waiting threads.
|
||||
let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
|
||||
let ret = abi::lock_unlock(
|
||||
&self.lock as *const AtomicU32 as *mut abi::lock,
|
||||
abi::scope::PRIVATE,
|
||||
);
|
||||
assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&self) {
|
||||
let lock = self.lock.get();
|
||||
assert_eq!(
|
||||
(*lock).load(Ordering::Relaxed),
|
||||
self.lock.load(Ordering::Relaxed),
|
||||
abi::LOCK_UNLOCKED.0,
|
||||
"Attempted to destroy locked rwlock"
|
||||
);
|
||||
|
@ -470,7 +470,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
&mut environ
|
||||
}
|
||||
|
||||
pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
|
||||
pub unsafe fn env_lock() -> StaticMutexGuard {
|
||||
// It is UB to attempt to acquire this mutex reentrantly!
|
||||
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
||||
ENV_LOCK.lock()
|
||||
|
@ -212,7 +212,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
&mut environ
|
||||
}
|
||||
|
||||
pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
|
||||
pub unsafe fn env_lock() -> StaticMutexGuard {
|
||||
// It is UB to attempt to acquire this mutex reentrantly!
|
||||
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
||||
ENV_LOCK.lock()
|
||||
|
17
library/std/src/sys/wasm/futex_atomics.rs
Normal file
17
library/std/src/sys/wasm/futex_atomics.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use crate::arch::wasm32;
|
||||
use crate::convert::TryInto;
|
||||
use crate::sync::atomic::AtomicI32;
|
||||
use crate::time::Duration;
|
||||
|
||||
pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
|
||||
let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
|
||||
unsafe {
|
||||
wasm32::memory_atomic_wait32(futex as *const AtomicI32 as *mut i32, expected, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn futex_wake(futex: &AtomicI32) {
|
||||
unsafe {
|
||||
wasm32::memory_atomic_notify(futex as *const AtomicI32 as *mut i32, 1);
|
||||
}
|
||||
}
|
@ -55,6 +55,8 @@ cfg_if::cfg_if! {
|
||||
pub mod mutex;
|
||||
#[path = "rwlock_atomics.rs"]
|
||||
pub mod rwlock;
|
||||
#[path = "futex_atomics.rs"]
|
||||
pub mod futex;
|
||||
} else {
|
||||
#[path = "../unsupported/condvar.rs"]
|
||||
pub mod condvar;
|
||||
|
@ -8,27 +8,15 @@ use crate::io;
|
||||
use crate::io::prelude::*;
|
||||
use crate::path::{self, Path, PathBuf};
|
||||
use crate::sync::atomic::{self, Ordering};
|
||||
use crate::sys::mutex::Mutex;
|
||||
use crate::sys_common::mutex::StaticMutex;
|
||||
|
||||
/// Max number of frames to print.
|
||||
const MAX_NB_FRAMES: usize = 100;
|
||||
|
||||
pub fn lock() -> impl Drop {
|
||||
struct Guard;
|
||||
static LOCK: Mutex = Mutex::new();
|
||||
|
||||
impl Drop for Guard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
LOCK.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
LOCK.lock();
|
||||
Guard
|
||||
}
|
||||
// SAFETY: Don't attempt to lock this reentrantly.
|
||||
pub unsafe fn lock() -> impl Drop {
|
||||
static LOCK: StaticMutex = StaticMutex::new();
|
||||
LOCK.lock()
|
||||
}
|
||||
|
||||
/// Prints the current backtrace.
|
||||
|
@ -3,8 +3,7 @@ use crate::sys::mutex as imp;
|
||||
/// An OS-based mutual exclusion lock, meant for use in static variables.
|
||||
///
|
||||
/// This mutex has a const constructor ([`StaticMutex::new`]), does not
|
||||
/// implement `Drop` to cleanup resources, and causes UB when moved or used
|
||||
/// reentrantly.
|
||||
/// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
|
||||
///
|
||||
/// This mutex does not implement poisoning.
|
||||
///
|
||||
@ -16,11 +15,6 @@ unsafe impl Sync for StaticMutex {}
|
||||
|
||||
impl StaticMutex {
|
||||
/// Creates a new mutex for use.
|
||||
///
|
||||
/// Behavior is undefined if the mutex is moved after it is
|
||||
/// first used with any of the functions below.
|
||||
/// Also, the behavior is undefined if this mutex is ever used reentrantly,
|
||||
/// i.e., `lock` is called by the thread currently holding the lock.
|
||||
pub const fn new() -> Self {
|
||||
Self(imp::Mutex::new())
|
||||
}
|
||||
@ -28,19 +22,19 @@ impl StaticMutex {
|
||||
/// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
|
||||
/// will be unlocked.
|
||||
///
|
||||
/// It is undefined behaviour to call this function while locked, or if the
|
||||
/// mutex has been moved since the last time this was called.
|
||||
/// It is undefined behaviour to call this function while locked by the
|
||||
/// same thread.
|
||||
#[inline]
|
||||
pub unsafe fn lock(&self) -> StaticMutexGuard<'_> {
|
||||
pub unsafe fn lock(&'static self) -> StaticMutexGuard {
|
||||
self.0.lock();
|
||||
StaticMutexGuard(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct StaticMutexGuard<'a>(&'a imp::Mutex);
|
||||
pub struct StaticMutexGuard(&'static imp::Mutex);
|
||||
|
||||
impl Drop for StaticMutexGuard<'_> {
|
||||
impl Drop for StaticMutexGuard {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
@ -1,5 +1,9 @@
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_os = "linux", target_os = "android"))] {
|
||||
if #[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
all(target_arch = "wasm32", target_feature = "atomics"),
|
||||
))] {
|
||||
mod futex;
|
||||
pub use futex::Parker;
|
||||
} else {
|
||||
|
@ -201,6 +201,37 @@ impl Cfg {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to simplify this cfg by assuming that `assume` is already known to be true, will
|
||||
/// return `None` if simplification managed to completely eliminate any requirements from this
|
||||
/// `Cfg`.
|
||||
///
|
||||
/// See `tests::test_simplify_with` for examples.
|
||||
pub(crate) fn simplify_with(&self, assume: &Cfg) -> Option<Cfg> {
|
||||
if self == assume {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Cfg::All(a) = self {
|
||||
let mut sub_cfgs: Vec<Cfg> = if let Cfg::All(b) = assume {
|
||||
a.iter().filter(|a| !b.contains(a)).cloned().collect()
|
||||
} else {
|
||||
a.iter().filter(|&a| a != assume).cloned().collect()
|
||||
};
|
||||
let len = sub_cfgs.len();
|
||||
return match len {
|
||||
0 => None,
|
||||
1 => sub_cfgs.pop(),
|
||||
_ => Some(Cfg::All(sub_cfgs)),
|
||||
};
|
||||
} else if let Cfg::All(b) = assume {
|
||||
if b.contains(self) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Not for Cfg {
|
||||
|
@ -433,3 +433,39 @@ fn test_render_long_html() {
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simplify_with() {
|
||||
// This is a tiny subset of things that could be simplified, but it likely covers 90% of
|
||||
// real world usecases well.
|
||||
with_default_session_globals(|| {
|
||||
let foo = word_cfg("foo");
|
||||
let bar = word_cfg("bar");
|
||||
let baz = word_cfg("baz");
|
||||
let quux = word_cfg("quux");
|
||||
|
||||
let foobar = Cfg::All(vec![foo.clone(), bar.clone()]);
|
||||
let barbaz = Cfg::All(vec![bar.clone(), baz.clone()]);
|
||||
let foobarbaz = Cfg::All(vec![foo.clone(), bar.clone(), baz.clone()]);
|
||||
let bazquux = Cfg::All(vec![baz.clone(), quux.clone()]);
|
||||
|
||||
// Unrelated cfgs don't affect each other
|
||||
assert_eq!(foo.simplify_with(&bar).as_ref(), Some(&foo));
|
||||
assert_eq!(foobar.simplify_with(&bazquux).as_ref(), Some(&foobar));
|
||||
|
||||
// Identical cfgs are eliminated
|
||||
assert_eq!(foo.simplify_with(&foo), None);
|
||||
assert_eq!(foobar.simplify_with(&foobar), None);
|
||||
|
||||
// Multiple cfgs eliminate a single assumed cfg
|
||||
assert_eq!(foobar.simplify_with(&foo).as_ref(), Some(&bar));
|
||||
assert_eq!(foobar.simplify_with(&bar).as_ref(), Some(&foo));
|
||||
|
||||
// A single cfg is eliminated by multiple assumed cfg containing it
|
||||
assert_eq!(foo.simplify_with(&foobar), None);
|
||||
|
||||
// Multiple cfgs eliminate the matching subset of multiple assumed cfg
|
||||
assert_eq!(foobar.simplify_with(&barbaz).as_ref(), Some(&foo));
|
||||
assert_eq!(foobar.simplify_with(&foobarbaz), None);
|
||||
});
|
||||
}
|
||||
|
@ -1763,11 +1763,11 @@ crate fn shorten(s: String) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) {
|
||||
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
|
||||
if let Some(ref name) = item.name {
|
||||
info!("Documenting {}", name);
|
||||
}
|
||||
document_stability(w, cx, item, false);
|
||||
document_stability(w, cx, item, false, parent);
|
||||
document_full(w, item, cx, "", false);
|
||||
}
|
||||
|
||||
@ -1851,8 +1851,14 @@ fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str,
|
||||
}
|
||||
}
|
||||
|
||||
fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) {
|
||||
let stabilities = short_stability(item, cx);
|
||||
fn document_stability(
|
||||
w: &mut Buffer,
|
||||
cx: &Context,
|
||||
item: &clean::Item,
|
||||
is_hidden: bool,
|
||||
parent: Option<&clean::Item>,
|
||||
) {
|
||||
let stabilities = short_stability(item, cx, parent);
|
||||
if !stabilities.is_empty() {
|
||||
write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" });
|
||||
for stability in stabilities {
|
||||
@ -1952,7 +1958,7 @@ pub fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering {
|
||||
}
|
||||
|
||||
fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) {
|
||||
document(w, cx, item);
|
||||
document(w, cx, item, None);
|
||||
|
||||
let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
|
||||
|
||||
@ -2111,7 +2117,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
|
||||
<td class='docblock-short'>{stab_tags}{docs}</td>\
|
||||
</tr>",
|
||||
name = *myitem.name.as_ref().unwrap(),
|
||||
stab_tags = stability_tags(myitem),
|
||||
stab_tags = stability_tags(myitem, item),
|
||||
docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
|
||||
class = myitem.type_(),
|
||||
add = add,
|
||||
@ -2135,7 +2141,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
|
||||
|
||||
/// Render the stability and deprecation tags that are displayed in the item's summary at the
|
||||
/// module level.
|
||||
fn stability_tags(item: &clean::Item) -> String {
|
||||
fn stability_tags(item: &clean::Item, parent: &clean::Item) -> String {
|
||||
let mut tags = String::new();
|
||||
|
||||
fn tag_html(class: &str, title: &str, contents: &str) -> String {
|
||||
@ -2159,7 +2165,13 @@ fn stability_tags(item: &clean::Item) -> String {
|
||||
tags += &tag_html("unstable", "", "Experimental");
|
||||
}
|
||||
|
||||
if let Some(ref cfg) = item.attrs.cfg {
|
||||
let cfg = match (&item.attrs.cfg, parent.attrs.cfg.as_ref()) {
|
||||
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
|
||||
(cfg, _) => cfg.as_deref().cloned(),
|
||||
};
|
||||
|
||||
debug!("Portability {:?} - {:?} = {:?}", item.attrs.cfg, parent.attrs.cfg, cfg);
|
||||
if let Some(ref cfg) = cfg {
|
||||
tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
|
||||
}
|
||||
|
||||
@ -2168,7 +2180,7 @@ fn stability_tags(item: &clean::Item) -> String {
|
||||
|
||||
/// Render the stability and/or deprecation warning that is displayed at the top of the item's
|
||||
/// documentation.
|
||||
fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
||||
fn short_stability(item: &clean::Item, cx: &Context, parent: Option<&clean::Item>) -> Vec<String> {
|
||||
let mut stability = vec![];
|
||||
let error_codes = cx.shared.codes;
|
||||
|
||||
@ -2243,7 +2255,18 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
||||
stability.push(format!("<div class='stab unstable'>{}</div>", message));
|
||||
}
|
||||
|
||||
if let Some(ref cfg) = item.attrs.cfg {
|
||||
let cfg = match (&item.attrs.cfg, parent.and_then(|p| p.attrs.cfg.as_ref())) {
|
||||
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
|
||||
(cfg, _) => cfg.as_deref().cloned(),
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Portability {:?} - {:?} = {:?}",
|
||||
item.attrs.cfg,
|
||||
parent.and_then(|p| p.attrs.cfg.as_ref()),
|
||||
cfg
|
||||
);
|
||||
if let Some(cfg) = cfg {
|
||||
stability.push(format!("<div class='stab portability'>{}</div>", cfg.render_long_html()));
|
||||
}
|
||||
|
||||
@ -2282,7 +2305,7 @@ fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Cons
|
||||
}
|
||||
|
||||
write!(w, "</pre>");
|
||||
document(w, cx, it)
|
||||
document(w, cx, it, None)
|
||||
}
|
||||
|
||||
fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
|
||||
@ -2296,7 +2319,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static
|
||||
name = it.name.as_ref().unwrap(),
|
||||
typ = s.type_.print()
|
||||
);
|
||||
document(w, cx, it)
|
||||
document(w, cx, it, None)
|
||||
}
|
||||
|
||||
fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) {
|
||||
@ -2329,7 +2352,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
|
||||
.print(),
|
||||
spotlight = spotlight_decl(&f.decl),
|
||||
);
|
||||
document(w, cx, it)
|
||||
document(w, cx, it, None)
|
||||
}
|
||||
|
||||
fn render_implementor(
|
||||
@ -2354,6 +2377,7 @@ fn render_implementor(
|
||||
w,
|
||||
cx,
|
||||
implementor,
|
||||
None,
|
||||
AssocItemLink::Anchor(None),
|
||||
RenderMode::Normal,
|
||||
implementor.impl_item.stable_since().as_deref(),
|
||||
@ -2383,6 +2407,7 @@ fn render_impls(
|
||||
&mut buffer,
|
||||
cx,
|
||||
i,
|
||||
Some(containing_item),
|
||||
assoc_link,
|
||||
RenderMode::Normal,
|
||||
containing_item.stable_since().as_deref(),
|
||||
@ -2502,7 +2527,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
|
||||
});
|
||||
|
||||
// Trait documentation
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
|
||||
fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
|
||||
write!(
|
||||
@ -2520,6 +2545,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
|
||||
|
||||
fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
|
||||
let name = m.name.as_ref().unwrap();
|
||||
info!("Documenting {} on {}", name, t.name.as_deref().unwrap_or_default());
|
||||
let item_type = m.type_();
|
||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||
write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
|
||||
@ -2527,7 +2553,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
|
||||
write!(w, "</code>");
|
||||
render_stability_since(w, m, t);
|
||||
write!(w, "</h3>");
|
||||
document(w, cx, m);
|
||||
document(w, cx, m, Some(t));
|
||||
}
|
||||
|
||||
if !types.is_empty() {
|
||||
@ -2628,6 +2654,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
|
||||
w,
|
||||
cx,
|
||||
&implementor,
|
||||
None,
|
||||
assoc_link,
|
||||
RenderMode::Normal,
|
||||
implementor.impl_item.stable_since().as_deref(),
|
||||
@ -2890,7 +2917,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
|
||||
write!(w, "</pre>")
|
||||
});
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
let mut fields = s
|
||||
.fields
|
||||
.iter()
|
||||
@ -2925,7 +2952,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
|
||||
name = field.name.as_ref().unwrap(),
|
||||
ty = ty.print()
|
||||
);
|
||||
document(w, cx, field);
|
||||
document(w, cx, field, Some(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2940,7 +2967,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
|
||||
write!(w, "</pre>")
|
||||
});
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
let mut fields = s
|
||||
.fields
|
||||
.iter()
|
||||
@ -2972,7 +2999,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
|
||||
if let Some(stability_class) = field.stability_class() {
|
||||
write!(w, "<span class='stab {stab}'></span>", stab = stability_class);
|
||||
}
|
||||
document(w, cx, field);
|
||||
document(w, cx, field, Some(it));
|
||||
}
|
||||
}
|
||||
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
|
||||
@ -3027,7 +3054,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
|
||||
write!(w, "</pre>")
|
||||
});
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
if !e.variants.is_empty() {
|
||||
write!(
|
||||
w,
|
||||
@ -3060,7 +3087,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
|
||||
}
|
||||
}
|
||||
write!(w, "</code></div>");
|
||||
document(w, cx, variant);
|
||||
document(w, cx, variant, Some(it));
|
||||
document_non_exhaustive(w, variant);
|
||||
|
||||
use crate::clean::{Variant, VariantKind};
|
||||
@ -3095,7 +3122,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
|
||||
f = field.name.as_ref().unwrap(),
|
||||
t = ty.print()
|
||||
);
|
||||
document(w, cx, field);
|
||||
document(w, cx, field, Some(variant));
|
||||
}
|
||||
}
|
||||
write!(w, "</div></div>");
|
||||
@ -3293,6 +3320,10 @@ fn render_assoc_items(
|
||||
what: AssocItemRender<'_>,
|
||||
cache: &Cache,
|
||||
) {
|
||||
info!(
|
||||
"Documenting associated items of {}",
|
||||
containing_item.name.as_deref().unwrap_or_default()
|
||||
);
|
||||
let v = match cache.impls.get(&it) {
|
||||
Some(v) => v,
|
||||
None => return,
|
||||
@ -3327,6 +3358,7 @@ fn render_assoc_items(
|
||||
w,
|
||||
cx,
|
||||
i,
|
||||
Some(containing_item),
|
||||
AssocItemLink::Anchor(None),
|
||||
render_mode,
|
||||
containing_item.stable_since().as_deref(),
|
||||
@ -3518,6 +3550,7 @@ fn render_impl(
|
||||
w: &mut Buffer,
|
||||
cx: &Context,
|
||||
i: &Impl,
|
||||
parent: Option<&clean::Item>,
|
||||
link: AssocItemLink<'_>,
|
||||
render_mode: RenderMode,
|
||||
outer_version: Option<&str>,
|
||||
@ -3600,6 +3633,7 @@ fn render_impl(
|
||||
w: &mut Buffer,
|
||||
cx: &Context,
|
||||
item: &clean::Item,
|
||||
parent: Option<&clean::Item>,
|
||||
link: AssocItemLink<'_>,
|
||||
render_mode: RenderMode,
|
||||
is_default_item: bool,
|
||||
@ -3684,7 +3718,7 @@ fn render_impl(
|
||||
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
|
||||
// We need the stability of the item from the trait
|
||||
// because impls can't have a stability.
|
||||
document_stability(w, cx, it, is_hidden);
|
||||
document_stability(w, cx, it, is_hidden, parent);
|
||||
if item.doc_value().is_some() {
|
||||
document_full(w, item, cx, "", is_hidden);
|
||||
} else if show_def_docs {
|
||||
@ -3694,13 +3728,13 @@ fn render_impl(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
document_stability(w, cx, item, is_hidden);
|
||||
document_stability(w, cx, item, is_hidden, parent);
|
||||
if show_def_docs {
|
||||
document_full(w, item, cx, "", is_hidden);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
document_stability(w, cx, item, is_hidden);
|
||||
document_stability(w, cx, item, is_hidden, parent);
|
||||
if show_def_docs {
|
||||
document_short(w, item, link, "", is_hidden);
|
||||
}
|
||||
@ -3717,6 +3751,7 @@ fn render_impl(
|
||||
w,
|
||||
cx,
|
||||
trait_item,
|
||||
parent,
|
||||
link,
|
||||
render_mode,
|
||||
false,
|
||||
@ -3732,6 +3767,7 @@ fn render_impl(
|
||||
cx: &Context,
|
||||
t: &clean::Trait,
|
||||
i: &clean::Impl,
|
||||
parent: Option<&clean::Item>,
|
||||
render_mode: RenderMode,
|
||||
outer_version: Option<&str>,
|
||||
show_def_docs: bool,
|
||||
@ -3749,6 +3785,7 @@ fn render_impl(
|
||||
w,
|
||||
cx,
|
||||
trait_item,
|
||||
parent,
|
||||
assoc_link,
|
||||
render_mode,
|
||||
true,
|
||||
@ -3771,6 +3808,7 @@ fn render_impl(
|
||||
cx,
|
||||
t,
|
||||
&i.inner_impl(),
|
||||
parent,
|
||||
render_mode,
|
||||
outer_version,
|
||||
show_def_docs,
|
||||
@ -3799,7 +3837,7 @@ fn item_opaque_ty(
|
||||
bounds = bounds(&t.bounds, false)
|
||||
);
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
|
||||
// Render any items associated directly to this alias, as otherwise they
|
||||
// won't be visible anywhere in the docs. It would be nice to also show
|
||||
@ -3826,7 +3864,7 @@ fn item_trait_alias(
|
||||
bounds(&t.bounds, true)
|
||||
);
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
|
||||
// Render any items associated directly to this alias, as otherwise they
|
||||
// won't be visible anywhere in the docs. It would be nice to also show
|
||||
@ -3847,7 +3885,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed
|
||||
type_ = t.type_.print()
|
||||
);
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
|
||||
// Render any items associated directly to this alias, as otherwise they
|
||||
// won't be visible anywhere in the docs. It would be nice to also show
|
||||
@ -3866,7 +3904,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cac
|
||||
it.name.as_ref().unwrap(),
|
||||
);
|
||||
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
|
||||
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
|
||||
}
|
||||
@ -4511,7 +4549,7 @@ fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro)
|
||||
None,
|
||||
))
|
||||
});
|
||||
document(w, cx, it)
|
||||
document(w, cx, it, None)
|
||||
}
|
||||
|
||||
fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) {
|
||||
@ -4541,16 +4579,16 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr
|
||||
write!(w, "</pre>");
|
||||
}
|
||||
}
|
||||
document(w, cx, it)
|
||||
document(w, cx, it, None)
|
||||
}
|
||||
|
||||
fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
|
||||
document(w, cx, it);
|
||||
document(w, cx, it, None);
|
||||
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
|
||||
}
|
||||
|
||||
fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
|
||||
document(w, cx, it)
|
||||
document(w, cx, it, None)
|
||||
}
|
||||
|
||||
crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
|
||||
|
182
src/test/rustdoc/doc-cfg-simplification.rs
Normal file
182
src/test/rustdoc/doc-cfg-simplification.rs
Normal file
@ -0,0 +1,182 @@
|
||||
#![crate_name = "globuliferous"]
|
||||
#![feature(doc_cfg)]
|
||||
|
||||
// @has 'globuliferous/index.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' '^ratel$'
|
||||
|
||||
// @has 'globuliferous/ratel/index.html'
|
||||
// @count - '//*[@class="stab portability"]' 8
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
// @matches - '//*[@class="stab portability"]' '^zoonosology$'
|
||||
// @matches - '//*[@class="stab portability"]' '^yusho$'
|
||||
// @matches - '//*[@class="stab portability"]' '^nunciative$'
|
||||
// @matches - '//*[@class="stab portability"]' '^thionic$'
|
||||
// @matches - '//*[@class="stab portability"]' '^zincic$'
|
||||
// @matches - '//*[@class="stab portability"]' '^cosmotellurian$'
|
||||
// @matches - '//*[@class="stab portability"]' '^aposiopesis$'
|
||||
#[doc(cfg(feature = "ratel"))]
|
||||
pub mod ratel {
|
||||
// @has 'globuliferous/ratel/fn.ovicide.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
pub fn ovicide() {}
|
||||
|
||||
// @has 'globuliferous/ratel/fn.zoonosology.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and zoonosology'
|
||||
#[doc(cfg(feature = "zoonosology"))]
|
||||
pub fn zoonosology() {}
|
||||
|
||||
// @has 'globuliferous/ratel/constant.DIAGRAPHICS.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
pub const DIAGRAPHICS: () = ();
|
||||
|
||||
// @has 'globuliferous/ratel/constant.YUSHO.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and yusho'
|
||||
#[doc(cfg(feature = "yusho"))]
|
||||
pub const YUSHO: () = ();
|
||||
|
||||
// @has 'globuliferous/ratel/static.KEYBUGLE.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
pub static KEYBUGLE: () = ();
|
||||
|
||||
// @has 'globuliferous/ratel/static.NUNCIATIVE.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and nunciative'
|
||||
#[doc(cfg(feature = "nunciative"))]
|
||||
pub static NUNCIATIVE: () = ();
|
||||
|
||||
// @has 'globuliferous/ratel/type.Wrick.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
pub type Wrick = ();
|
||||
|
||||
// @has 'globuliferous/ratel/type.Thionic.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and thionic'
|
||||
#[doc(cfg(feature = "thionic"))]
|
||||
pub type Thionic = ();
|
||||
|
||||
// @has 'globuliferous/ratel/struct.Eventration.html'
|
||||
// @count - '//*[@class="stab portability"]' 1
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
pub struct Eventration;
|
||||
|
||||
// @has 'globuliferous/ratel/struct.Zincic.html'
|
||||
// @count - '//*[@class="stab portability"]' 2
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and zincic'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature rutherford'
|
||||
#[doc(cfg(feature = "zincic"))]
|
||||
pub struct Zincic {
|
||||
pub rectigrade: (),
|
||||
|
||||
#[doc(cfg(feature = "rutherford"))]
|
||||
pub rutherford: (),
|
||||
}
|
||||
|
||||
// @has 'globuliferous/ratel/enum.Cosmotellurian.html'
|
||||
// @count - '//*[@class="stab portability"]' 10
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and cosmotellurian'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature biotaxy'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature xiphopagus'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature juxtapositive'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature fuero'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature palaeophile'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features broadcloth and xanthocomic'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features broadcloth and whosoever'
|
||||
#[doc(cfg(feature = "cosmotellurian"))]
|
||||
pub enum Cosmotellurian {
|
||||
Groundsel {
|
||||
jagger: (),
|
||||
|
||||
#[doc(cfg(feature = "xiphopagus"))]
|
||||
xiphopagus: (),
|
||||
},
|
||||
|
||||
#[doc(cfg(feature = "biotaxy"))]
|
||||
Biotaxy {
|
||||
glossography: (),
|
||||
|
||||
#[doc(cfg(feature = "juxtapositive"))]
|
||||
juxtapositive: (),
|
||||
},
|
||||
}
|
||||
|
||||
impl Cosmotellurian {
|
||||
pub fn uxoricide() {}
|
||||
|
||||
#[doc(cfg(feature = "fuero"))]
|
||||
pub fn fuero() {}
|
||||
|
||||
pub const MAMELLE: () = ();
|
||||
|
||||
#[doc(cfg(feature = "palaeophile"))]
|
||||
pub const PALAEOPHILE: () = ();
|
||||
}
|
||||
|
||||
#[doc(cfg(feature = "broadcloth"))]
|
||||
impl Cosmotellurian {
|
||||
pub fn trabeculated() {}
|
||||
|
||||
#[doc(cfg(feature = "xanthocomic"))]
|
||||
pub fn xanthocomic() {}
|
||||
|
||||
pub const BRACHIFEROUS: () = ();
|
||||
|
||||
#[doc(cfg(feature = "whosoever"))]
|
||||
pub const WHOSOEVER: () = ();
|
||||
}
|
||||
|
||||
// @has 'globuliferous/ratel/trait.Gnotobiology.html'
|
||||
// @count - '//*[@class="stab portability"]' 4
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature unzymotic'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature summate'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature unctuous'
|
||||
pub trait Gnotobiology {
|
||||
const XYLOTHERAPY: ();
|
||||
|
||||
#[doc(cfg(feature = "unzymotic"))]
|
||||
const UNZYMOTIC: ();
|
||||
|
||||
type Lepadoid;
|
||||
|
||||
#[doc(cfg(feature = "summate"))]
|
||||
type Summate;
|
||||
|
||||
fn decalcomania();
|
||||
|
||||
#[doc(cfg(feature = "unctuous"))]
|
||||
fn unctuous();
|
||||
}
|
||||
|
||||
// @has 'globuliferous/ratel/trait.Aposiopesis.html'
|
||||
// @count - '//*[@class="stab portability"]' 4
|
||||
// @matches - '//*[@class="stab portability"]' 'crate features ratel and aposiopesis'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature umbracious'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature uakari'
|
||||
// @matches - '//*[@class="stab portability"]' 'crate feature rotograph'
|
||||
#[doc(cfg(feature = "aposiopesis"))]
|
||||
pub trait Aposiopesis {
|
||||
const REDHIBITION: ();
|
||||
|
||||
#[doc(cfg(feature = "umbracious"))]
|
||||
const UMBRACIOUS: ();
|
||||
|
||||
type Ophthalmoscope;
|
||||
|
||||
#[doc(cfg(feature = "uakari"))]
|
||||
type Uakari;
|
||||
|
||||
fn meseems();
|
||||
|
||||
#[doc(cfg(feature = "rotograph"))]
|
||||
fn rotograph();
|
||||
}
|
||||
}
|
@ -10,9 +10,8 @@ pub struct Portable;
|
||||
// @has doc_cfg/unix_only/index.html \
|
||||
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
||||
// 'This is supported on Unix only.'
|
||||
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix\Z'
|
||||
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix and ARM\Z'
|
||||
// @count - '//*[@class="stab portability"]' 3
|
||||
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AARM\Z'
|
||||
// @count - '//*[@class="stab portability"]' 2
|
||||
#[doc(cfg(unix))]
|
||||
pub mod unix_only {
|
||||
// @has doc_cfg/unix_only/fn.unix_only_function.html \
|
||||
@ -26,7 +25,7 @@ pub mod unix_only {
|
||||
// @has doc_cfg/unix_only/trait.ArmOnly.html \
|
||||
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
||||
// 'This is supported on Unix and ARM only.'
|
||||
// @count - '//*[@class="stab portability"]' 3
|
||||
// @count - '//*[@class="stab portability"]' 2
|
||||
#[doc(cfg(target_arch = "arm"))]
|
||||
pub trait ArmOnly {
|
||||
fn unix_and_arm_only_function();
|
||||
|
@ -14,45 +14,41 @@
|
||||
pub struct Foo;
|
||||
|
||||
// @has 'foo/bar/index.html'
|
||||
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$'
|
||||
// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
|
||||
|
||||
// @has 'foo/bar/struct.Bar.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
|
||||
#[doc(cfg(feature = "sync"))]
|
||||
pub mod bar {
|
||||
// @has 'foo/bar/struct.Bar.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
|
||||
#[doc(cfg(feature = "sync"))]
|
||||
pub struct Bar;
|
||||
}
|
||||
|
||||
// @has 'foo/baz/index.html'
|
||||
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send$'
|
||||
// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate features `sync` and `send` only'
|
||||
|
||||
// @has 'foo/baz/struct.Baz.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
|
||||
#[doc(cfg(all(feature = "sync", feature = "send")))]
|
||||
pub mod baz {
|
||||
// @has 'foo/baz/struct.Baz.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
|
||||
#[doc(cfg(feature = "sync"))]
|
||||
pub struct Baz;
|
||||
}
|
||||
|
||||
// @has 'foo/qux/struct.Qux.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
|
||||
// @has 'foo/qux/index.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
|
||||
#[doc(cfg(feature = "sync"))]
|
||||
pub mod qux {
|
||||
// @has 'foo/qux/struct.Qux.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
|
||||
#[doc(cfg(all(feature = "sync", feature = "send")))]
|
||||
pub struct Qux;
|
||||
}
|
||||
|
||||
// @has 'foo/quux/index.html'
|
||||
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send and foo and bar$'
|
||||
// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` and crate feature `send` and `foo` and `bar` only'
|
||||
|
||||
// @has 'foo/quux/struct.Quux.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.'
|
||||
#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
|
||||
pub mod quux {
|
||||
// @has 'foo/quux/struct.Quux.html'
|
||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
|
||||
#[doc(cfg(all(feature = "send", feature = "sync", bar)))]
|
||||
pub struct Quux;
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||
--> $DIR/arg-count-mismatch.rs:5:28
|
||||
|
|
||||
LL | fn f(x: isize) { }
|
||||
| -------------- defined here
|
||||
LL |
|
||||
LL | fn main() { let i: (); i = f(); }
|
||||
| ^-- supplied 0 arguments
|
||||
| |
|
||||
| expected 1 argument
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/arg-count-mismatch.rs:3:4
|
||||
|
|
||||
LL | fn f(x: isize) { }
|
||||
| ^ --------
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
#![feature(or_patterns)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
enum Test {
|
||||
Foo,
|
||||
Bar,
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:38:9
|
||||
|
|
||||
LL | ref foo @ [.., ref mut bar] => (),
|
||||
| -------^^^^^^^^-----------^
|
||||
@ -8,7 +8,7 @@ LL | ref foo @ [.., ref mut bar] => (),
|
||||
| immutable borrow, by `foo`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:122:9
|
||||
|
|
||||
LL | ref foo @ Some(box ref mut s) => (),
|
||||
| -------^^^^^^^^^^^^---------^
|
||||
@ -17,7 +17,7 @@ LL | ref foo @ Some(box ref mut s) => (),
|
||||
| immutable borrow, by `foo`, occurs here
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:20:5
|
||||
|
|
||||
LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
|
||||
| - move occurs because `x` has type `[String; 4]`, which does not implement the `Copy` trait
|
||||
@ -29,7 +29,7 @@ LL | &x;
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:30:5
|
||||
|
|
||||
LL | ref mut foo @ [.., _] => Some(foo),
|
||||
| --------------------- mutable borrow occurs here
|
||||
@ -41,7 +41,7 @@ LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:52:5
|
||||
|
|
||||
LL | [ref foo @ .., ref bar] => Some(foo),
|
||||
| ------------ immutable borrow occurs here
|
||||
@ -53,7 +53,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:64:5
|
||||
|
|
||||
LL | ref foo @ [.., ref bar] => Some(foo),
|
||||
| ----------------------- immutable borrow occurs here
|
||||
@ -65,7 +65,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:78:5
|
||||
|
|
||||
LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
|
||||
| - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait
|
||||
@ -80,7 +80,7 @@ LL | &x;
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:88:5
|
||||
|
|
||||
LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||
| ------------------------------------- immutable borrow occurs here
|
||||
@ -92,7 +92,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:100:5
|
||||
|
|
||||
LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||
| ----------------------------------------- mutable borrow occurs here
|
||||
@ -104,7 +104,7 @@ LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:114:5
|
||||
|
|
||||
LL | ref foo @ Some(box ref s) => Some(foo),
|
||||
| ------------------------- immutable borrow occurs here
|
||||
@ -116,7 +116,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:136:5
|
||||
|
|
||||
LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
|
||||
| - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait
|
||||
@ -131,7 +131,7 @@ LL | &x;
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:146:5
|
||||
|
|
||||
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
|
||||
| ------------------------------------------------- immutable borrow occurs here
|
||||
@ -143,7 +143,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:158:5
|
||||
|
|
||||
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
|
||||
| ---------- immutable borrow occurs here
|
||||
@ -155,7 +155,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:172:5
|
||||
|
|
||||
LL | [_, ref a @ Some(box ref b), ..] => Some(a),
|
||||
| ----------------------- immutable borrow occurs here
|
||||
@ -167,7 +167,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:188:5
|
||||
|
|
||||
LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
| ------------------------------------------- immutable borrow occurs here
|
||||
@ -179,7 +179,7 @@ LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:202:5
|
||||
|
|
||||
LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
| ----------------------------------------------- mutable borrow occurs here
|
||||
@ -191,7 +191,7 @@ LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:216:5
|
||||
|
|
||||
LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
| ------------------------------------------------------------ immutable borrow occurs here
|
||||
|
@ -7,24 +7,30 @@ LL | fn printf(_: *const u8, ...);
|
||||
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
|
||||
--> $DIR/variadic-ffi-1.rs:17:9
|
||||
|
|
||||
LL | fn foo(f: isize, x: u8, ...);
|
||||
| ----------------------------- defined here
|
||||
...
|
||||
LL | foo();
|
||||
| ^^^-- supplied 0 arguments
|
||||
| |
|
||||
| expected at least 2 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/variadic-ffi-1.rs:10:8
|
||||
|
|
||||
LL | fn foo(f: isize, x: u8, ...);
|
||||
| ^^^
|
||||
|
||||
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
|
||||
--> $DIR/variadic-ffi-1.rs:18:9
|
||||
|
|
||||
LL | fn foo(f: isize, x: u8, ...);
|
||||
| ----------------------------- defined here
|
||||
...
|
||||
LL | foo(1);
|
||||
| ^^^ - supplied 1 argument
|
||||
| |
|
||||
| expected at least 2 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/variadic-ffi-1.rs:10:8
|
||||
|
|
||||
LL | fn foo(f: isize, x: u8, ...);
|
||||
| ^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/variadic-ffi-1.rs:20:56
|
||||
|
@ -2,7 +2,7 @@ error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-no-fixed-args.rs:2:12
|
||||
|
|
||||
LL | fn foo(...);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
// edition:2018
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use std::{
|
||||
|
@ -2,7 +2,6 @@
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
|
||||
#![feature(generators, generator_trait, untagged_unions)]
|
||||
#![feature(move_ref_pattern)]
|
||||
#![feature(bindings_after_at)]
|
||||
|
||||
#![allow(unused_assignments)]
|
||||
|
@ -1,11 +0,0 @@
|
||||
#![feature(bindings_after_at)]
|
||||
|
||||
fn main() {
|
||||
let x = Some("s".to_string());
|
||||
match x {
|
||||
op_string @ Some(s) => {},
|
||||
//~^ ERROR E0007
|
||||
//~| ERROR E0382
|
||||
None => {},
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
error[E0007]: cannot bind by-move with sub-bindings
|
||||
--> $DIR/E0007.rs:6:9
|
||||
|
|
||||
LL | op_string @ Some(s) => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/E0007.rs:6:26
|
||||
|
|
||||
LL | let x = Some("s".to_string());
|
||||
| - move occurs because `x` has type `Option<String>`, which does not implement the `Copy` trait
|
||||
LL | match x {
|
||||
LL | op_string @ Some(s) => {},
|
||||
| -----------------^-
|
||||
| | |
|
||||
| | value used here after move
|
||||
| value moved here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0007, E0382.
|
||||
For more information about an error, try `rustc --explain E0007`.
|
@ -1,13 +1,16 @@
|
||||
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
|
||||
--> $DIR/E0060.rs:6:14
|
||||
|
|
||||
LL | fn printf(_: *const u8, ...) -> u32;
|
||||
| ------------------------------------ defined here
|
||||
...
|
||||
LL | unsafe { printf(); }
|
||||
| ^^^^^^-- supplied 0 arguments
|
||||
| |
|
||||
| expected at least 1 argument
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/E0060.rs:2:8
|
||||
|
|
||||
LL | fn printf(_: *const u8, ...) -> u32;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,24 +1,30 @@
|
||||
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
||||
--> $DIR/E0061.rs:6:5
|
||||
|
|
||||
LL | fn f(a: u16, b: &str) {}
|
||||
| --------------------- defined here
|
||||
...
|
||||
LL | f(0);
|
||||
| ^ - supplied 1 argument
|
||||
| |
|
||||
| expected 2 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/E0061.rs:1:4
|
||||
|
|
||||
LL | fn f(a: u16, b: &str) {}
|
||||
| ^ ------ -------
|
||||
|
||||
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||
--> $DIR/E0061.rs:10:5
|
||||
|
|
||||
LL | fn f2(a: u16) {}
|
||||
| ------------- defined here
|
||||
...
|
||||
LL | f2();
|
||||
| ^^-- supplied 0 arguments
|
||||
| |
|
||||
| expected 1 argument
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/E0061.rs:3:4
|
||||
|
|
||||
LL | fn f2(a: u16) {}
|
||||
| ^^ ------
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||
--> $DIR/issue-58451.rs:12:9
|
||||
|
|
||||
LL | / fn f<I>(i: I)
|
||||
LL | | where
|
||||
LL | | I: IntoIterator,
|
||||
LL | | I::Item: for<'a> Into<&'a ()>,
|
||||
| |__________________________________- defined here
|
||||
...
|
||||
LL | f(&[f()]);
|
||||
| ^-- supplied 0 arguments
|
||||
| |
|
||||
| expected 1 argument
|
||||
LL | f(&[f()]);
|
||||
| ^-- supplied 0 arguments
|
||||
| |
|
||||
| expected 1 argument
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-58451.rs:5:4
|
||||
|
|
||||
LL | fn f<I>(i: I)
|
||||
| ^ ----
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
||||
--> $DIR/issue-18819.rs:16:5
|
||||
|
|
||||
LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
|
||||
| ----------------------------------------------- defined here
|
||||
...
|
||||
LL | print_x(X);
|
||||
| ^^^^^^^ - supplied 1 argument
|
||||
| |
|
||||
| expected 2 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-18819.rs:11:4
|
||||
|
|
||||
LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
|
||||
| ^^^^^^^ ---------------------- -----------
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,11 +4,14 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
|
||||
LL | $other(None)
|
||||
| ---- supplied 1 argument
|
||||
...
|
||||
LL | fn some_function() {}
|
||||
| ------------------ defined here
|
||||
...
|
||||
LL | some_macro!(some_function);
|
||||
| ^^^^^^^^^^^^^ expected 0 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-26094.rs:7:4
|
||||
|
|
||||
LL | fn some_function() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||
--> $DIR/issue-4935.rs:5:13
|
||||
|
|
||||
LL | fn foo(a: usize) {}
|
||||
| ---------------- defined here
|
||||
LL |
|
||||
LL | fn main() { foo(5, 6) }
|
||||
| ^^^ - - supplied 2 arguments
|
||||
| |
|
||||
| expected 1 argument
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/issue-4935.rs:3:4
|
||||
|
|
||||
LL | fn foo(a: usize) {}
|
||||
| ^^^ --------
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,35 +1,44 @@
|
||||
error[E0061]: this function takes 0 arguments but 1 argument was supplied
|
||||
--> $DIR/method-call-err-msg.rs:13:7
|
||||
|
|
||||
LL | fn zero(self) -> Foo { self }
|
||||
| -------------------- defined here
|
||||
...
|
||||
LL | x.zero(0)
|
||||
| ^^^^ - supplied 1 argument
|
||||
| |
|
||||
| expected 0 arguments
|
||||
|
|
||||
note: associated function defined here
|
||||
--> $DIR/method-call-err-msg.rs:5:8
|
||||
|
|
||||
LL | fn zero(self) -> Foo { self }
|
||||
| ^^^^ ----
|
||||
|
||||
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||
--> $DIR/method-call-err-msg.rs:14:7
|
||||
|
|
||||
LL | fn one(self, _: isize) -> Foo { self }
|
||||
| ----------------------------- defined here
|
||||
...
|
||||
LL | .one()
|
||||
| ^^^- supplied 0 arguments
|
||||
| |
|
||||
| expected 1 argument
|
||||
|
|
||||
note: associated function defined here
|
||||
--> $DIR/method-call-err-msg.rs:6:8
|
||||
|
|
||||
LL | fn one(self, _: isize) -> Foo { self }
|
||||
| ^^^ ---- --------
|
||||
|
||||
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
||||
--> $DIR/method-call-err-msg.rs:15:7
|
||||
|
|
||||
LL | fn two(self, _: isize, _: isize) -> Foo { self }
|
||||
| --------------------------------------- defined here
|
||||
...
|
||||
LL | .two(0);
|
||||
| ^^^ - supplied 1 argument
|
||||
| |
|
||||
| expected 2 arguments
|
||||
|
|
||||
note: associated function defined here
|
||||
--> $DIR/method-call-err-msg.rs:7:8
|
||||
|
|
||||
LL | fn two(self, _: isize, _: isize) -> Foo { self }
|
||||
| ^^^ ---- -------- --------
|
||||
|
||||
error[E0599]: no method named `take` found for struct `Foo` in the current scope
|
||||
--> $DIR/method-call-err-msg.rs:19:7
|
||||
@ -53,13 +62,16 @@ LL | .take()
|
||||
error[E0061]: this function takes 3 arguments but 0 arguments were supplied
|
||||
--> $DIR/method-call-err-msg.rs:21:7
|
||||
|
|
||||
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
|
||||
| ------------------------------------------ defined here
|
||||
...
|
||||
LL | y.three::<usize>();
|
||||
| ^^^^^--------- supplied 0 arguments
|
||||
| |
|
||||
| expected 3 arguments
|
||||
|
|
||||
note: associated function defined here
|
||||
--> $DIR/method-call-err-msg.rs:8:8
|
||||
|
|
||||
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
|
||||
| ^^^^^ ---- ---- ---- ----
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:4:8
|
||||
|
|
||||
LL | fn foo(&foo: Foo) {
|
||||
| ^^^^------
|
||||
| ^^^^-----
|
||||
| | |
|
||||
| | expected due to this
|
||||
| expected struct `Foo`, found reference
|
||||
|
@ -6,7 +6,26 @@ fn foo(a: isize, b: isize, c: isize, d:isize) {
|
||||
panic!();
|
||||
}
|
||||
|
||||
// Check that all arguments are shown in the error message, even if they're across multiple lines.
|
||||
fn bar(
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
d: i32,
|
||||
e: i32,
|
||||
f: i32,
|
||||
) {
|
||||
println!("{}", a);
|
||||
println!("{}", b);
|
||||
println!("{}", c);
|
||||
println!("{}", d);
|
||||
println!("{}", e);
|
||||
println!("{}", f);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1, 2, 3);
|
||||
//~^ ERROR this function takes 4 arguments but 3
|
||||
bar(1, 2, 3);
|
||||
//~^ ERROR this function takes 6 arguments but 3
|
||||
}
|
||||
|
@ -1,14 +1,43 @@
|
||||
error[E0061]: this function takes 4 arguments but 3 arguments were supplied
|
||||
--> $DIR/not-enough-arguments.rs:10:3
|
||||
--> $DIR/not-enough-arguments.rs:27:3
|
||||
|
|
||||
LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
|
||||
| --------------------------------------------- defined here
|
||||
...
|
||||
LL | foo(1, 2, 3);
|
||||
| ^^^ - - - supplied 3 arguments
|
||||
| |
|
||||
| expected 4 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/not-enough-arguments.rs:5:4
|
||||
|
|
||||
LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
|
||||
| ^^^ -------- -------- -------- -------
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0061]: this function takes 6 arguments but 3 arguments were supplied
|
||||
--> $DIR/not-enough-arguments.rs:29:3
|
||||
|
|
||||
LL | bar(1, 2, 3);
|
||||
| ^^^ - - - supplied 3 arguments
|
||||
| |
|
||||
| expected 6 arguments
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/not-enough-arguments.rs:10:4
|
||||
|
|
||||
LL | fn bar(
|
||||
| ^^^
|
||||
LL | a: i32,
|
||||
| ------
|
||||
LL | b: i32,
|
||||
| ------
|
||||
LL | c: i32,
|
||||
| ------
|
||||
LL | d: i32,
|
||||
| ------
|
||||
LL | e: i32,
|
||||
| ------
|
||||
LL | f: i32,
|
||||
| ------
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0061`.
|
||||
|
@ -2,205 +2,205 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
|
||||
|
|
||||
LL | fn f1_1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
||||
|
|
||||
LL | fn f1_2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
||||
|
|
||||
LL | fn f1_2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
||||
|
|
||||
LL | extern "C" fn f2_1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||
|
|
||||
LL | extern "C" fn f2_2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||
|
|
||||
LL | extern "C" fn f2_2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
||||
|
|
||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
||||
|
|
||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
|
||||
|
|
||||
LL | extern fn f3_1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
||||
|
|
||||
LL | extern fn f3_2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
||||
|
|
||||
LL | extern fn f3_2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
||||
|
|
||||
LL | extern fn f3_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
||||
|
|
||||
LL | extern fn f3_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
|
||||
|
|
||||
LL | fn e_f1(...);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
|
||||
|
|
||||
LL | fn e_f2(..., x: isize);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
|
||||
|
|
||||
LL | fn i_f1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
||||
|
|
||||
LL | fn i_f2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
||||
|
|
||||
LL | fn i_f2(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
|
||||
|
|
||||
LL | fn t_f1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
|
||||
|
|
||||
LL | fn t_f2(x: isize, ...);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
||||
|
|
||||
LL | fn t_f3(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
||||
|
|
||||
LL | fn t_f3(...) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
||||
|
|
||||
LL | fn t_f4(...);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
||||
|
|
||||
LL | fn t_f4(...);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
||||
|
|
||||
LL | fn t_f5(..., x: isize) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
||||
|
|
||||
LL | fn t_f5(..., x: isize) {}
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||
|
|
||||
LL | fn t_f6(..., x: isize);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||
|
|
||||
LL | fn t_f6(..., x: isize);
|
||||
| ^^^^
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 34 previous errors
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// where one side is by-ref and the other is by-move.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
struct X {
|
||||
x: (),
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:15:14
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
|
||||
|
|
||||
LL | Some(ref _y @ _z) => {}
|
||||
| ------^^^--
|
||||
@ -8,7 +8,7 @@ LL | Some(ref _y @ _z) => {}
|
||||
| value borrowed, by `_y`, here
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:14
|
||||
|
|
||||
LL | Some(_z @ ref _y) => {}
|
||||
| --^^^------
|
||||
@ -18,7 +18,7 @@ LL | Some(_z @ ref _y) => {}
|
||||
| move occurs because `_z` has type `X` which does not implement the `Copy` trait
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
|
||||
|
|
||||
LL | Some(ref mut _y @ _z) => {}
|
||||
| ----------^^^--
|
||||
@ -27,7 +27,7 @@ LL | Some(ref mut _y @ _z) => {}
|
||||
| value borrowed, by `_y`, here
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:14
|
||||
|
|
||||
LL | Some(_z @ ref mut _y) => {}
|
||||
| --^^^----------
|
||||
@ -37,7 +37,7 @@ LL | Some(_z @ ref mut _y) => {}
|
||||
| move occurs because `_z` has type `X` which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:19
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:19
|
||||
|
|
||||
LL | Some(_z @ ref _y) => {}
|
||||
| -----^^^^^^
|
||||
@ -52,7 +52,7 @@ LL | Some(ref _z @ ref _y) => {}
|
||||
| ^^^
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:19
|
||||
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:19
|
||||
|
|
||||
LL | Some(_z @ ref mut _y) => {}
|
||||
| -----^^^^^^^^^^
|
||||
|
@ -1,7 +1,6 @@
|
||||
// See issue #12534.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:10:12
|
||||
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:12
|
||||
|
|
||||
LL | fn f(a @ A(u): A) -> Box<u8> {
|
||||
| ------^-
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Test that moving on both sides of an `@` pattern is not allowed.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U; // Not copy!
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:14:13
|
||||
--> $DIR/borrowck-move-and-move.rs:13:13
|
||||
|
|
||||
LL | let a @ b = U;
|
||||
| ----^ - move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
@ -8,7 +8,7 @@ LL | let a @ b = U;
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:16:17
|
||||
--> $DIR/borrowck-move-and-move.rs:15:17
|
||||
|
|
||||
LL | let a @ (b, c) = (U, U);
|
||||
| --------^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||
@ -17,7 +17,7 @@ LL | let a @ (b, c) = (U, U);
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:18:17
|
||||
--> $DIR/borrowck-move-and-move.rs:17:17
|
||||
|
|
||||
LL | let a @ (b, c) = (u(), u());
|
||||
| --------^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||
@ -26,7 +26,7 @@ LL | let a @ (b, c) = (u(), u());
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:21:16
|
||||
--> $DIR/borrowck-move-and-move.rs:20:16
|
||||
|
|
||||
LL | match Ok(U) {
|
||||
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
|
||||
@ -37,7 +37,7 @@ LL | a @ Ok(b) | a @ Err(b) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:21:29
|
||||
--> $DIR/borrowck-move-and-move.rs:20:29
|
||||
|
|
||||
LL | match Ok(U) {
|
||||
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
|
||||
@ -48,7 +48,7 @@ LL | a @ Ok(b) | a @ Err(b) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:28:22
|
||||
--> $DIR/borrowck-move-and-move.rs:27:22
|
||||
|
|
||||
LL | match [u(), u(), u(), u()] {
|
||||
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
|
||||
@ -59,7 +59,7 @@ LL | xs @ [a, .., b] => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:32:18
|
||||
--> $DIR/borrowck-move-and-move.rs:31:18
|
||||
|
|
||||
LL | match [u(), u(), u(), u()] {
|
||||
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
|
||||
@ -70,7 +70,7 @@ LL | xs @ [_, ys @ .., _] => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-move-and-move.rs:25:16
|
||||
--> $DIR/borrowck-move-and-move.rs:24:16
|
||||
|
|
||||
LL | fn fun(a @ b: U) {}
|
||||
| ----^
|
||||
|
@ -3,7 +3,6 @@
|
||||
// Test `@` patterns combined with `box` patterns.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Test `@` patterns combined with `box` patterns.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:37:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:36:9
|
||||
|
|
||||
LL | let ref a @ box b = Box::new(NC);
|
||||
| -----^^^^^^^-
|
||||
@ -8,7 +8,7 @@ LL | let ref a @ box b = Box::new(NC);
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:39:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:38:9
|
||||
|
|
||||
LL | let ref a @ box ref mut b = Box::new(nc());
|
||||
| -----^^^^^^^---------
|
||||
@ -17,7 +17,7 @@ LL | let ref a @ box ref mut b = Box::new(nc());
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:41:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:40:9
|
||||
|
|
||||
LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| -----^^^^^^^---------
|
||||
@ -26,7 +26,7 @@ LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:43:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:42:9
|
||||
|
|
||||
LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| -----^^^^^^^---------
|
||||
@ -35,7 +35,7 @@ LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:46:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:45:9
|
||||
|
|
||||
LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| -----^^^^^^^---------
|
||||
@ -44,7 +44,7 @@ LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:52:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:51:9
|
||||
|
|
||||
LL | let ref mut a @ box ref b = Box::new(NC);
|
||||
| ---------^^^^^^^-----
|
||||
@ -53,7 +53,7 @@ LL | let ref mut a @ box ref b = Box::new(NC);
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:66:9
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:65:9
|
||||
|
|
||||
LL | ref mut a @ box ref b => {
|
||||
| ---------^^^^^^^-----
|
||||
@ -62,7 +62,7 @@ LL | ref mut a @ box ref b => {
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:58:11
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:57:11
|
||||
|
|
||||
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
|
||||
| ---------^^^^^^^-----
|
||||
@ -71,7 +71,7 @@ LL | fn f5(ref mut a @ box ref b: Box<NC>) {
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:21:18
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:20:18
|
||||
|
|
||||
LL | let a @ box &b = Box::new(&C);
|
||||
| ---------^ ------------ move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
|
||||
@ -80,7 +80,7 @@ LL | let a @ box &b = Box::new(&C);
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:24:17
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:23:17
|
||||
|
|
||||
LL | let a @ box b = Box::new(C);
|
||||
| --------^ ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
|
||||
@ -89,7 +89,7 @@ LL | let a @ box b = Box::new(C);
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:34:17
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:33:17
|
||||
|
|
||||
LL | match Box::new(C) {
|
||||
| ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
|
||||
@ -100,7 +100,7 @@ LL | a @ box b => {}
|
||||
| value moved here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:46:21
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:45:21
|
||||
|
|
||||
LL | let ref a @ box ref mut b = Box::new(NC);
|
||||
| ------------^^^^^^^^^
|
||||
@ -112,7 +112,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:52:25
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:51:25
|
||||
|
|
||||
LL | let ref mut a @ box ref b = Box::new(NC);
|
||||
| ----------------^^^^^
|
||||
@ -124,7 +124,7 @@ LL | *a = Box::new(NC);
|
||||
| -- mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:66:25
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:65:25
|
||||
|
|
||||
LL | ref mut a @ box ref b => {
|
||||
| ----------------^^^^^
|
||||
@ -136,7 +136,7 @@ LL | *a = Box::new(NC);
|
||||
| -- mutable borrow later used here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:27:20
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:26:20
|
||||
|
|
||||
LL | fn f1(a @ box &b: Box<&C>) {}
|
||||
| ---------^
|
||||
@ -146,7 +146,7 @@ LL | fn f1(a @ box &b: Box<&C>) {}
|
||||
| move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:30:19
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:29:19
|
||||
|
|
||||
LL | fn f2(a @ box b: Box<C>) {}
|
||||
| --------^
|
||||
@ -156,7 +156,7 @@ LL | fn f2(a @ box b: Box<C>) {}
|
||||
| move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:58:27
|
||||
--> $DIR/borrowck-pat-at-and-box.rs:57:27
|
||||
|
|
||||
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
|
||||
| ----------------^^^^^
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Currently this logic exists in THIR match checking as opposed to borrowck.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:9:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:8:9
|
||||
|
|
||||
LL | let a @ ref b = U;
|
||||
| -^^^-----
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:28:9
|
||||
|
|
||||
LL | let a @ ref b = U;
|
||||
| -^^^-----
|
||||
@ -9,7 +9,7 @@ LL | let a @ ref b = U;
|
||||
| move occurs because `a` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:9
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| -^^^^^^^^^^^^---------^^^^^^-----^
|
||||
@ -20,7 +20,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:14
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:14
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| -----^^^---------
|
||||
@ -30,7 +30,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:33
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| -^^^-----
|
||||
@ -40,7 +40,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:37:9
|
||||
|
|
||||
LL | let a @ [ref mut b, ref c] = [U, U];
|
||||
| -^^^^---------^^-----^
|
||||
@ -51,7 +51,7 @@ LL | let a @ [ref mut b, ref c] = [U, U];
|
||||
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:9
|
||||
|
|
||||
LL | let a @ ref b = u();
|
||||
| -^^^-----
|
||||
@ -61,7 +61,7 @@ LL | let a @ ref b = u();
|
||||
| move occurs because `a` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:9
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| -^^^^^^^^^^^^---------^^^^^^-----^
|
||||
@ -72,7 +72,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:14
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:14
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| -----^^^---------
|
||||
@ -82,7 +82,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:33
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| -^^^-----
|
||||
@ -92,7 +92,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:50:9
|
||||
|
|
||||
LL | let a @ [ref mut b, ref c] = [u(), u()];
|
||||
| -^^^^---------^^-----^
|
||||
@ -103,7 +103,7 @@ LL | let a @ [ref mut b, ref c] = [u(), u()];
|
||||
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:56:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9
|
||||
|
|
||||
LL | a @ Some(ref b) => {}
|
||||
| -^^^^^^^^-----^
|
||||
@ -113,7 +113,7 @@ LL | a @ Some(ref b) => {}
|
||||
| move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
|
||||
@ -124,7 +124,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:19
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:19
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| -----^^^---------
|
||||
@ -134,7 +134,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:38
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| -^^^-----
|
||||
@ -144,7 +144,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:70:9
|
||||
|
|
||||
LL | mut a @ Some([ref b, ref mut c]) => {}
|
||||
| -----^^^^^^^^^-----^^---------^^
|
||||
@ -155,7 +155,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
|
||||
| move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:76:9
|
||||
|
|
||||
LL | a @ Some(ref b) => {}
|
||||
| -^^^^^^^^-----^
|
||||
@ -165,7 +165,7 @@ LL | a @ Some(ref b) => {}
|
||||
| move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:9
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
|
||||
@ -176,7 +176,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:19
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:19
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| -----^^^---------
|
||||
@ -186,7 +186,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:38
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| -^^^-----
|
||||
@ -196,7 +196,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:92:9
|
||||
|
|
||||
LL | mut a @ Some([ref b, ref mut c]) => {}
|
||||
| -----^^^^^^^^^-----^^---------^^
|
||||
@ -207,7 +207,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
|
||||
| move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:11
|
||||
|
|
||||
LL | fn f1(a @ ref b: U) {}
|
||||
| -^^^-----
|
||||
@ -217,7 +217,7 @@ LL | fn f1(a @ ref b: U) {}
|
||||
| move occurs because `a` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:11
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:11
|
||||
|
|
||||
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| -----^^^^^^^^-----^^^^^^^^^^-----^
|
||||
@ -228,7 +228,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:20
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:20
|
||||
|
|
||||
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| -^^^-----
|
||||
@ -238,7 +238,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:31
|
||||
|
|
||||
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| -----^^^-----
|
||||
@ -248,7 +248,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:11
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:11
|
||||
|
|
||||
LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
|
||||
| -^^^^---------^^-----^
|
||||
@ -259,7 +259,7 @@ LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
|
||||
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:22
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:22
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| --------^^^^^^^^^
|
||||
@ -270,7 +270,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:33
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| ------------------------^^^^^^^^^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||
@ -279,7 +279,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:37
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:37
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
| ----^^^^^
|
||||
@ -290,7 +290,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
|
||||
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:25
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:37:25
|
||||
|
|
||||
LL | let a @ [ref mut b, ref c] = [U, U];
|
||||
| ----------------^^^^^- ------ move occurs because value has type `[U; 2]`, which does not implement the `Copy` trait
|
||||
@ -299,7 +299,7 @@ LL | let a @ [ref mut b, ref c] = [U, U];
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:13
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:13
|
||||
|
|
||||
LL | let a @ ref b = u();
|
||||
| ----^^^^^ --- move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
@ -308,7 +308,7 @@ LL | let a @ ref b = u();
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:22
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:22
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| --------^^^^^^^^^
|
||||
@ -319,7 +319,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:33
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| ------------------------^^^^^^^^^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||
@ -328,7 +328,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:37
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:37
|
||||
|
|
||||
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
| ----^^^^^
|
||||
@ -339,7 +339,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
|
||||
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:25
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:50:25
|
||||
|
|
||||
LL | let a @ [ref mut b, ref c] = [u(), u()];
|
||||
| ----------------^^^^^- ---------- move occurs because value has type `[U; 2]`, which does not implement the `Copy` trait
|
||||
@ -348,7 +348,7 @@ LL | let a @ [ref mut b, ref c] = [u(), u()];
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:27
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:27
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| --------^^^^^^^^^
|
||||
@ -363,7 +363,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
|
||||
| ^^^
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:38
|
||||
|
|
||||
LL | match Some((U, U)) {
|
||||
| ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
|
||||
@ -374,7 +374,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:42
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:42
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| ----^^^^^
|
||||
@ -389,7 +389,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
|
||||
| ^^^
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:70:30
|
||||
|
|
||||
LL | match Some([U, U]) {
|
||||
| ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
|
||||
@ -400,7 +400,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:18
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:76:18
|
||||
|
|
||||
LL | match Some(u()) {
|
||||
| --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait
|
||||
@ -411,7 +411,7 @@ LL | a @ Some(ref b) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:27
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:27
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| --------^^^^^^^^^
|
||||
@ -426,7 +426,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
|
||||
| ^^^
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:38
|
||||
|
|
||||
LL | match Some((u(), u())) {
|
||||
| ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
|
||||
@ -437,7 +437,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:42
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:42
|
||||
|
|
||||
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
|
||||
| ----^^^^^
|
||||
@ -452,7 +452,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
|
||||
| ^^^
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:92:30
|
||||
|
|
||||
LL | match Some([u(), u()]) {
|
||||
| ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
|
||||
@ -463,7 +463,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:15
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:15
|
||||
|
|
||||
LL | fn f1(a @ ref b: U) {}
|
||||
| ----^^^^^
|
||||
@ -473,7 +473,7 @@ LL | fn f1(a @ ref b: U) {}
|
||||
| move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:24
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:24
|
||||
|
|
||||
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| ----^^^^^
|
||||
@ -484,7 +484,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:31
|
||||
|
|
||||
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| --------------------^^^^^^^^^^^^^-
|
||||
@ -494,7 +494,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:39
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:39
|
||||
|
|
||||
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
| --------^^^^^
|
||||
@ -505,7 +505,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
|
||||
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:27
|
||||
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:27
|
||||
|
|
||||
LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
|
||||
| ----------------^^^^^-
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Test that `ref mut? @ pat_with_by_move_bindings` is prevented.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:23:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:22:9
|
||||
|
|
||||
LL | let ref a @ b = U;
|
||||
| -----^^^-
|
||||
@ -8,7 +8,7 @@ LL | let ref a @ b = U;
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:25:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:24:9
|
||||
|
|
||||
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
|
||||
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
|
||||
@ -18,7 +18,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:25:18
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:24:18
|
||||
|
|
||||
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
|
||||
| -----^^^-----
|
||||
@ -27,7 +27,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:25:33
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:24:33
|
||||
|
|
||||
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
|
||||
| -----^^^-
|
||||
@ -36,7 +36,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
|
||||
| value borrowed, by `d`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:29:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:28:9
|
||||
|
|
||||
LL | let ref mut a @ [b, mut c] = [U, U];
|
||||
| ---------^^^^-^^-----^
|
||||
@ -46,7 +46,7 @@ LL | let ref mut a @ [b, mut c] = [U, U];
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:31:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
|
||||
|
|
||||
LL | let ref a @ b = u();
|
||||
| -----^^^-
|
||||
@ -55,7 +55,7 @@ LL | let ref a @ b = u();
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:32:9
|
||||
|
|
||||
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
|
||||
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
|
||||
@ -65,7 +65,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:18
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:32:18
|
||||
|
|
||||
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
|
||||
| -----^^^-----
|
||||
@ -74,7 +74,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:33
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:32:33
|
||||
|
|
||||
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
|
||||
| -----^^^-
|
||||
@ -83,7 +83,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
|
||||
| value borrowed, by `d`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:37:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:36:9
|
||||
|
|
||||
LL | let ref mut a @ [b, mut c] = [u(), u()];
|
||||
| ---------^^^^-^^-----^
|
||||
@ -93,7 +93,7 @@ LL | let ref mut a @ [b, mut c] = [u(), u()];
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:41:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:40:9
|
||||
|
|
||||
LL | ref a @ Some(b) => {}
|
||||
| -----^^^^^^^^-^
|
||||
@ -102,7 +102,7 @@ LL | ref a @ Some(b) => {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:46:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:45:9
|
||||
|
|
||||
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
|
||||
@ -112,7 +112,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:46:23
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:45:23
|
||||
|
|
||||
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| -----^^^-----
|
||||
@ -121,7 +121,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:46:38
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:45:38
|
||||
|
|
||||
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| -----^^^-
|
||||
@ -130,7 +130,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| value borrowed, by `d`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:53:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:52:9
|
||||
|
|
||||
LL | ref mut a @ Some([b, mut c]) => {}
|
||||
| ---------^^^^^^^^^-^^-----^^
|
||||
@ -140,7 +140,7 @@ LL | ref mut a @ Some([b, mut c]) => {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:58:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:57:9
|
||||
|
|
||||
LL | ref a @ Some(b) => {}
|
||||
| -----^^^^^^^^-^
|
||||
@ -149,7 +149,7 @@ LL | ref a @ Some(b) => {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:63:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:62:9
|
||||
|
|
||||
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
|
||||
@ -159,7 +159,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:63:23
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:62:23
|
||||
|
|
||||
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| -----^^^-----
|
||||
@ -168,7 +168,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:63:38
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:62:38
|
||||
|
|
||||
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| -----^^^-
|
||||
@ -177,7 +177,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
|
||||
| value borrowed, by `d`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:70:9
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:69:9
|
||||
|
|
||||
LL | ref mut a @ Some([b, mut c]) => {}
|
||||
| ---------^^^^^^^^^-^^-----^^
|
||||
@ -187,7 +187,7 @@ LL | ref mut a @ Some([b, mut c]) => {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:13:11
|
||||
|
|
||||
LL | fn f1(ref a @ b: U) {}
|
||||
| -----^^^-
|
||||
@ -196,7 +196,7 @@ LL | fn f1(ref a @ b: U) {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:16:11
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:15:11
|
||||
|
|
||||
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
|
||||
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
|
||||
@ -206,7 +206,7 @@ LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:16:20
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:15:20
|
||||
|
|
||||
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
|
||||
| -----^^^-----
|
||||
@ -215,7 +215,7 @@ LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:16:35
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:15:35
|
||||
|
|
||||
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
|
||||
| -----^^^-
|
||||
@ -224,7 +224,7 @@ LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
|
||||
| value borrowed, by `d`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
|
||||
--> $DIR/borrowck-pat-by-move-and-ref.rs:19:11
|
||||
|
|
||||
LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
|
||||
| ---------^^^^-^^-----^
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
enum Option<T> {
|
||||
None,
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
|
||||
|
|
||||
LL | ref mut z @ &mut Some(ref a) => {
|
||||
| ---------^^^^^^^^^^^^^-----^
|
||||
@ -8,7 +8,7 @@ LL | ref mut z @ &mut Some(ref a) => {
|
||||
| mutable borrow, by `z`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:34:9
|
||||
|
|
||||
LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
|
||||
| ---------^^^^-----------------^
|
||||
@ -18,7 +18,7 @@ LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:22
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:34:22
|
||||
|
|
||||
LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
|
||||
| -----^^^---------
|
||||
@ -27,7 +27,7 @@ LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
|
||||
| immutable borrow, by `b`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9
|
||||
|
|
||||
LL | let ref a @ ref mut b = U;
|
||||
| -----^^^---------
|
||||
@ -36,7 +36,7 @@ LL | let ref a @ ref mut b = U;
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9
|
||||
|
|
||||
LL | let ref mut a @ ref b = U;
|
||||
| ---------^^^-----
|
||||
@ -45,7 +45,7 @@ LL | let ref mut a @ ref b = U;
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| -----^^^^---------^^---------^
|
||||
@ -55,7 +55,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9
|
||||
|
|
||||
LL | let ref mut a @ (ref b, ref c) = (U, U);
|
||||
| ---------^^^^-----^^-----^
|
||||
@ -65,7 +65,7 @@ LL | let ref mut a @ (ref b, ref c) = (U, U);
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:47:9
|
||||
|
|
||||
LL | let ref mut a @ ref b = u();
|
||||
| ---------^^^-----
|
||||
@ -74,7 +74,7 @@ LL | let ref mut a @ ref b = u();
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:52:9
|
||||
|
|
||||
LL | let ref a @ ref mut b = u();
|
||||
| -----^^^---------
|
||||
@ -83,7 +83,7 @@ LL | let ref a @ ref mut b = u();
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:58:9
|
||||
|
|
||||
LL | let ref mut a @ ref b = U;
|
||||
| ---------^^^-----
|
||||
@ -92,7 +92,7 @@ LL | let ref mut a @ ref b = U;
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:63:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:62:9
|
||||
|
|
||||
LL | let ref a @ ref mut b = U;
|
||||
| -----^^^---------
|
||||
@ -101,7 +101,7 @@ LL | let ref a @ ref mut b = U;
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:68:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
|
||||
| ---------^^^^^^-----^
|
||||
@ -110,7 +110,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:33
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:68:33
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
|
||||
| ---------^^^^^^^-----^
|
||||
@ -119,7 +119,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:9
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
|
||||
| -----^^^^^^---------^
|
||||
@ -128,7 +128,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:33
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:33
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
|
||||
| -----^^^^^^^---------^
|
||||
@ -137,7 +137,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:9
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
|
||||
| -----^^^^^^---------^
|
||||
@ -146,7 +146,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:33
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:33
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
|
||||
| -----^^^^^^^---------^
|
||||
@ -155,7 +155,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
|
||||
| ---------^^^^^^-----^
|
||||
@ -164,7 +164,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:33
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
|
||||
| ---------^^^^^^^-----^
|
||||
@ -173,7 +173,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:9
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
|
||||
| -----^^^^^^---------^
|
||||
@ -182,7 +182,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:33
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
|
||||
| -----^^^^^^^---------^
|
||||
@ -191,7 +191,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
|
||||
| ---------^^^^^^-----^
|
||||
@ -200,7 +200,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:33
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:33
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
|
||||
| ---------^^^^^^^-----^
|
||||
@ -209,7 +209,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:118:9
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| -----^^^^---------^^---------^
|
||||
@ -219,7 +219,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| -----^^^^---------^^---------^
|
||||
@ -229,7 +229,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:9
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| -----^^^^---------^^---------^
|
||||
@ -239,7 +239,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:136:9
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:135:9
|
||||
|
|
||||
LL | let ref mut a @ (ref b, ref c) = (U, U);
|
||||
| ---------^^^^-----^^-----^
|
||||
@ -249,7 +249,7 @@ LL | let ref mut a @ (ref b, ref c) = (U, U);
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
|
||||
|
|
||||
LL | fn f1(ref a @ ref mut b: U) {}
|
||||
| -----^^^---------
|
||||
@ -258,7 +258,7 @@ LL | fn f1(ref a @ ref mut b: U) {}
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
|
||||
|
|
||||
LL | fn f2(ref mut a @ ref b: U) {}
|
||||
| ---------^^^-----
|
||||
@ -267,7 +267,7 @@ LL | fn f2(ref mut a @ ref b: U) {}
|
||||
| mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
|
||||
|
|
||||
LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
|
||||
| -----^^^^^^^^^^^----------------^^^^^^^^
|
||||
@ -276,7 +276,7 @@ LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:22
|
||||
|
|
||||
LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
|
||||
| -----^^^-------------
|
||||
@ -286,7 +286,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
|
||||
| immutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:30
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:30
|
||||
|
|
||||
LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
|
||||
| ---------^^^-
|
||||
@ -295,7 +295,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
|
||||
|
|
||||
LL | ref mut z @ &mut Some(ref a) => {
|
||||
| ----------------------^^^^^-
|
||||
@ -307,7 +307,7 @@ LL | **z = None;
|
||||
| ---------- mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:21
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:47:21
|
||||
|
|
||||
LL | let ref mut a @ ref b = u();
|
||||
| ------------^^^^^
|
||||
@ -319,7 +319,7 @@ LL | *a = u();
|
||||
| -------- mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:17
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:52:17
|
||||
|
|
||||
LL | let ref a @ ref mut b = u();
|
||||
| --------^^^^^^^^^
|
||||
@ -331,7 +331,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:20
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
|
||||
| -----------^^^^^^^^^-
|
||||
@ -343,7 +343,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:45
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
|
||||
| ------------^^^^^^^^^-
|
||||
@ -355,7 +355,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:61
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:61
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
|
||||
| ^^^^^^ cannot assign
|
||||
@ -363,7 +363,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
|
||||
= note: variables bound in patterns are immutable until the end of the pattern guard
|
||||
|
||||
error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:61
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
@ -371,7 +371,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
|
||||
= note: variables bound in patterns are immutable until the end of the pattern guard
|
||||
|
||||
error[E0507]: cannot move out of `b` in pattern guard
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:66
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
|
||||
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
|
||||
@ -379,7 +379,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
|
||||
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
|
||||
|
||||
error[E0507]: cannot move out of `b` in pattern guard
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:66
|
||||
|
|
||||
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
|
||||
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
|
||||
@ -387,7 +387,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
|
||||
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
|
||||
|
||||
error[E0507]: cannot move out of `a` in pattern guard
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:66
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
|
||||
| ^ move occurs because `a` has type `&mut std::result::Result<U, U>`, which does not implement the `Copy` trait
|
||||
@ -395,7 +395,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
|
||||
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
|
||||
|
||||
error[E0507]: cannot move out of `a` in pattern guard
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:66
|
||||
|
|
||||
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
|
||||
| ^ move occurs because `a` has type `&mut std::result::Result<U, U>`, which does not implement the `Copy` trait
|
||||
@ -403,7 +403,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
|
||||
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:18
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:18
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| ---------^^^^^^^^^------------
|
||||
@ -415,7 +415,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:29
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:29
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| --------------------^^^^^^^^^-
|
||||
@ -427,7 +427,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:18
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:18
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| ---------^^^^^^^^^------------
|
||||
@ -439,7 +439,7 @@ LL | drop(a);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:29
|
||||
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:29
|
||||
|
|
||||
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||
| --------------------^^^^^^^^^-
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:27:9
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ---------^^^---------
|
||||
@ -8,7 +8,7 @@ LL | let ref mut a @ ref mut b = U;
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:32:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ---------^^^---------
|
||||
@ -17,7 +17,7 @@ LL | let ref mut a @ ref mut b = U;
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:34:9
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ---------^^^---------
|
||||
@ -26,7 +26,7 @@ LL | let ref mut a @ ref mut b = U;
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:37:9
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ---------^^^---------
|
||||
@ -35,7 +35,7 @@ LL | let ref mut a @ ref mut b = U;
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:42:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:41:9
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ---------^^^---------
|
||||
@ -44,7 +44,7 @@ LL | let ref mut a @ ref mut b = U;
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:46:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:45:9
|
||||
|
|
||||
LL | let ref mut a @ (
|
||||
| ^--------
|
||||
@ -66,7 +66,7 @@ LL | | ) = (U, [U, U, U]);
|
||||
| |_____^
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:56:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:55:9
|
||||
|
|
||||
LL | let ref mut a @ (
|
||||
| ^--------
|
||||
@ -88,7 +88,7 @@ LL | | ) = (u(), [u(), u(), u()]);
|
||||
| |_________^
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:65:9
|
||||
|
|
||||
LL | let a @ (ref mut b, ref mut c) = (U, U);
|
||||
| -^^^^---------^^---------^
|
||||
@ -99,7 +99,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U);
|
||||
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:69:9
|
||||
|
|
||||
LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
|
||||
| -^^^^-^^^-^^-^^
|
||||
@ -111,7 +111,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
|
||||
| move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:73:9
|
||||
|
|
||||
LL | let a @ &mut ref mut b = &mut U;
|
||||
| -^^^^^^^^---------
|
||||
@ -121,7 +121,7 @@ LL | let a @ &mut ref mut b = &mut U;
|
||||
| move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:77:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:76:9
|
||||
|
|
||||
LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
|
||||
| -^^^^^^^^^---------^^---------^
|
||||
@ -132,7 +132,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
|
||||
| move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:81:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^---------^
|
||||
@ -141,7 +141,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:81:37
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^^---------^
|
||||
@ -150,7 +150,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:88:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:87:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^---------^
|
||||
@ -159,7 +159,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:88:37
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:87:37
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^^---------^
|
||||
@ -168,7 +168,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^---------^
|
||||
@ -177,7 +177,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:37
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:37
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^^---------^
|
||||
@ -186,7 +186,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:9
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^---------^
|
||||
@ -195,7 +195,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:37
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:37
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------^^^^^^^---------^
|
||||
@ -204,7 +204,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:11:11
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
|
||||
|
|
||||
LL | fn f1(ref mut a @ ref mut b: U) {}
|
||||
| ---------^^^---------
|
||||
@ -213,7 +213,7 @@ LL | fn f1(ref mut a @ ref mut b: U) {}
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:13:11
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
|
||||
|
|
||||
LL | fn f2(ref mut a @ ref mut b: U) {}
|
||||
| ---------^^^---------
|
||||
@ -222,7 +222,7 @@ LL | fn f2(ref mut a @ ref mut b: U) {}
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:16:9
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
|
||||
|
|
||||
LL | ref mut a @ [
|
||||
| ^--------
|
||||
@ -240,7 +240,7 @@ LL | | ] : [[U; 4]; 5]
|
||||
| |_________^
|
||||
|
||||
error: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:24:22
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:23:22
|
||||
|
|
||||
LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
|
||||
| ---------^^^-------------
|
||||
@ -250,7 +250,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
|
||||
| first mutable borrow, by `a`, occurs here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:24:34
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:23:34
|
||||
|
|
||||
LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
|
||||
| ---------^^^-
|
||||
@ -259,7 +259,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
|
||||
| value borrowed, by `b`, here
|
||||
|
||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:28:21
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:27:21
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ------------^^^^^^^^^
|
||||
@ -271,7 +271,7 @@ LL | drop(a);
|
||||
| - first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:38:21
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:37:21
|
||||
|
|
||||
LL | let ref mut a @ ref mut b = U;
|
||||
| ------------^^^^^^^^^
|
||||
@ -283,7 +283,7 @@ LL | *a = U;
|
||||
| ------ first borrow later used here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:66:25
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:65:25
|
||||
|
|
||||
LL | let a @ (ref mut b, ref mut c) = (U, U);
|
||||
| ----------------^^^^^^^^^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||
@ -292,7 +292,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U);
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:70:21
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:69:21
|
||||
|
|
||||
LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
|
||||
| ------------^-- -------- move occurs because value has type `&mut (U, [U; 2])`, which does not implement the `Copy` trait
|
||||
@ -301,7 +301,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:74:18
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:73:18
|
||||
|
|
||||
LL | let a @ &mut ref mut b = &mut U;
|
||||
| ---------^^^^^^^^^ ------ move occurs because value has type `&mut U`, which does not implement the `Copy` trait
|
||||
@ -310,7 +310,7 @@ LL | let a @ &mut ref mut b = &mut U;
|
||||
| value moved here
|
||||
|
||||
error[E0382]: borrow of moved value
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:77:30
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:76:30
|
||||
|
|
||||
LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
|
||||
| ---------------------^^^^^^^^^- ----------- move occurs because value has type `&mut (U, U)`, which does not implement the `Copy` trait
|
||||
@ -319,7 +319,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
|
||||
| value moved here
|
||||
|
||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:24
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:24
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------------^^^^^^^^^-
|
||||
@ -331,7 +331,7 @@ LL | *a = Err(U);
|
||||
| ----------- first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:53
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:53
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ----------------^^^^^^^^^-
|
||||
@ -343,7 +343,7 @@ LL | *a = Err(U);
|
||||
| ----------- first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:24
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:24
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ---------------^^^^^^^^^-
|
||||
@ -355,7 +355,7 @@ LL | drop(a);
|
||||
| - first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:53
|
||||
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:53
|
||||
|
|
||||
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||
| ----------------^^^^^^^^^-
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct C;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/copy-and-move-mixed.rs:12:19
|
||||
--> $DIR/copy-and-move-mixed.rs:11:19
|
||||
|
|
||||
LL | let a @ NC(b, c) = NC(C, C);
|
||||
| ----------^- -------- move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait
|
||||
@ -8,7 +8,7 @@ LL | let a @ NC(b, c) = NC(C, C);
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/copy-and-move-mixed.rs:15:19
|
||||
--> $DIR/copy-and-move-mixed.rs:14:19
|
||||
|
|
||||
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
|
||||
| ----------^^^^^^^^^^^^- --------------- move occurs because value has type `NC<C, NC<C, C>>`, which does not implement the `Copy` trait
|
||||
@ -17,7 +17,7 @@ LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
|
||||
| value moved here
|
||||
|
||||
error[E0382]: use of moved value
|
||||
--> $DIR/copy-and-move-mixed.rs:15:29
|
||||
--> $DIR/copy-and-move-mixed.rs:14:29
|
||||
|
|
||||
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
|
||||
| ----------^-
|
||||
|
@ -8,7 +8,6 @@
|
||||
// this would create problems for the generalization aforementioned.
|
||||
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct NotCopy;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:28:9
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:27:9
|
||||
|
|
||||
LL | let ref a @ b = NotCopy;
|
||||
| -----^^^-
|
||||
@ -8,7 +8,7 @@ LL | let ref a @ b = NotCopy;
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:31:9
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:30:9
|
||||
|
|
||||
LL | let ref mut a @ b = NotCopy;
|
||||
| ---------^^^-
|
||||
@ -17,7 +17,7 @@ LL | let ref mut a @ b = NotCopy;
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:36:12
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:35:12
|
||||
|
|
||||
LL | Ok(ref a @ b) | Err(b @ ref a) => {
|
||||
| -----^^^-
|
||||
@ -26,7 +26,7 @@ LL | Ok(ref a @ b) | Err(b @ ref a) => {
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error: borrow of moved value
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:36:29
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:35:29
|
||||
|
|
||||
LL | Ok(ref a @ b) | Err(b @ ref a) => {
|
||||
| -^^^-----
|
||||
@ -36,7 +36,7 @@ LL | Ok(ref a @ b) | Err(b @ ref a) => {
|
||||
| move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
|
||||
|
||||
error: cannot move out of value because it is borrowed
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:44:9
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:43:9
|
||||
|
|
||||
LL | ref a @ b => {
|
||||
| -----^^^-
|
||||
@ -45,7 +45,7 @@ LL | ref a @ b => {
|
||||
| value borrowed, by `a`, here
|
||||
|
||||
error[E0505]: cannot move out of value because it is borrowed
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:31:21
|
||||
--> $DIR/default-binding-modes-both-sides-independent.rs:30:21
|
||||
|
|
||||
LL | let ref mut a @ b = NotCopy;
|
||||
| ------------^
|
||||
|
@ -1,7 +1,5 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct U;
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct U;
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:10:24
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:8:24
|
||||
|
|
||||
LL | let hold_all = &arr;
|
||||
| ---- borrow of `arr` occurs here
|
||||
@ -10,7 +10,7 @@ LL | drop(hold_all);
|
||||
| -------- borrow later used here
|
||||
|
||||
error[E0384]: cannot assign twice to immutable variable `_x1`
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:11:5
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:9:5
|
||||
|
|
||||
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||
| ---
|
||||
@ -21,7 +21,7 @@ LL | _x1 = U;
|
||||
| ^^^^^^^ cannot assign twice to immutable variable
|
||||
|
||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:13:10
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:11:10
|
||||
|
|
||||
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||
| ------------ borrow of `arr[..]` occurs here
|
||||
@ -32,7 +32,7 @@ LL | drop(_x0_hold);
|
||||
| -------- borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:15:16
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:13:16
|
||||
|
|
||||
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||
| ---------------- immutable borrow occurs here
|
||||
@ -44,7 +44,7 @@ LL | drop(xs_hold);
|
||||
| ------- immutable borrow later used here
|
||||
|
||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:15:29
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:13:29
|
||||
|
|
||||
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||
| ---------------- borrow of `arr[..]` occurs here
|
||||
@ -56,7 +56,7 @@ LL | drop(xs_hold);
|
||||
| ------- borrow later used here
|
||||
|
||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:15:34
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:13:34
|
||||
|
|
||||
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||
| ---------------- borrow of `arr[..]` occurs here
|
||||
@ -68,7 +68,7 @@ LL | drop(xs_hold);
|
||||
| ------- borrow later used here
|
||||
|
||||
error[E0384]: cannot assign twice to immutable variable `_x1`
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:25:5
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:23:5
|
||||
|
|
||||
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||
| ---
|
||||
@ -79,7 +79,7 @@ LL | _x1 = U;
|
||||
| ^^^^^^^ cannot assign twice to immutable variable
|
||||
|
||||
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:26:20
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:24:20
|
||||
|
|
||||
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||
| ------- immutable borrow occurs here
|
||||
@ -91,7 +91,7 @@ LL | *_x0 = U;
|
||||
| -------- immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:27:10
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:25:10
|
||||
|
|
||||
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||
| ------- immutable borrow occurs here
|
||||
@ -102,7 +102,7 @@ LL | *_x0 = U;
|
||||
| -------- immutable borrow later used here
|
||||
|
||||
error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:28:5
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:26:5
|
||||
|
|
||||
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||
| ------- help: consider changing this to be a mutable reference: `ref mut _x0`
|
||||
@ -111,7 +111,7 @@ LL | *_x0 = U;
|
||||
| ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:29:5
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:27:5
|
||||
|
|
||||
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||
| ------- help: consider changing this to be a mutable reference: `ref mut _x2`
|
||||
@ -120,7 +120,7 @@ LL | *_x2 = U;
|
||||
| ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error[E0382]: use of moved value: `tup.1`
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:30:10
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:28:10
|
||||
|
|
||||
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||
| --- value moved here
|
||||
@ -131,7 +131,7 @@ LL | drop(tup.1);
|
||||
= note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0382]: borrow of moved value: `tup.1`
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:31:20
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:29:20
|
||||
|
|
||||
LL | drop(tup.1);
|
||||
| ----- value moved here
|
||||
@ -141,7 +141,7 @@ LL | let _x1_hold = &tup.1;
|
||||
= note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:33:20
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:31:20
|
||||
|
|
||||
LL | let (.., ref mut _x3) = tup;
|
||||
| ----------- mutable borrow occurs here
|
||||
@ -152,7 +152,7 @@ LL | drop(_x3);
|
||||
| --- mutable borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:34:20
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:32:20
|
||||
|
|
||||
LL | let (.., ref mut _x3) = tup;
|
||||
| ----------- first mutable borrow occurs here
|
||||
@ -164,7 +164,7 @@ LL | drop(_x3);
|
||||
| --- first borrow later used here
|
||||
|
||||
error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:35:14
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:33:14
|
||||
|
|
||||
LL | let (.., ref mut _x3) = tup;
|
||||
| ----------- first mutable borrow occurs here
|
||||
@ -176,7 +176,7 @@ LL | drop(_x3);
|
||||
| --- first borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:36:14
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:34:14
|
||||
|
|
||||
LL | let (.., ref mut _x3) = tup;
|
||||
| ----------- mutable borrow occurs here
|
||||
@ -187,7 +187,7 @@ LL | drop(_x3);
|
||||
| --- mutable borrow later used here
|
||||
|
||||
error[E0382]: use of moved value: `tup`
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:45:14
|
||||
--> $DIR/borrowck-move-ref-pattern.rs:43:14
|
||||
|
|
||||
LL | let mut tup = (U, U, U);
|
||||
| ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
#![feature(bindings_after_at)]
|
||||
|
||||
fn main() {
|
||||
|
@ -1,23 +0,0 @@
|
||||
fn main() {
|
||||
#[derive(Clone)]
|
||||
struct X {
|
||||
x: (),
|
||||
}
|
||||
let mut tup = (X { x: () }, X { x: () });
|
||||
match Some(tup.clone()) {
|
||||
Some((y, ref z)) => {}
|
||||
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
|
||||
None => panic!(),
|
||||
}
|
||||
|
||||
let (ref a, b) = tup.clone();
|
||||
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
|
||||
|
||||
let (a, mut b) = &tup;
|
||||
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
|
||||
//~| ERROR cannot move out of a shared reference
|
||||
|
||||
let (mut a, b) = &mut tup;
|
||||
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
|
||||
//~| ERROR cannot move out of a mutable reference
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
error[E0658]: binding by-move and by-ref in the same pattern is unstable
|
||||
--> $DIR/feature-gate-move_ref_pattern.rs:8:15
|
||||
|
|
||||
LL | Some((y, ref z)) => {}
|
||||
| ^ ----- by-ref pattern here
|
||||
| |
|
||||
| by-move pattern here
|
||||
|
|
||||
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
|
||||
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: binding by-move and by-ref in the same pattern is unstable
|
||||
--> $DIR/feature-gate-move_ref_pattern.rs:13:17
|
||||
|
|
||||
LL | let (ref a, b) = tup.clone();
|
||||
| ----- ^ by-move pattern here
|
||||
| |
|
||||
| by-ref pattern here
|
||||
|
|
||||
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
|
||||
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: binding by-move and by-ref in the same pattern is unstable
|
||||
--> $DIR/feature-gate-move_ref_pattern.rs:16:13
|
||||
|
|
||||
LL | let (a, mut b) = &tup;
|
||||
| - ^^^^^ by-move pattern here
|
||||
| |
|
||||
| by-ref pattern here
|
||||
|
|
||||
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
|
||||
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: binding by-move and by-ref in the same pattern is unstable
|
||||
--> $DIR/feature-gate-move_ref_pattern.rs:20:10
|
||||
|
|
||||
LL | let (mut a, b) = &mut tup;
|
||||
| ^^^^^ - by-ref pattern here
|
||||
| |
|
||||
| by-move pattern here
|
||||
|
|
||||
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
|
||||
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0507]: cannot move out of a shared reference
|
||||
--> $DIR/feature-gate-move_ref_pattern.rs:16:22
|
||||
|
|
||||
LL | let (a, mut b) = &tup;
|
||||
| ----- ^^^^
|
||||
| |
|
||||
| data moved here
|
||||
| move occurs because `b` has type `X`, which does not implement the `Copy` trait
|
||||
|
||||
error[E0507]: cannot move out of a mutable reference
|
||||
--> $DIR/feature-gate-move_ref_pattern.rs:20:22
|
||||
|
|
||||
LL | let (mut a, b) = &mut tup;
|
||||
| ----- ^^^^^^^^
|
||||
| |
|
||||
| data moved here
|
||||
| move occurs because `a` has type `X`, which does not implement the `Copy` trait
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0507, E0658.
|
||||
For more information about an error, try `rustc --explain E0507`.
|
@ -1,7 +1,5 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
enum E {
|
||||
Foo(String, String, String),
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct S; // Not `Copy`.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0382]: borrow of moved value: `tup0`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:31:10
|
||||
|
|
||||
LL | let mut tup0 = (S, S);
|
||||
| -------- move occurs because `tup0` has type `(S, S)`, which does not implement the `Copy` trait
|
||||
@ -14,7 +14,7 @@ LL | drop(&tup0);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup1`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:32:10
|
||||
|
|
||||
LL | let mut tup1 = (S, S, S);
|
||||
| -------- move occurs because `tup1` has type `(S, S, S)`, which does not implement the `Copy` trait
|
||||
@ -29,7 +29,7 @@ LL | drop(&tup1);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup2`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:35:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10
|
||||
|
|
||||
LL | let tup2 = (S, S);
|
||||
| ---- move occurs because `tup2` has type `(S, S)`, which does not implement the `Copy` trait
|
||||
@ -44,7 +44,7 @@ LL | drop(&tup2);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup3`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:36:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10
|
||||
|
|
||||
LL | let tup3 = (S, S, S);
|
||||
| ---- move occurs because `tup3` has type `(S, S, S)`, which does not implement the `Copy` trait
|
||||
@ -59,7 +59,7 @@ LL | drop(&tup3);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup4`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:39:10
|
||||
|
|
||||
LL | let tup4 = (S, S);
|
||||
| ---- move occurs because `tup4` has type `(S, S)`, which does not implement the `Copy` trait
|
||||
@ -74,7 +74,7 @@ LL | drop(&tup4.0);
|
||||
| ^^^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr0`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10
|
||||
|
|
||||
LL | let mut arr0 = [S, S, S];
|
||||
| -------- move occurs because `arr0` has type `[S; 3]`, which does not implement the `Copy` trait
|
||||
@ -89,7 +89,7 @@ LL | drop(&arr0);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr1`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:42:36
|
||||
|
|
||||
LL | let mut arr1 = [S, S, S, S, S];
|
||||
| -------- move occurs because `arr1` has type `[S; 5]`, which does not implement the `Copy` trait
|
||||
@ -104,7 +104,7 @@ LL | let [_, mov1, mov2, mov3, _] = &arr1;
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr2`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:45:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10
|
||||
|
|
||||
LL | let arr2 = [S, S, S];
|
||||
| ---- move occurs because `arr2` has type `[S; 3]`, which does not implement the `Copy` trait
|
||||
@ -119,7 +119,7 @@ LL | drop(&arr2);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr3`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:46:36
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36
|
||||
|
|
||||
LL | let arr3 = [S, S, S, S, S];
|
||||
| ---- move occurs because `arr3` has type `[S; 5]`, which does not implement the `Copy` trait
|
||||
@ -134,7 +134,7 @@ LL | let [_, mov1, mov2, mov3, _] = &arr3;
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup0`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:75:10
|
||||
|
|
||||
LL | let mut tup0: Option<(S, S)> = None;
|
||||
| -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
||||
@ -148,7 +148,7 @@ LL | drop(&tup0);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup1`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:76:10
|
||||
|
|
||||
LL | let mut tup1: Option<(S, S, S)> = None;
|
||||
| -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
|
||||
@ -163,7 +163,7 @@ LL | drop(&tup1);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup2`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:79:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10
|
||||
|
|
||||
LL | let tup2: Option<(S, S)> = None;
|
||||
| ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
||||
@ -178,7 +178,7 @@ LL | drop(&tup2);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup3`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10
|
||||
|
|
||||
LL | let tup3: Option<(S, S, S)> = None;
|
||||
| ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
|
||||
@ -193,7 +193,7 @@ LL | drop(&tup3);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup4`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:81:21
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:79:21
|
||||
|
|
||||
LL | let tup4: Option<(S, S)> = None;
|
||||
| ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
||||
@ -208,7 +208,7 @@ LL | m!((ref x, _) = &tup4);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr0`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10
|
||||
|
|
||||
LL | let mut arr0: Option<[S; 3]> = None;
|
||||
| -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
||||
@ -223,7 +223,7 @@ LL | drop(&arr0);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr1`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:81:35
|
||||
|
|
||||
LL | let mut arr1: Option<[S; 5]> = None;
|
||||
| -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
||||
@ -238,7 +238,7 @@ LL | m!([_, mov1, mov2, mov3, _] = &arr1);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr2`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:84:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10
|
||||
|
|
||||
LL | let arr2: Option<[S; 3]> = None;
|
||||
| ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
||||
@ -253,7 +253,7 @@ LL | drop(&arr2);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr3`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:85:35
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35
|
||||
|
|
||||
LL | let arr3: Option<[S; 5]> = None;
|
||||
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
||||
@ -267,7 +267,7 @@ LL | m!([_, mov1, mov2, mov3, _] = &arr3);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup0`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:111:10
|
||||
|
|
||||
LL | let mut tup0: Option<(S, S)> = None;
|
||||
| -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
||||
@ -281,7 +281,7 @@ LL | drop(&tup0);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup1`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:112:10
|
||||
|
|
||||
LL | let mut tup1: Option<(S, S, S)> = None;
|
||||
| -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
|
||||
@ -296,7 +296,7 @@ LL | drop(&tup1);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup2`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:115:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10
|
||||
|
|
||||
LL | let tup2: Option<(S, S)> = None;
|
||||
| ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
||||
@ -311,7 +311,7 @@ LL | drop(&tup2);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup3`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10
|
||||
|
|
||||
LL | let tup3: Option<(S, S, S)> = None;
|
||||
| ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
|
||||
@ -326,7 +326,7 @@ LL | drop(&tup3);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `tup4`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:117:21
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:115:21
|
||||
|
|
||||
LL | let tup4: Option<(S, S)> = None;
|
||||
| ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
||||
@ -341,7 +341,7 @@ LL | m!((ref x, _) = &tup4);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr0`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10
|
||||
|
|
||||
LL | let mut arr0: Option<[S; 3]> = None;
|
||||
| -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
||||
@ -356,7 +356,7 @@ LL | drop(&arr0);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr1`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:117:35
|
||||
|
|
||||
LL | let mut arr1: Option<[S; 5]> = None;
|
||||
| -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
||||
@ -371,7 +371,7 @@ LL | m!([_, mov1, mov2, mov3, _] = &arr1);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr2`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:120:10
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10
|
||||
|
|
||||
LL | let arr2: Option<[S; 3]> = None;
|
||||
| ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
||||
@ -386,7 +386,7 @@ LL | drop(&arr2);
|
||||
| ^^^^^ value borrowed here after move
|
||||
|
||||
error[E0382]: borrow of moved value: `arr3`
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:121:35
|
||||
--> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35
|
||||
|
|
||||
LL | let arr3: Option<[S; 5]> = None;
|
||||
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
||||
|
@ -1,7 +1,5 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
fn accept_fn_once(_: impl FnOnce()) {}
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
fn accept_fn_once(_: &impl FnOnce()) {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
|
||||
--> $DIR/move-ref-patterns-closure-captures.rs:11:14
|
||||
--> $DIR/move-ref-patterns-closure-captures.rs:9:14
|
||||
|
|
||||
LL | let c1 = || {
|
||||
| ^^ this closure implements `FnOnce`, not `FnMut`
|
||||
@ -11,7 +11,7 @@ LL | accept_fn_mut(&c1);
|
||||
| ------------- the requirement to implement `FnMut` derives from here
|
||||
|
||||
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
|
||||
--> $DIR/move-ref-patterns-closure-captures.rs:11:14
|
||||
--> $DIR/move-ref-patterns-closure-captures.rs:9:14
|
||||
|
|
||||
LL | let c1 = || {
|
||||
| ^^ this closure implements `FnOnce`, not `Fn`
|
||||
@ -23,7 +23,7 @@ LL | accept_fn(&c1);
|
||||
| --------- the requirement to implement `Fn` derives from here
|
||||
|
||||
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
|
||||
--> $DIR/move-ref-patterns-closure-captures.rs:22:14
|
||||
--> $DIR/move-ref-patterns-closure-captures.rs:20:14
|
||||
|
|
||||
LL | let c2 = || {
|
||||
| ^^ this closure implements `FnMut`, not `Fn`
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
fn main() {
|
||||
struct U;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user