Auto merge of #76771 - Dylan-DPC:rollup-qj4j3ma, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #73955 (deny(unsafe_op_in_unsafe_fn) in libstd/process.rs) - #75146 (Detect overflow in proc_macro_server subspan) - #75304 (Note when a a move/borrow error is caused by a deref coercion) - #75749 (Consolidate some duplicate code in the sys modules.) - #75882 (Use translated variable for test string) - #75886 (Test that bounds checks are elided for [..index] after .position()) - #76048 (Initial support for riscv32gc_unknown_linux_gnu) - #76198 (Make some Ordering methods const) - #76689 (Upgrade to pulldown-cmark 0.8.0) - #76763 (Update cargo) Failed merges: r? `@ghost`
This commit is contained in:
commit
f4e4485a05
57 changed files with 564 additions and 973 deletions
17
Cargo.lock
17
Cargo.lock
|
@ -534,7 +534,7 @@ dependencies = [
|
|||
"if_chain",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark 0.7.2",
|
||||
"quine-mc_cluskey",
|
||||
"quote",
|
||||
"regex-syntax",
|
||||
|
@ -1853,7 +1853,7 @@ dependencies = [
|
|||
"log",
|
||||
"memchr",
|
||||
"open",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark 0.7.2",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
@ -2511,6 +2511,17 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "punycode"
|
||||
version = "0.4.1"
|
||||
|
@ -4122,7 +4133,7 @@ dependencies = [
|
|||
"expect-test",
|
||||
"itertools 0.9.0",
|
||||
"minifier",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark 0.8.0",
|
||||
"rustc-rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -584,12 +584,12 @@ impl server::Literal for Rustc<'_> {
|
|||
|
||||
let start = match start {
|
||||
Bound::Included(lo) => lo,
|
||||
Bound::Excluded(lo) => lo + 1,
|
||||
Bound::Excluded(lo) => lo.checked_add(1)?,
|
||||
Bound::Unbounded => 0,
|
||||
};
|
||||
|
||||
let end = match end {
|
||||
Bound::Included(hi) => hi + 1,
|
||||
Bound::Included(hi) => hi.checked_add(1)?,
|
||||
Bound::Excluded(hi) => hi,
|
||||
Bound::Unbounded => length,
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum PointerCast {
|
||||
|
@ -113,6 +114,9 @@ pub enum Adjust<'tcx> {
|
|||
pub struct OverloadedDeref<'tcx> {
|
||||
pub region: ty::Region<'tcx>,
|
||||
pub mutbl: hir::Mutability,
|
||||
/// The `Span` associated with the field access or method call
|
||||
/// that triggered this overloaded deref.
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> OverloadedDeref<'tcx> {
|
||||
|
|
|
@ -612,8 +612,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> {
|
|||
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::OverloadedDeref<'a> {
|
||||
type Lifted = ty::adjustment::OverloadedDeref<'tcx>;
|
||||
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.region)
|
||||
.map(|region| ty::adjustment::OverloadedDeref { region, mutbl: self.mutbl })
|
||||
tcx.lift(&self.region).map(|region| ty::adjustment::OverloadedDeref {
|
||||
region,
|
||||
mutbl: self.mutbl,
|
||||
span: self.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
let span = use_spans.args_or_use();
|
||||
|
||||
let move_site_vec = self.get_moved_indexes(location, mpi);
|
||||
debug!("report_use_of_moved_or_uninitialized: move_site_vec={:?}", move_site_vec);
|
||||
debug!(
|
||||
"report_use_of_moved_or_uninitialized: move_site_vec={:?} use_spans={:?}",
|
||||
move_site_vec, use_spans
|
||||
);
|
||||
let move_out_indices: Vec<_> =
|
||||
move_site_vec.iter().map(|move_site| move_site.moi).collect();
|
||||
|
||||
|
@ -229,6 +232,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
// Deref::deref takes &self, which cannot cause a move
|
||||
FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
err.span_label(
|
||||
|
@ -355,6 +360,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
self.note_type_does_not_implement_copy(&mut err, ¬e_msg, ty, span, partial_str);
|
||||
}
|
||||
|
||||
if let UseSpans::FnSelfUse {
|
||||
kind: FnSelfUseKind::DerefCoercion { deref_target, deref_target_ty },
|
||||
..
|
||||
} = use_spans
|
||||
{
|
||||
err.note(&format!(
|
||||
"{} occurs due to deref coercion to `{}`",
|
||||
desired_action.as_noun(),
|
||||
deref_target_ty
|
||||
));
|
||||
|
||||
err.span_note(deref_target, "deref defined here");
|
||||
}
|
||||
|
||||
if let Some((_, mut old_err)) =
|
||||
self.move_error_reported.insert(move_out_indices, (used_place, err))
|
||||
{
|
||||
|
@ -945,7 +964,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
name: &str,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
drop_span: Span,
|
||||
borrow_spans: UseSpans,
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
explanation: BorrowExplanation,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
debug!(
|
||||
|
@ -1146,7 +1165,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
location: Location,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
drop_span: Span,
|
||||
borrow_spans: UseSpans,
|
||||
borrow_spans: UseSpans<'tcx>,
|
||||
proper_span: Span,
|
||||
explanation: BorrowExplanation,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
|
@ -1274,7 +1293,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
fn report_escaping_closure_capture(
|
||||
&mut self,
|
||||
use_span: UseSpans,
|
||||
use_span: UseSpans<'tcx>,
|
||||
var_span: Span,
|
||||
fr_name: &RegionName,
|
||||
category: ConstraintCategory,
|
||||
|
|
|
@ -501,7 +501,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn later_use_kind(
|
||||
&self,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
use_spans: UseSpans,
|
||||
use_spans: UseSpans<'tcx>,
|
||||
location: Location,
|
||||
) -> (LaterUseKind, Span) {
|
||||
match use_spans {
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_middle::mir::{
|
|||
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::print::Print;
|
||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
|
||||
use rustc_span::{
|
||||
hygiene::{DesugaringKind, ForLoopLoc},
|
||||
symbol::sym,
|
||||
|
@ -538,7 +538,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
/// The span(s) associated to a use of a place.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub(super) enum UseSpans {
|
||||
pub(super) enum UseSpans<'tcx> {
|
||||
/// The access is caused by capturing a variable for a closure.
|
||||
ClosureUse {
|
||||
/// This is true if the captured variable was from a generator.
|
||||
|
@ -558,7 +558,7 @@ pub(super) enum UseSpans {
|
|||
fn_call_span: Span,
|
||||
/// The definition span of the method being called
|
||||
fn_span: Span,
|
||||
kind: FnSelfUseKind,
|
||||
kind: FnSelfUseKind<'tcx>,
|
||||
},
|
||||
/// This access is caused by a `match` or `if let` pattern.
|
||||
PatUse(Span),
|
||||
|
@ -567,22 +567,32 @@ pub(super) enum UseSpans {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub(super) enum FnSelfUseKind {
|
||||
pub(super) enum FnSelfUseKind<'tcx> {
|
||||
/// A normal method call of the form `receiver.foo(a, b, c)`
|
||||
Normal { self_arg: Ident, implicit_into_iter: bool },
|
||||
/// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
|
||||
FnOnceCall,
|
||||
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
|
||||
Operator { self_arg: Ident },
|
||||
DerefCoercion {
|
||||
/// The `Span` of the `Target` associated type
|
||||
/// in the `Deref` impl we are using.
|
||||
deref_target: Span,
|
||||
/// The type `T::Deref` we are dereferencing to
|
||||
deref_target_ty: Ty<'tcx>,
|
||||
},
|
||||
}
|
||||
|
||||
impl UseSpans {
|
||||
impl UseSpans<'_> {
|
||||
pub(super) fn args_or_use(self) -> Span {
|
||||
match self {
|
||||
UseSpans::ClosureUse { args_span: span, .. }
|
||||
| UseSpans::PatUse(span)
|
||||
| UseSpans::FnSelfUse { var_span: span, .. }
|
||||
| UseSpans::OtherUse(span) => span,
|
||||
UseSpans::FnSelfUse {
|
||||
fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
|
||||
} => fn_call_span,
|
||||
UseSpans::FnSelfUse { var_span, .. } => var_span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,8 +600,11 @@ impl UseSpans {
|
|||
match self {
|
||||
UseSpans::ClosureUse { var_span: span, .. }
|
||||
| UseSpans::PatUse(span)
|
||||
| UseSpans::FnSelfUse { var_span: span, .. }
|
||||
| UseSpans::OtherUse(span) => span,
|
||||
UseSpans::FnSelfUse {
|
||||
fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
|
||||
} => fn_call_span,
|
||||
UseSpans::FnSelfUse { var_span, .. } => var_span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,7 +767,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
&self,
|
||||
moved_place: PlaceRef<'tcx>, // Could also be an upvar.
|
||||
location: Location,
|
||||
) -> UseSpans {
|
||||
) -> UseSpans<'tcx> {
|
||||
use self::UseSpans::*;
|
||||
|
||||
let stmt = match self.body[location.block].statements.get(location.statement_index) {
|
||||
|
@ -809,36 +822,64 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
|
||||
}) = &self.body[location.block].terminator
|
||||
{
|
||||
let method_did = if let Some(method_did) =
|
||||
let (method_did, method_substs) = if let Some(info) =
|
||||
crate::util::find_self_call(self.infcx.tcx, &self.body, target_temp, location.block)
|
||||
{
|
||||
method_did
|
||||
info
|
||||
} else {
|
||||
return normal_ret;
|
||||
};
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
let parent = tcx.parent(method_did);
|
||||
let is_fn_once = parent == tcx.lang_items().fn_once_trait();
|
||||
let is_operator = !from_hir_call
|
||||
&& parent.map_or(false, |p| tcx.lang_items().group(LangItemGroup::Op).contains(&p));
|
||||
let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
|
||||
let fn_call_span = *fn_span;
|
||||
|
||||
let self_arg = tcx.fn_arg_names(method_did)[0];
|
||||
|
||||
debug!(
|
||||
"terminator = {:?} from_hir_call={:?}",
|
||||
self.body[location.block].terminator, from_hir_call
|
||||
);
|
||||
|
||||
// Check for a 'special' use of 'self' -
|
||||
// an FnOnce call, an operator (e.g. `<<`), or a
|
||||
// deref coercion.
|
||||
let kind = if is_fn_once {
|
||||
FnSelfUseKind::FnOnceCall
|
||||
Some(FnSelfUseKind::FnOnceCall)
|
||||
} else if is_operator {
|
||||
FnSelfUseKind::Operator { self_arg }
|
||||
Some(FnSelfUseKind::Operator { self_arg })
|
||||
} else if is_deref {
|
||||
let deref_target =
|
||||
tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
|
||||
Instance::resolve(tcx, self.param_env, deref_target, method_substs)
|
||||
.transpose()
|
||||
});
|
||||
if let Some(Ok(instance)) = deref_target {
|
||||
let deref_target_ty = instance.ty(tcx, self.param_env);
|
||||
Some(FnSelfUseKind::DerefCoercion {
|
||||
deref_target: tcx.def_span(instance.def_id()),
|
||||
deref_target_ty,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let kind = kind.unwrap_or_else(|| {
|
||||
// This isn't a 'special' use of `self`
|
||||
debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
|
||||
let implicit_into_iter = matches!(
|
||||
fn_call_span.desugaring_kind(),
|
||||
Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
|
||||
);
|
||||
FnSelfUseKind::Normal { self_arg, implicit_into_iter }
|
||||
};
|
||||
});
|
||||
|
||||
return FnSelfUse {
|
||||
var_span: stmt.source_info.span,
|
||||
|
@ -859,7 +900,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
/// and its usage of the local assigned at `location`.
|
||||
/// This is done by searching in statements succeeding `location`
|
||||
/// and originating from `maybe_closure_span`.
|
||||
pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans {
|
||||
pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans<'tcx> {
|
||||
use self::UseSpans::*;
|
||||
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
|
||||
|
||||
|
@ -963,7 +1004,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
/// Helper to retrieve span(s) of given borrow from the current MIR
|
||||
/// representation
|
||||
pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans {
|
||||
pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans<'tcx> {
|
||||
let span = self.body.source_info(borrow.reserve_location).span;
|
||||
self.borrow_spans(span, borrow.reserve_location)
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ enum GroupedMoveError<'tcx> {
|
|||
// Everything that isn't from pattern matching.
|
||||
OtherIllegalMove {
|
||||
original_path: Place<'tcx>,
|
||||
use_spans: UseSpans,
|
||||
use_spans: UseSpans<'tcx>,
|
||||
kind: IllegalMoveOriginKind<'tcx>,
|
||||
},
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let (mut err, err_span) = {
|
||||
let (span, use_spans, original_path, kind): (
|
||||
Span,
|
||||
Option<UseSpans>,
|
||||
Option<UseSpans<'tcx>>,
|
||||
Place<'tcx>,
|
||||
&IllegalMoveOriginKind<'_>,
|
||||
) = match error {
|
||||
|
@ -291,7 +291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
move_place: Place<'tcx>,
|
||||
deref_target_place: Place<'tcx>,
|
||||
span: Span,
|
||||
use_spans: Option<UseSpans>,
|
||||
use_spans: Option<UseSpans<'tcx>>,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
// Inspect the type of the content behind the
|
||||
// borrow to provide feedback about why this
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind
|
|||
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, InstanceDef, RegionVid, TyCtxt};
|
||||
use rustc_middle::ty::{self, InstanceDef, ParamEnv, RegionVid, TyCtxt};
|
||||
use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
|
||||
|
@ -287,6 +287,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
if let Err((move_data, move_errors)) = move_data_results {
|
||||
let mut promoted_mbcx = MirBorrowckCtxt {
|
||||
infcx,
|
||||
param_env,
|
||||
body: promoted_body,
|
||||
mir_def_id: def.did,
|
||||
move_data: &move_data,
|
||||
|
@ -320,6 +321,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
|
||||
let mut mbcx = MirBorrowckCtxt {
|
||||
infcx,
|
||||
param_env,
|
||||
body,
|
||||
mir_def_id: def.did,
|
||||
move_data: &mdpe.move_data,
|
||||
|
@ -473,6 +475,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
|
||||
crate struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
crate infcx: &'cx InferCtxt<'cx, 'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
body: &'cx Body<'tcx>,
|
||||
mir_def_id: LocalDefId,
|
||||
move_data: &'cx MoveData<'tcx>,
|
||||
|
|
|
@ -101,7 +101,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ConstMutationChecker<'a, 'tcx> {
|
|||
.note("each usage of a `const` item creates a new temporary")
|
||||
.note("the mutable reference will refer to this temporary, not the original `const` item");
|
||||
|
||||
if let Some(method_did) = method_did {
|
||||
if let Some((method_did, _substs)) = method_did {
|
||||
lint.span_note(self.tcx.def_span(method_did), "mutable reference created due to call to this method");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
/// Checks if the specified `local` is used as the `self` prameter of a method call
|
||||
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
|
||||
/// returned.
|
||||
pub fn find_self_call(
|
||||
tcx: TyCtxt<'_>,
|
||||
body: &Body<'_>,
|
||||
pub fn find_self_call<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
local: Local,
|
||||
block: BasicBlock,
|
||||
) -> Option<DefId> {
|
||||
) -> Option<(DefId, SubstsRef<'tcx>)> {
|
||||
debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
|
||||
if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
|
||||
&body[block].terminator
|
||||
{
|
||||
debug!("find_self_call: func={:?}", func);
|
||||
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
||||
if let ty::FnDef(def_id, _) = *ty.kind() {
|
||||
if let ty::FnDef(def_id, substs) = *ty.kind() {
|
||||
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
|
||||
tcx.opt_associated_item(def_id)
|
||||
{
|
||||
debug!("find_self_call: args={:?}", args);
|
||||
if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
|
||||
if self_place.as_local() == Some(local) {
|
||||
return Some(def_id);
|
||||
return Some((def_id, substs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,14 @@ fn apply_adjustment<'a, 'tcx>(
|
|||
},
|
||||
};
|
||||
|
||||
overloaded_place(cx, hir_expr, adjustment.target, Some(call), vec![expr.to_ref()])
|
||||
overloaded_place(
|
||||
cx,
|
||||
hir_expr,
|
||||
adjustment.target,
|
||||
Some(call),
|
||||
vec![expr.to_ref()],
|
||||
deref.span,
|
||||
)
|
||||
}
|
||||
Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
|
||||
ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: expr.to_ref() }
|
||||
|
@ -277,7 +284,14 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
|||
|
||||
hir::ExprKind::Index(ref lhs, ref index) => {
|
||||
if cx.typeck_results().is_method_call(expr) {
|
||||
overloaded_place(cx, expr, expr_ty, None, vec![lhs.to_ref(), index.to_ref()])
|
||||
overloaded_place(
|
||||
cx,
|
||||
expr,
|
||||
expr_ty,
|
||||
None,
|
||||
vec![lhs.to_ref(), index.to_ref()],
|
||||
expr.span,
|
||||
)
|
||||
} else {
|
||||
ExprKind::Index { lhs: lhs.to_ref(), index: index.to_ref() }
|
||||
}
|
||||
|
@ -285,7 +299,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
|||
|
||||
hir::ExprKind::Unary(hir::UnOp::UnDeref, ref arg) => {
|
||||
if cx.typeck_results().is_method_call(expr) {
|
||||
overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()])
|
||||
overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()], expr.span)
|
||||
} else {
|
||||
ExprKind::Deref { arg: arg.to_ref() }
|
||||
}
|
||||
|
@ -1025,6 +1039,7 @@ fn overloaded_place<'a, 'tcx>(
|
|||
place_ty: Ty<'tcx>,
|
||||
overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
|
||||
args: Vec<ExprRef<'tcx>>,
|
||||
span: Span,
|
||||
) -> ExprKind<'tcx> {
|
||||
// For an overloaded *x or x[y] expression of type T, the method
|
||||
// call returns an &T and we must add the deref so that the types
|
||||
|
@ -1040,24 +1055,24 @@ fn overloaded_place<'a, 'tcx>(
|
|||
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
||||
let (region, mutbl) = match *recv_ty.kind() {
|
||||
ty::Ref(region, _, mutbl) => (region, mutbl),
|
||||
_ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"),
|
||||
_ => span_bug!(span, "overloaded_place: receiver is not a reference"),
|
||||
};
|
||||
let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
|
||||
|
||||
// construct the complete expression `foo()` for the overloaded call,
|
||||
// which will yield the &T type
|
||||
let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
|
||||
let fun = method_callee(cx, expr, expr.span, overloaded_callee);
|
||||
let fun = method_callee(cx, expr, span, overloaded_callee);
|
||||
let ref_expr = Expr {
|
||||
temp_lifetime,
|
||||
ty: ref_ty,
|
||||
span: expr.span,
|
||||
span,
|
||||
kind: ExprKind::Call {
|
||||
ty: fun.ty,
|
||||
fun: fun.to_ref(),
|
||||
args,
|
||||
from_hir_call: false,
|
||||
fn_span: expr.span,
|
||||
fn_span: span,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -416,7 +416,9 @@ symbols! {
|
|||
deny,
|
||||
deprecated,
|
||||
deref,
|
||||
deref_method,
|
||||
deref_mut,
|
||||
deref_target,
|
||||
derive,
|
||||
diagnostic,
|
||||
direct,
|
||||
|
|
|
@ -654,6 +654,7 @@ supported_targets! {
|
|||
("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
|
||||
("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
|
||||
("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
|
||||
("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
|
||||
("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
|
||||
("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
|
||||
("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
use crate::spec::{CodeModel, LinkerFlavor, Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
Ok(Target {
|
||||
llvm_target: "riscv32-unknown-linux-gnu".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "32".to_string(),
|
||||
target_c_int_width: "32".to_string(),
|
||||
target_env: "gnu".to_string(),
|
||||
data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
|
||||
arch: "riscv32".to_string(),
|
||||
target_os: "linux".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
linker_flavor: LinkerFlavor::Gcc,
|
||||
options: TargetOptions {
|
||||
unsupported_abis: super::riscv_base::unsupported_abis(),
|
||||
code_model: Some(CodeModel::Medium),
|
||||
cpu: "generic-rv32".to_string(),
|
||||
features: "+m,+a,+f,+d,+c".to_string(),
|
||||
llvm_abiname: "ilp32d".to_string(),
|
||||
max_atomic_width: Some(32),
|
||||
..super::linux_base::opts()
|
||||
},
|
||||
})
|
||||
}
|
|
@ -27,6 +27,7 @@ pub struct Autoderef<'a, 'tcx> {
|
|||
// Meta infos:
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
overloaded_span: Span,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
|
@ -98,10 +99,12 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||
body_id: hir::HirId,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
overloaded_span: Span,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef {
|
||||
infcx,
|
||||
span,
|
||||
overloaded_span,
|
||||
body_id,
|
||||
param_env,
|
||||
state: AutoderefSnapshot {
|
||||
|
@ -190,6 +193,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||
self.span
|
||||
}
|
||||
|
||||
pub fn overloaded_span(&self) -> Span {
|
||||
self.overloaded_span
|
||||
}
|
||||
|
||||
pub fn reached_recursion_limit(&self) -> bool {
|
||||
self.state.reached_recursion_limit
|
||||
}
|
||||
|
|
|
@ -483,7 +483,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
|
||||
let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty);
|
||||
let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span);
|
||||
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
|
||||
// Re-add the `&`
|
||||
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
|
||||
|
|
|
@ -12,7 +12,18 @@ use std::iter;
|
|||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
|
||||
}
|
||||
|
||||
/// Like `autoderef`, but provides a custom `Span` to use for calls to
|
||||
/// an overloaded `Deref` operator
|
||||
pub fn autoderef_overloaded_span(
|
||||
&'a self,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
overloaded_span: Span,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
|
||||
}
|
||||
|
||||
pub fn try_overloaded_deref(
|
||||
|
@ -44,7 +55,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|InferOk { value: method, obligations: o }| {
|
||||
obligations.extend(o);
|
||||
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
|
||||
Some(OverloadedDeref { region, mutbl })
|
||||
Some(OverloadedDeref {
|
||||
region,
|
||||
mutbl,
|
||||
span: autoderef.overloaded_span(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -137,7 +137,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
) -> Ty<'tcx> {
|
||||
// Commit the autoderefs by calling `autoderef` again, but this
|
||||
// time writing the results into the various typeck results.
|
||||
let mut autoderef = self.autoderef(self.span, unadjusted_self_ty);
|
||||
let mut autoderef =
|
||||
self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
|
||||
let (_, n) = match autoderef.nth(pick.autoderefs) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
|
|
|
@ -446,9 +446,10 @@ fn method_autoderef_steps<'tcx>(
|
|||
tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &goal, |ref infcx, goal, inference_vars| {
|
||||
let ParamEnvAnd { param_env, value: self_ty } = goal;
|
||||
|
||||
let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
|
||||
.include_raw_pointers()
|
||||
.silence_errors();
|
||||
let mut autoderef =
|
||||
Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
|
||||
.include_raw_pointers()
|
||||
.silence_errors();
|
||||
let mut reached_raw_pointer = false;
|
||||
let mut steps: Vec<_> = autoderef
|
||||
.by_ref()
|
||||
|
|
|
@ -242,7 +242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
let method = self.register_infer_ok_obligations(ok);
|
||||
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
|
||||
*deref = OverloadedDeref { region, mutbl };
|
||||
*deref = OverloadedDeref { region, mutbl, span: deref.span };
|
||||
}
|
||||
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
|
||||
// This helps avoid accidental drops.
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#![feature(slice_ptr_get)]
|
||||
#![feature(split_inclusive)]
|
||||
#![feature(binary_heap_retain)]
|
||||
#![feature(deque_range)]
|
||||
#![feature(inplace_iteration)]
|
||||
#![feature(iter_map_while)]
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
use std::collections::TryReserveError::*;
|
||||
use std::mem::size_of;
|
||||
use std::ops::Bound::*;
|
||||
|
||||
pub trait IntoCow<'a, B: ?Sized>
|
||||
where
|
||||
|
@ -271,8 +272,8 @@ fn test_split_off_past_end() {
|
|||
#[test]
|
||||
#[should_panic]
|
||||
fn test_split_off_mid_char() {
|
||||
let mut orig = String::from("山");
|
||||
let _ = orig.split_off(1);
|
||||
let mut shan = String::from("山");
|
||||
let _broken_mountain = shan.split_off(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -467,6 +468,20 @@ fn test_drain() {
|
|||
assert_eq!(t, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_drain_start_overflow() {
|
||||
let mut s = String::from("abc");
|
||||
s.drain((Excluded(usize::MAX), Included(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_drain_end_overflow() {
|
||||
let mut s = String::from("abc");
|
||||
s.drain((Included(0), Included(usize::MAX)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_range() {
|
||||
let mut s = "Hello, world!".to_owned();
|
||||
|
@ -504,6 +519,20 @@ fn test_replace_range_inclusive_out_of_bounds() {
|
|||
s.replace_range(5..=5, "789");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_replace_range_start_overflow() {
|
||||
let mut s = String::from("123");
|
||||
s.replace_range((Excluded(usize::MAX), Included(0)), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_replace_range_end_overflow() {
|
||||
let mut s = String::from("456");
|
||||
s.replace_range((Included(0), Included(usize::MAX)), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_range_empty() {
|
||||
let mut s = String::from("12345");
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::TryReserveError::*;
|
|||
use std::fmt::Debug;
|
||||
use std::iter::InPlaceIterable;
|
||||
use std::mem::size_of;
|
||||
use std::ops::Bound::*;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::rc::Rc;
|
||||
use std::vec::{Drain, IntoIter};
|
||||
|
@ -645,6 +646,16 @@ fn test_drain_max_vec_size() {
|
|||
assert_eq!(v.len(), usize::MAX - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_drain_index_overflow() {
|
||||
let mut v = Vec::<()>::with_capacity(usize::MAX);
|
||||
unsafe {
|
||||
v.set_len(usize::MAX);
|
||||
}
|
||||
v.drain(0..=usize::MAX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_drain_inclusive_out_of_bounds() {
|
||||
|
@ -652,6 +663,20 @@ fn test_drain_inclusive_out_of_bounds() {
|
|||
v.drain(5..=5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_drain_start_overflow() {
|
||||
let mut v = vec![1, 2, 3];
|
||||
v.drain((Excluded(usize::MAX), Included(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_drain_end_overflow() {
|
||||
let mut v = vec![1, 2, 3];
|
||||
v.drain((Included(0), Included(usize::MAX)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_drain_leak() {
|
||||
static mut DROPS: i32 = 0;
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::TryReserveError::*;
|
|||
use std::collections::{vec_deque::Drain, VecDeque};
|
||||
use std::fmt::Debug;
|
||||
use std::mem::size_of;
|
||||
use std::ops::Bound::*;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
|
||||
use crate::hash;
|
||||
|
@ -115,6 +116,20 @@ fn test_index_out_of_bounds() {
|
|||
deq[3];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_range_start_overflow() {
|
||||
let deq = VecDeque::from(vec![1, 2, 3]);
|
||||
deq.range((Included(0), Included(usize::MAX)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_range_end_overflow() {
|
||||
let deq = VecDeque::from(vec![1, 2, 3]);
|
||||
deq.range((Excluded(usize::MAX), Included(0)));
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
enum Taggy {
|
||||
One(i32),
|
||||
|
|
|
@ -356,8 +356,9 @@ impl Ordering {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[rustc_const_stable(feature = "const_ordering", since = "1.48.0")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn reverse(self) -> Ordering {
|
||||
pub const fn reverse(self) -> Ordering {
|
||||
match self {
|
||||
Less => Greater,
|
||||
Equal => Equal,
|
||||
|
@ -394,8 +395,9 @@ impl Ordering {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[rustc_const_stable(feature = "const_ordering", since = "1.48.0")]
|
||||
#[stable(feature = "ordering_chaining", since = "1.17.0")]
|
||||
pub fn then(self, other: Ordering) -> Ordering {
|
||||
pub const fn then(self, other: Ordering) -> Ordering {
|
||||
match self {
|
||||
Equal => other,
|
||||
_ => self,
|
||||
|
|
|
@ -63,11 +63,13 @@
|
|||
pub trait Deref {
|
||||
/// The resulting type after dereferencing.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "deref_target"]
|
||||
type Target: ?Sized;
|
||||
|
||||
/// Dereferences the value.
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "deref_method"]
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use core::cmp::{self, Ordering::*};
|
||||
use core::cmp::{
|
||||
self,
|
||||
Ordering::{self, *},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_int_totalord() {
|
||||
|
@ -116,3 +119,16 @@ fn test_user_defined_eq() {
|
|||
assert!(SketchyNum { num: 37 } == SketchyNum { num: 34 });
|
||||
assert!(SketchyNum { num: 25 } != SketchyNum { num: 57 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ordering_const() {
|
||||
// test that the methods of `Ordering` are usable in a const context
|
||||
|
||||
const ORDERING: Ordering = Greater;
|
||||
|
||||
const REVERSE: Ordering = ORDERING.reverse();
|
||||
assert_eq!(REVERSE, Less);
|
||||
|
||||
const THEN: Ordering = Equal.then(ORDERING);
|
||||
assert_eq!(THEN, Greater);
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
//! [`Read`]: io::Read
|
||||
|
||||
#![stable(feature = "process", since = "1.0.0")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
|
||||
mod tests;
|
||||
|
@ -321,7 +322,8 @@ impl Read for ChildStdout {
|
|||
|
||||
#[inline]
|
||||
unsafe fn initializer(&self) -> Initializer {
|
||||
Initializer::nop()
|
||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
||||
unsafe { Initializer::nop() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +383,8 @@ impl Read for ChildStderr {
|
|||
|
||||
#[inline]
|
||||
unsafe fn initializer(&self) -> Initializer {
|
||||
Initializer::nop()
|
||||
// SAFETY: Read is guaranteed to work on uninitialized memory
|
||||
unsafe { Initializer::nop() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,308 +0,0 @@
|
|||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::{unsupported, Void};
|
||||
|
||||
pub struct File(Void);
|
||||
|
||||
pub struct FileAttr(Void);
|
||||
|
||||
pub struct ReadDir(Void);
|
||||
|
||||
pub struct DirEntry(Void);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {}
|
||||
|
||||
pub struct FilePermissions(Void);
|
||||
|
||||
pub struct FileType(Void);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> FileAttr {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> FilePermissions {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileType {
|
||||
fn clone(&self) -> FileType {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for FileType {}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
fn eq(&self, _other: &FileType) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FileType {}
|
||||
|
||||
impl Hash for FileType {
|
||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenOptions {
|
||||
pub fn new() -> OpenOptions {
|
||||
OpenOptions {}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, _read: bool) {}
|
||||
pub fn write(&mut self, _write: bool) {}
|
||||
pub fn append(&mut self, _append: bool) {}
|
||||
pub fn truncate(&mut self, _truncate: bool) {}
|
||||
pub fn create(&mut self, _create: bool) {}
|
||||
pub fn create_new(&mut self, _create_new: bool) {}
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn diverge(&self) -> ! {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
pub fn new() -> DirBuilder {
|
||||
DirBuilder {}
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn unlink(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
match perm.0 {}
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
|
||||
unsupported()
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
use crate::mem;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct IoSlice<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> IoSlice<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
IoSlice(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
self.0 = &self.0[n..]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IoSliceMut<'a>(&'a mut [u8]);
|
||||
|
||||
impl<'a> IoSliceMut<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
IoSliceMut(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
let slice = mem::replace(&mut self.0, &mut []);
|
||||
let (_, remaining) = slice.split_at_mut(n);
|
||||
self.0 = remaining;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
|
@ -17,14 +17,18 @@ pub mod condvar;
|
|||
pub mod env;
|
||||
pub mod ext;
|
||||
pub mod fd;
|
||||
#[path = "../unsupported/fs.rs"]
|
||||
pub mod fs;
|
||||
#[path = "../unsupported/io.rs"]
|
||||
pub mod io;
|
||||
pub mod memchr;
|
||||
pub mod mutex;
|
||||
pub mod net;
|
||||
pub mod os;
|
||||
pub mod path;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
#[path = "../unsupported/process.rs"]
|
||||
pub mod process;
|
||||
pub mod rwlock;
|
||||
pub mod stack_overflow;
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::sys::Void;
|
||||
|
||||
pub struct AnonPipe(Void);
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn diverge(&self) -> ! {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
match p1.0 {}
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
use crate::ffi::OsStr;
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::pipe::AnonPipe;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::sys_common::process::CommandEnv;
|
||||
|
||||
pub use crate::ffi::OsString as EnvKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct Command {
|
||||
env: CommandEnv,
|
||||
}
|
||||
|
||||
// passed back to std::process with the pipes connected to the child, if any
|
||||
// were requested
|
||||
pub struct StdioPipes {
|
||||
pub stdin: Option<AnonPipe>,
|
||||
pub stdout: Option<AnonPipe>,
|
||||
pub stderr: Option<AnonPipe>,
|
||||
}
|
||||
|
||||
pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
MakePipe,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(_program: &OsStr) -> Command {
|
||||
Command { env: Default::default() }
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, _arg: &OsStr) {}
|
||||
|
||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||
&mut self.env
|
||||
}
|
||||
|
||||
pub fn cwd(&mut self, _dir: &OsStr) {}
|
||||
|
||||
pub fn stdin(&mut self, _stdin: Stdio) {}
|
||||
|
||||
pub fn stdout(&mut self, _stdout: Stdio) {}
|
||||
|
||||
pub fn stderr(&mut self, _stderr: Stdio) {}
|
||||
|
||||
pub fn spawn(
|
||||
&mut self,
|
||||
_default: Stdio,
|
||||
_needs_stdin: bool,
|
||||
) -> io::Result<(Process, StdioPipes)> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
pipe.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(file: File) -> Stdio {
|
||||
file.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExitStatus(Void);
|
||||
|
||||
impl ExitStatus {
|
||||
pub fn success(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn code(&self) -> Option<i32> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ExitStatus {
|
||||
fn clone(&self) -> ExitStatus {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for ExitStatus {}
|
||||
|
||||
impl PartialEq for ExitStatus {
|
||||
fn eq(&self, _other: &ExitStatus) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExitStatus {}
|
||||
|
||||
impl fmt::Debug for ExitStatus {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ExitStatus {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(bool);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(false);
|
||||
pub const FAILURE: ExitCode = ExitCode(true);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Process(Void);
|
||||
|
||||
impl Process {
|
||||
pub fn id(&self) -> u32 {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn kill(&mut self) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
|
@ -52,46 +52,48 @@ unsafe impl GlobalAlloc for System {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris"
|
||||
))]
|
||||
#[inline]
|
||||
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
||||
// On android we currently target API level 9 which unfortunately
|
||||
// doesn't have the `posix_memalign` API used below. Instead we use
|
||||
// `memalign`, but this unfortunately has the property on some systems
|
||||
// where the memory returned cannot be deallocated by `free`!
|
||||
//
|
||||
// Upon closer inspection, however, this appears to work just fine with
|
||||
// Android, so for this platform we should be fine to call `memalign`
|
||||
// (which is present in API level 9). Some helpful references could
|
||||
// possibly be chromium using memalign [1], attempts at documenting that
|
||||
// memalign + free is ok [2] [3], or the current source of chromium
|
||||
// which still uses memalign on android [4].
|
||||
//
|
||||
// [1]: https://codereview.chromium.org/10796020/
|
||||
// [2]: https://code.google.com/p/android/issues/detail?id=35391
|
||||
// [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
|
||||
// [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
|
||||
// /memory/aligned_memory.cc
|
||||
libc::memalign(layout.align(), layout.size()) as *mut u8
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
#[inline]
|
||||
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
||||
let mut out = ptr::null_mut();
|
||||
// posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
|
||||
// Since these are all powers of 2, we can just use max.
|
||||
let align = layout.align().max(crate::mem::size_of::<usize>());
|
||||
let ret = libc::posix_memalign(&mut out, align, layout.size());
|
||||
if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris"
|
||||
))] {
|
||||
#[inline]
|
||||
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
||||
// On android we currently target API level 9 which unfortunately
|
||||
// doesn't have the `posix_memalign` API used below. Instead we use
|
||||
// `memalign`, but this unfortunately has the property on some systems
|
||||
// where the memory returned cannot be deallocated by `free`!
|
||||
//
|
||||
// Upon closer inspection, however, this appears to work just fine with
|
||||
// Android, so for this platform we should be fine to call `memalign`
|
||||
// (which is present in API level 9). Some helpful references could
|
||||
// possibly be chromium using memalign [1], attempts at documenting that
|
||||
// memalign + free is ok [2] [3], or the current source of chromium
|
||||
// which still uses memalign on android [4].
|
||||
//
|
||||
// [1]: https://codereview.chromium.org/10796020/
|
||||
// [2]: https://code.google.com/p/android/issues/detail?id=35391
|
||||
// [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
|
||||
// [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
|
||||
// /memory/aligned_memory.cc
|
||||
libc::memalign(layout.align(), layout.size()) as *mut u8
|
||||
}
|
||||
} else if #[cfg(target_os = "wasi")] {
|
||||
#[inline]
|
||||
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
||||
libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
|
||||
}
|
||||
} else {
|
||||
#[inline]
|
||||
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
||||
let mut out = ptr::null_mut();
|
||||
// posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
|
||||
// Since these are all powers of 2, we can just use max.
|
||||
let align = layout.align().max(crate::mem::size_of::<usize>());
|
||||
let ret = libc::posix_memalign(&mut out, align, layout.size());
|
||||
if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -233,10 +233,6 @@ impl File {
|
|||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn diverge(&self) -> ! {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
|
|
|
@ -8,6 +8,7 @@ pub mod io;
|
|||
pub mod mutex;
|
||||
pub mod net;
|
||||
pub mod os;
|
||||
#[path = "../unix/path.rs"]
|
||||
pub mod path;
|
||||
pub mod pipe;
|
||||
pub mod process;
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
use crate::ffi::OsStr;
|
||||
use crate::path::Prefix;
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_verbatim_sep(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub const MAIN_SEP_STR: &str = "/";
|
||||
pub const MAIN_SEP: char = '/';
|
|
@ -65,8 +65,8 @@ impl From<AnonPipe> for Stdio {
|
|||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(file: File) -> Stdio {
|
||||
file.diverge()
|
||||
fn from(_file: File) -> Stdio {
|
||||
panic!("unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::alloc::{GlobalAlloc, Layout, System};
|
||||
use crate::ptr;
|
||||
use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
|
||||
|
||||
// SAFETY: All methods implemented follow the contract rules defined
|
||||
// in `GlobalAlloc`.
|
||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||
unsafe impl GlobalAlloc for System {
|
||||
#[inline]
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
|
||||
// SAFETY: `libc::malloc` is guaranteed to be safe, it will allocate
|
||||
// `layout.size()` bytes of memory and return a pointer to it
|
||||
unsafe { libc::malloc(layout.size()) as *mut u8 }
|
||||
} else {
|
||||
// SAFETY: `libc::aligned_alloc` is guaranteed to be safe if
|
||||
// `layout.size()` is a multiple of `layout.align()`. This
|
||||
// constraint can be satisfied if `pad_to_align` is called,
|
||||
// which creates a layout by rounding the size of this layout up
|
||||
// to a multiple of the layout's alignment
|
||||
let aligned_layout = layout.pad_to_align();
|
||||
unsafe { libc::aligned_alloc(aligned_layout.align(), aligned_layout.size()) as *mut u8 }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
|
||||
// SAFETY: `libc::calloc` is safe as long that `layout.size() * 1`
|
||||
// would not result in integer overflow which cannot happen,
|
||||
// multiplying by one never overflows
|
||||
unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
|
||||
} else {
|
||||
// SAFETY: The safety contract for `alloc` must be upheld by the caller
|
||||
let ptr = unsafe { self.alloc(layout.clone()) };
|
||||
if !ptr.is_null() {
|
||||
// SAFETY: in the case of the `ptr` being not null
|
||||
// it will be properly aligned and a valid ptr
|
||||
// which satisfies `ptr::write_bytes` safety constrains
|
||||
unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
|
||||
}
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
// SAFETY: `libc::free` is guaranteed to be safe if `ptr` is allocated
|
||||
// by this allocator or if `ptr` is NULL
|
||||
unsafe { libc::free(ptr as *mut libc::c_void) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
|
||||
// SAFETY: `libc::realloc` is safe if `ptr` is allocated by this
|
||||
// allocator or NULL
|
||||
// - If `new_size` is 0 and `ptr` is not NULL, it will act as `libc::free`
|
||||
// - If `new_size` is not 0 and `ptr` is NULL, it will act as `libc::malloc`
|
||||
// - Else, it will resize the block accordingly
|
||||
unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
|
||||
} else {
|
||||
// SAFETY: The safety contract for `realloc_fallback` must be upheld by the caller
|
||||
unsafe { realloc_fallback(self, ptr, layout, new_size) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
use crate::io as std_io;
|
||||
use crate::mem;
|
||||
|
||||
#[path = "../unix/alloc.rs"]
|
||||
pub mod alloc;
|
||||
pub mod args;
|
||||
#[path = "../unsupported/cmath.rs"]
|
||||
|
@ -33,8 +34,11 @@ pub mod net;
|
|||
pub mod os;
|
||||
pub use crate::sys_common::os_str_bytes as os_str;
|
||||
pub mod ext;
|
||||
#[path = "../unix/path.rs"]
|
||||
pub mod path;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
#[path = "../unsupported/process.rs"]
|
||||
pub mod process;
|
||||
#[path = "../unsupported/rwlock.rs"]
|
||||
pub mod rwlock;
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
use crate::ffi::OsStr;
|
||||
use crate::path::Prefix;
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_verbatim_sep(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub const MAIN_SEP_STR: &str = "/";
|
||||
pub const MAIN_SEP: char = '/';
|
|
@ -1,40 +0,0 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::sys::Void;
|
||||
|
||||
pub struct AnonPipe(Void);
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn diverge(&self) -> ! {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
match p1.0 {}
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::ffi::OsStr;
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::pipe::AnonPipe;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::sys_common::process::CommandEnv;
|
||||
|
||||
pub use crate::ffi::OsString as EnvKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct Command {
|
||||
env: CommandEnv,
|
||||
}
|
||||
|
||||
// passed back to std::process with the pipes connected to the child, if any
|
||||
// were requested
|
||||
pub struct StdioPipes {
|
||||
pub stdin: Option<AnonPipe>,
|
||||
pub stdout: Option<AnonPipe>,
|
||||
pub stderr: Option<AnonPipe>,
|
||||
}
|
||||
|
||||
pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
MakePipe,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(_program: &OsStr) -> Command {
|
||||
Command { env: Default::default() }
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, _arg: &OsStr) {}
|
||||
|
||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||
&mut self.env
|
||||
}
|
||||
|
||||
pub fn cwd(&mut self, _dir: &OsStr) {}
|
||||
|
||||
pub fn stdin(&mut self, _stdin: Stdio) {}
|
||||
|
||||
pub fn stdout(&mut self, _stdout: Stdio) {}
|
||||
|
||||
pub fn stderr(&mut self, _stderr: Stdio) {}
|
||||
|
||||
pub fn spawn(
|
||||
&mut self,
|
||||
_default: Stdio,
|
||||
_needs_stdin: bool,
|
||||
) -> io::Result<(Process, StdioPipes)> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
pipe.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(_file: File) -> Stdio {
|
||||
panic!("unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExitStatus(Void);
|
||||
|
||||
impl ExitStatus {
|
||||
pub fn success(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn code(&self) -> Option<i32> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ExitStatus {
|
||||
fn clone(&self) -> ExitStatus {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for ExitStatus {}
|
||||
|
||||
impl PartialEq for ExitStatus {
|
||||
fn eq(&self, _other: &ExitStatus) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExitStatus {}
|
||||
|
||||
impl fmt::Debug for ExitStatus {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ExitStatus {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(bool);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(false);
|
||||
pub const FAILURE: ExitCode = ExitCode(true);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Process(Void);
|
||||
|
||||
impl Process {
|
||||
pub fn id(&self) -> u32 {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn kill(&mut self) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ pub mod io;
|
|||
pub mod net;
|
||||
#[path = "../unsupported/os.rs"]
|
||||
pub mod os;
|
||||
#[path = "../unsupported/path.rs"]
|
||||
#[path = "../unix/path.rs"]
|
||||
pub mod path;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
|
|
|
@ -195,6 +195,7 @@ target | std | host | notes
|
|||
`powerpc64-unknown-linux-musl` | ? | |
|
||||
`powerpc64-wrs-vxworks` | ? | |
|
||||
`powerpc64le-unknown-linux-musl` | ? | |
|
||||
`riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33)
|
||||
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
|
||||
`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64
|
||||
`sparc64-unknown-openbsd` | ? | |
|
||||
|
|
|
@ -8,7 +8,7 @@ edition = "2018"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
pulldown-cmark = { version = "0.7", default-features = false }
|
||||
pulldown-cmark = { version = "0.8", default-features = false }
|
||||
minifier = "0.0.33"
|
||||
rayon = { version = "0.3.0", package = "rustc-rayon" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
@ -27,7 +27,6 @@ use rustc_session::lint;
|
|||
use rustc_span::edition::Edition;
|
||||
use rustc_span::Span;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::default::Default;
|
||||
use std::fmt::Write;
|
||||
|
@ -39,7 +38,7 @@ use crate::doctest;
|
|||
use crate::html::highlight;
|
||||
use crate::html::toc::TocBuilder;
|
||||
|
||||
use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
|
||||
use pulldown_cmark::{html, BrokenLink, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -931,15 +930,17 @@ impl Markdown<'_> {
|
|||
if md.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
let replacer = |_: &str, s: &str| {
|
||||
if let Some(link) = links.iter().find(|link| &*link.original_text == s) {
|
||||
Some((link.href.clone(), link.new_text.clone()))
|
||||
let mut replacer = |broken_link: BrokenLink<'_>| {
|
||||
if let Some(link) =
|
||||
links.iter().find(|link| &*link.original_text == broken_link.reference)
|
||||
{
|
||||
Some((link.href.as_str().into(), link.new_text.as_str().into()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let p = Parser::new_with_broken_link_callback(md, opts(), Some(&replacer));
|
||||
let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
|
||||
|
||||
let mut s = String::with_capacity(md.len() * 3 / 2);
|
||||
|
||||
|
@ -1009,9 +1010,11 @@ impl MarkdownSummaryLine<'_> {
|
|||
return String::new();
|
||||
}
|
||||
|
||||
let replacer = |_: &str, s: &str| {
|
||||
if let Some(link) = links.iter().find(|link| &*link.original_text == s) {
|
||||
Some((link.href.clone(), link.new_text.clone()))
|
||||
let mut replacer = |broken_link: BrokenLink<'_>| {
|
||||
if let Some(link) =
|
||||
links.iter().find(|link| &*link.original_text == broken_link.reference)
|
||||
{
|
||||
Some((link.href.as_str().into(), link.new_text.as_str().into()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1020,7 +1023,7 @@ impl MarkdownSummaryLine<'_> {
|
|||
let p = Parser::new_with_broken_link_callback(
|
||||
md,
|
||||
Options::ENABLE_STRIKETHROUGH,
|
||||
Some(&replacer),
|
||||
Some(&mut replacer),
|
||||
);
|
||||
|
||||
let mut s = String::new();
|
||||
|
@ -1067,7 +1070,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
|
|||
}
|
||||
|
||||
let mut links = vec![];
|
||||
let shortcut_links = RefCell::new(vec![]);
|
||||
let mut shortcut_links = vec![];
|
||||
|
||||
{
|
||||
let locate = |s: &str| unsafe {
|
||||
|
@ -1084,11 +1087,13 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
|
|||
}
|
||||
};
|
||||
|
||||
let push = |_: &str, s: &str| {
|
||||
shortcut_links.borrow_mut().push((s.to_owned(), locate(s)));
|
||||
let mut push = |link: BrokenLink<'_>| {
|
||||
// FIXME: use `link.span` instead of `locate`
|
||||
// (doing it now includes the `[]` as well as the text)
|
||||
shortcut_links.push((link.reference.to_owned(), locate(link.reference)));
|
||||
None
|
||||
};
|
||||
let p = Parser::new_with_broken_link_callback(md, opts(), Some(&push));
|
||||
let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push));
|
||||
|
||||
// There's no need to thread an IdMap through to here because
|
||||
// the IDs generated aren't going to be emitted anywhere.
|
||||
|
@ -1106,8 +1111,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut shortcut_links = shortcut_links.into_inner();
|
||||
links.extend(shortcut_links.drain(..));
|
||||
links.append(&mut shortcut_links);
|
||||
|
||||
links
|
||||
}
|
||||
|
|
78
src/test/codegen/issue-73396-bounds-check-after-position.rs
Normal file
78
src/test/codegen/issue-73396-bounds-check-after-position.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
// min-llvm-version: 11.0.0
|
||||
// compile-flags: -O
|
||||
// ignore-debug: the debug assertions get in the way
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Make sure no bounds checks are emitted when slicing or indexing
|
||||
// with an index from `position()` or `rposition()`.
|
||||
|
||||
// CHECK-LABEL: @position_slice_to_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
|
||||
// CHECK-NOT: panic
|
||||
// CHECK-NOT: slice_index_len_fail
|
||||
if let Some(idx) = s.iter().position(|b| *b == b'\\') {
|
||||
&s[..idx]
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @position_slice_from_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
|
||||
// CHECK-NOT: panic
|
||||
// CHECK-NOT: slice_index_len_fail
|
||||
if let Some(idx) = s.iter().position(|b| *b == b'\\') {
|
||||
&s[idx..]
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @position_index_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
|
||||
// CHECK-NOT: panic
|
||||
// CHECK-NOT: slice_index_len_fail
|
||||
if let Some(idx) = s.iter().position(|b| *b == b'\\') {
|
||||
s[idx]
|
||||
} else {
|
||||
42
|
||||
}
|
||||
}
|
||||
// CHECK-LABEL: @rposition_slice_to_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
|
||||
// CHECK-NOT: panic
|
||||
// CHECK-NOT: slice_index_len_fail
|
||||
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
|
||||
&s[..idx]
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @rposition_slice_from_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
|
||||
// CHECK-NOT: panic
|
||||
// CHECK-NOT: slice_index_len_fail
|
||||
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
|
||||
&s[idx..]
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @rposition_index_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
|
||||
// CHECK-NOT: panic
|
||||
// CHECK-NOT: slice_index_len_fail
|
||||
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
|
||||
s[idx]
|
||||
} else {
|
||||
42
|
||||
}
|
||||
}
|
7
src/test/rustdoc-ui/intra-link-double-anchor.rs
Normal file
7
src/test/rustdoc-ui/intra-link-double-anchor.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
// check-pass
|
||||
|
||||
// regression test for #73264
|
||||
// should only give one error
|
||||
/// docs [label][with#anchor#error]
|
||||
//~^ WARNING multiple anchors
|
||||
pub struct S;
|
10
src/test/rustdoc-ui/intra-link-double-anchor.stderr
Normal file
10
src/test/rustdoc-ui/intra-link-double-anchor.stderr
Normal file
|
@ -0,0 +1,10 @@
|
|||
warning: `with#anchor#error` contains multiple anchors
|
||||
--> $DIR/intra-link-double-anchor.rs:5:18
|
||||
|
|
||||
LL | /// docs [label][with#anchor#error]
|
||||
| ^^^^^^^^^^^^^^^^^ contains invalid anchor
|
||||
|
|
||||
= note: `#[warn(broken_intra_doc_links)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
|
@ -149,7 +149,7 @@ error: function cannot return without recursing
|
|||
LL | fn deref(&self) -> &Baz {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL | self.as_ref()
|
||||
| ---- recursive call site
|
||||
| ------------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
|
|
33
src/test/ui/moves/move-deref-coercion.rs
Normal file
33
src/test/ui/moves/move-deref-coercion.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
struct NotCopy {
|
||||
inner: bool
|
||||
}
|
||||
|
||||
impl NotCopy {
|
||||
fn inner_method(&self) {}
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
first: NotCopy,
|
||||
second: NotCopy
|
||||
}
|
||||
|
||||
impl Deref for Foo {
|
||||
type Target = NotCopy;
|
||||
fn deref(&self) -> &NotCopy {
|
||||
&self.second
|
||||
}
|
||||
}
|
||||
|
||||
fn use_field(val: Foo) {
|
||||
let _val = val.first;
|
||||
val.inner; //~ ERROR borrow of
|
||||
}
|
||||
|
||||
fn use_method(val: Foo) {
|
||||
let _val = val.first;
|
||||
val.inner_method(); //~ ERROR borrow of
|
||||
}
|
||||
|
||||
fn main() {}
|
35
src/test/ui/moves/move-deref-coercion.stderr
Normal file
35
src/test/ui/moves/move-deref-coercion.stderr
Normal file
|
@ -0,0 +1,35 @@
|
|||
error[E0382]: borrow of partially moved value: `val`
|
||||
--> $DIR/move-deref-coercion.rs:25:5
|
||||
|
|
||||
LL | let _val = val.first;
|
||||
| --------- value partially moved here
|
||||
LL | val.inner;
|
||||
| ^^^^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait
|
||||
= note: borrow occurs due to deref coercion to `NotCopy`
|
||||
note: deref defined here
|
||||
--> $DIR/move-deref-coercion.rs:17:5
|
||||
|
|
||||
LL | type Target = NotCopy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0382]: borrow of partially moved value: `val`
|
||||
--> $DIR/move-deref-coercion.rs:30:5
|
||||
|
|
||||
LL | let _val = val.first;
|
||||
| --------- value partially moved here
|
||||
LL | val.inner_method();
|
||||
| ^^^^^^^^^^^^^^^^^^ value borrowed here after partial move
|
||||
|
|
||||
= note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait
|
||||
= note: borrow occurs due to deref coercion to `NotCopy`
|
||||
note: deref defined here
|
||||
--> $DIR/move-deref-coercion.rs:17:5
|
||||
|
|
||||
LL | type Target = NotCopy;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
|
@ -1,5 +1,5 @@
|
|||
error[E0382]: borrow of moved value: `arc_v`
|
||||
--> $DIR/no-capture-arc.rs:14:18
|
||||
--> $DIR/no-capture-arc.rs:14:16
|
||||
|
|
||||
LL | let arc_v = Arc::new(v);
|
||||
| ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait
|
||||
|
@ -10,7 +10,14 @@ LL | assert_eq!((*arc_v)[3], 4);
|
|||
| ----- variable moved due to use in closure
|
||||
...
|
||||
LL | assert_eq!((*arc_v)[2], 3);
|
||||
| ^^^^^ value borrowed here after move
|
||||
| ^^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: borrow occurs due to deref coercion to `Vec<i32>`
|
||||
note: deref defined here
|
||||
--> $SRC_DIR/alloc/src/sync.rs:LL:COL
|
||||
|
|
||||
LL | type Target = T;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0382]: borrow of moved value: `arc_v`
|
||||
--> $DIR/no-reuse-move-arc.rs:12:18
|
||||
--> $DIR/no-reuse-move-arc.rs:12:16
|
||||
|
|
||||
LL | let arc_v = Arc::new(v);
|
||||
| ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait
|
||||
|
@ -10,7 +10,14 @@ LL | assert_eq!((*arc_v)[3], 4);
|
|||
| ----- variable moved due to use in closure
|
||||
...
|
||||
LL | assert_eq!((*arc_v)[2], 3);
|
||||
| ^^^^^ value borrowed here after move
|
||||
| ^^^^^^^^ value borrowed here after move
|
||||
|
|
||||
= note: borrow occurs due to deref coercion to `Vec<i32>`
|
||||
note: deref defined here
|
||||
--> $SRC_DIR/alloc/src/sync.rs:LL:COL
|
||||
|
|
||||
LL | type Target = T;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 875e0123259b0b6299903fe4aea0a12ecde9324f
|
||||
Subproject commit 8777a6b1e8834899f51b7e09cc9b8d85b2417110
|
Loading…
Add table
Add a link
Reference in a new issue