mirror of https://github.com/rust-lang/rust.git
Auto merge of #73635 - Dylan-DPC:rollup-b4wbp42, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #71756 (add Windows system error codes that should map to io::ErrorKind::TimedOut) - #73495 (Converted all platform-specific stdin/stdout/stderr implementations to use io:: traits) - #73575 (Fix typo in error_codes doc) - #73578 (Make is_freeze and is_copy_modulo_regions take TyCtxtAt) - #73586 (switch_ty is redundant) - #73600 (Fix spurious 'value moved here in previous iteration of loop' messages) - #73610 (Clean up E0699 explanation) Failed merges: r? @ghost
This commit is contained in:
commit
3b1c08c68c
|
@ -200,6 +200,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
targets: &Vec<mir::BasicBlock>,
|
||||
) {
|
||||
let discr = self.codegen_operand(&mut bx, &discr);
|
||||
// `switch_ty` is redundant, sanity-check that.
|
||||
assert_eq!(discr.layout.ty, switch_ty);
|
||||
if targets.len() == 2 {
|
||||
// If there are two targets, emit br instead of switch
|
||||
let lltrue = helper.llblock(self, targets[0]);
|
||||
|
|
|
@ -74,7 +74,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
|
|||
}
|
||||
|
||||
fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all(), DUMMY_SP)
|
||||
ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all())
|
||||
}
|
||||
|
||||
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
A discrimant value is present more than once.
|
||||
A discriminant value is present more than once.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
A method was called on a raw pointer whose inner type wasn't completely known.
|
||||
|
||||
For example, you may have done something like:
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
```compile_fail,edition2018,E0699
|
||||
# #![deny(warnings)]
|
||||
# fn main() {
|
||||
let foo = &1;
|
||||
let bar = foo as *const _;
|
||||
if bar.is_null() {
|
||||
// ...
|
||||
}
|
||||
# }
|
||||
```
|
||||
|
||||
Here, the type of `bar` isn't known; it could be a pointer to anything. Instead,
|
||||
|
|
|
@ -562,7 +562,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
|
|||
return;
|
||||
}
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
if ty.is_copy_modulo_regions(cx.tcx, param_env, item.span) {
|
||||
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
|
||||
return;
|
||||
}
|
||||
if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() {
|
||||
|
|
|
@ -1075,6 +1075,8 @@ pub enum TerminatorKind<'tcx> {
|
|||
discr: Operand<'tcx>,
|
||||
|
||||
/// The type of value being tested.
|
||||
/// This is always the same as the type of `discr`.
|
||||
/// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
|
||||
switch_ty: Ty<'tcx>,
|
||||
|
||||
/// Possible values. The locations to branch to in each case
|
||||
|
|
|
@ -2159,7 +2159,7 @@ where
|
|||
|
||||
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
|
||||
let tcx = cx.tcx();
|
||||
let is_freeze = ty.is_freeze(tcx, cx.param_env(), DUMMY_SP);
|
||||
let is_freeze = ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env());
|
||||
let kind = match mt {
|
||||
hir::Mutability::Not => {
|
||||
if is_freeze {
|
||||
|
|
|
@ -681,11 +681,10 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||
/// winds up being reported as an error during NLL borrow check.
|
||||
pub fn is_copy_modulo_regions(
|
||||
&'tcx self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
tcx_at: TyCtxtAt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
tcx.at(span).is_copy_raw(param_env.and(self))
|
||||
tcx_at.is_copy_raw(param_env.and(self))
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` have a size known at
|
||||
|
@ -706,13 +705,8 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||
/// that the `Freeze` trait is not exposed to end users and is
|
||||
/// effectively an implementation detail.
|
||||
// FIXME: use `TyCtxtAt` instead of separate `Span`.
|
||||
pub fn is_freeze(
|
||||
&'tcx self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
self.is_trivially_freeze() || tcx.at(span).is_freeze_raw(param_env.and(self))
|
||||
pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self))
|
||||
}
|
||||
|
||||
/// Fast path helper for testing if a type is `Freeze`.
|
||||
|
|
|
@ -138,7 +138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
|
||||
|
||||
if span == move_span {
|
||||
if location == move_out.source {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("value moved{} here, in previous iteration of loop", move_msg),
|
||||
|
|
|
@ -233,7 +233,7 @@ impl MutBorrow<'mir, 'tcx> {
|
|||
///
|
||||
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
|
||||
fn shared_borrow_allows_mutation(&self, place: Place<'tcx>) -> bool {
|
||||
!place.ty(self.body, self.tcx).ty.is_freeze(self.tcx, self.param_env, DUMMY_SP)
|
||||
!place.ty(self.body, self.tcx).ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
#[inline]
|
||||
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_freeze(*self.tcx, self.param_env, self.tcx.span)
|
||||
ty.is_freeze(self.tcx, self.param_env)
|
||||
}
|
||||
|
||||
pub fn load_mir(
|
||||
|
|
|
@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
|||
if let InternMode::Static(mutability) = mode {
|
||||
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
|
||||
// no interior mutability.
|
||||
let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env, ecx.tcx.span));
|
||||
let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env));
|
||||
// For statics, allocation mutability is the combination of the place mutability and
|
||||
// the type mutability.
|
||||
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
|
||||
|
|
|
@ -24,9 +24,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
|
||||
Goto { target } => self.go_to_block(target),
|
||||
|
||||
SwitchInt { ref discr, ref values, ref targets, .. } => {
|
||||
SwitchInt { ref discr, ref values, ref targets, switch_ty } => {
|
||||
let discr = self.read_immediate(self.eval_operand(discr, None)?)?;
|
||||
trace!("SwitchInt({:?})", *discr);
|
||||
assert_eq!(discr.layout.ty, switch_ty);
|
||||
|
||||
// Branch to the `otherwise` case by default, if no match is found.
|
||||
assert!(!targets.is_empty());
|
||||
|
@ -50,14 +51,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.go_to_block(target_block);
|
||||
}
|
||||
|
||||
Call {
|
||||
ref func,
|
||||
ref args,
|
||||
destination,
|
||||
ref cleanup,
|
||||
from_hir_call: _from_hir_call,
|
||||
fn_span: _,
|
||||
} => {
|
||||
Call { ref func, ref args, destination, ref cleanup, from_hir_call: _, fn_span: _ } => {
|
||||
let old_stack = self.frame_idx();
|
||||
let old_loc = self.frame().loc;
|
||||
let func = self.eval_operand(func, None)?;
|
||||
|
|
|
@ -327,7 +327,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
|
|||
let param_env = tcx.param_env(def_id);
|
||||
|
||||
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
|
||||
let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env, builder.span);
|
||||
let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env);
|
||||
|
||||
let dest = Place::return_place();
|
||||
let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));
|
||||
|
|
|
@ -77,7 +77,7 @@ impl Qualif for HasMutInterior {
|
|||
}
|
||||
|
||||
fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
!ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP)
|
||||
!ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env)
|
||||
}
|
||||
|
||||
fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
|
||||
|
|
|
@ -282,9 +282,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
|||
),
|
||||
};
|
||||
if !elem_ty.is_copy_modulo_regions(
|
||||
self.tcx,
|
||||
self.tcx.at(self.source_info.span),
|
||||
self.param_env,
|
||||
self.source_info.span,
|
||||
) {
|
||||
self.require_unsafe(
|
||||
"assignment to non-`Copy` union field",
|
||||
|
@ -459,11 +458,11 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
|
|||
|
||||
// Check `is_freeze` as late as possible to avoid cycle errors
|
||||
// with opaque types.
|
||||
} else if !place.ty(self.body, self.tcx).ty.is_freeze(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
self.source_info.span,
|
||||
) {
|
||||
} else if !place
|
||||
.ty(self.body, self.tcx)
|
||||
.ty
|
||||
.is_freeze(self.tcx.at(self.source_info.span), self.param_env)
|
||||
{
|
||||
(
|
||||
"borrow of layout constrained field with interior \
|
||||
mutability",
|
||||
|
|
|
@ -341,7 +341,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
Place::ty_from(place.local, proj_base, self.body, self.tcx)
|
||||
.projection_ty(self.tcx, elem)
|
||||
.ty;
|
||||
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
|
||||
if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) {
|
||||
has_mut_interior = false;
|
||||
break;
|
||||
}
|
||||
|
@ -678,7 +678,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||
let ty = Place::ty_from(place.local, proj_base, self.body, self.tcx)
|
||||
.projection_ty(self.tcx, elem)
|
||||
.ty;
|
||||
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
|
||||
if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) {
|
||||
has_mut_interior = false;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
|
||||
let span = self.body.source_info(location).span;
|
||||
|
||||
if !ty.is_copy_modulo_regions(self.tcx, self.param_env, span) {
|
||||
if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) {
|
||||
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
TerminatorKind::Goto { target } => {
|
||||
self.check_edge(location, *target, EdgeKind::Normal);
|
||||
}
|
||||
TerminatorKind::SwitchInt { targets, values, .. } => {
|
||||
TerminatorKind::SwitchInt { targets, values, switch_ty, discr } => {
|
||||
let ty = discr.ty(&self.body.local_decls, self.tcx);
|
||||
if ty != *switch_ty {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"encountered `SwitchInt` terminator with type mismatch: {:?} != {:?}",
|
||||
ty, switch_ty,
|
||||
),
|
||||
);
|
||||
}
|
||||
if targets.len() != values.len() + 1 {
|
||||
self.fail(
|
||||
location,
|
||||
|
|
|
@ -172,7 +172,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
if !ty.is_sized(tcx.at(span), param_env) {
|
||||
// !sized means !copy, so this is an unsized move
|
||||
assert!(!ty.is_copy_modulo_regions(tcx, param_env, span));
|
||||
assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env));
|
||||
|
||||
// As described above, detect the case where we are passing a value of unsized
|
||||
// type, and that value is coming from the deref of a box.
|
||||
|
|
|
@ -579,7 +579,7 @@ fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[super::Pat<'_>]) -> Vec<Span>
|
|||
|
||||
/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`.
|
||||
fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> bool {
|
||||
!cx.tables.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env, span)
|
||||
!cx.tables.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env)
|
||||
}
|
||||
|
||||
/// Check the legality of legality of by-move bindings.
|
||||
|
|
|
@ -214,7 +214,7 @@ impl ExprVisitor<'tcx> {
|
|||
|
||||
// Check that the type implements Copy. The only case where this can
|
||||
// possibly fail is for SIMD types which don't #[derive(Copy)].
|
||||
if !ty.is_copy_modulo_regions(self.tcx, self.param_env, DUMMY_SP) {
|
||||
if !ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), self.param_env) {
|
||||
let msg = "arguments for inline assembly must be copyable";
|
||||
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
|
||||
err.note(&format!("`{}` does not implement the Copy trait", ty));
|
||||
|
|
|
@ -44,7 +44,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
|
|||
let ty = self.resolve_vars_if_possible(&ty);
|
||||
|
||||
if !(param_env, ty).needs_infer() {
|
||||
return ty.is_copy_modulo_regions(self.tcx, param_env, span);
|
||||
return ty.is_copy_modulo_regions(self.tcx.at(span), param_env);
|
||||
}
|
||||
|
||||
let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
|
||||
|
|
|
@ -91,7 +91,7 @@ where
|
|||
|
||||
for component in components {
|
||||
match component.kind {
|
||||
_ if component.is_copy_modulo_regions(tcx, self.param_env, DUMMY_SP) => (),
|
||||
_ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
|
||||
|
||||
ty::Closure(_, substs) => {
|
||||
for upvar_ty in substs.as_closure().upvar_tys() {
|
||||
|
|
|
@ -160,6 +160,11 @@ pub enum ErrorKind {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Interrupted,
|
||||
/// Any I/O error not part of this list.
|
||||
///
|
||||
/// Errors that are `Other` now may move to a different or a new
|
||||
/// [`ErrorKind`] variant in the future. It is not recommended to match
|
||||
/// an error against `Other` and to expect any additional characteristics,
|
||||
/// e.g., a specific [`Error::raw_os_error`] return value.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Other,
|
||||
|
||||
|
|
|
@ -10,19 +10,19 @@ impl Stdin {
|
|||
pub fn new() -> io::Result<Stdin> {
|
||||
Ok(Stdin)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
|
||||
self.read_vectored(&mut [IoSliceMut::new(data)])
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
//ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
|
||||
// .read(data)
|
||||
fn read_vectored(&mut self, _data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
fn is_read_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,10 @@ impl Stdout {
|
|||
pub fn new() -> io::Result<Stdout> {
|
||||
Ok(Stdout)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
|
||||
|
@ -44,7 +46,7 @@ impl Stdout {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
|
||||
|
@ -57,11 +59,11 @@ impl Stdout {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +72,10 @@ impl Stderr {
|
|||
pub fn new() -> io::Result<Stderr> {
|
||||
Ok(Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
|
||||
|
@ -83,7 +87,7 @@ impl Stderr {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
|
||||
|
@ -96,21 +100,12 @@ impl Stderr {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
(&*self).write(data)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
(&*self).flush()
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,22 +11,25 @@ impl Stdin {
|
|||
Ok(Stdin)
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
|
||||
self.read_vectored(&mut [IoSliceMut::new(data)])
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
fn read_vectored(&mut self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
fn is_read_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn as_raw_fd(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl Stdout {
|
||||
|
@ -34,26 +37,28 @@ impl Stdout {
|
|||
Ok(Stdout)
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
self.write_vectored(&[IoSlice::new(data)])
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn as_raw_fd(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
|
@ -61,23 +66,7 @@ impl Stderr {
|
|||
Ok(Stderr)
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
self.write_vectored(&[IoSlice::new(data)])
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn as_raw_fd(&self) -> u32 {
|
||||
2
|
||||
}
|
||||
|
@ -85,11 +74,20 @@ impl Stderr {
|
|||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
(&*self).write(data)
|
||||
self.write_vectored(&[IoSlice::new(data)])
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
(&*self).flush()
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,8 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
|
|||
|
||||
pub const PROGRESS_CONTINUE: DWORD = 0;
|
||||
|
||||
// List of Windows system error codes with descriptions:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes
|
||||
pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
|
||||
pub const ERROR_PATH_NOT_FOUND: DWORD = 3;
|
||||
pub const ERROR_ACCESS_DENIED: DWORD = 5;
|
||||
|
@ -171,13 +173,26 @@ pub const ERROR_FILE_EXISTS: DWORD = 80;
|
|||
pub const ERROR_INVALID_PARAMETER: DWORD = 87;
|
||||
pub const ERROR_BROKEN_PIPE: DWORD = 109;
|
||||
pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
|
||||
pub const ERROR_SEM_TIMEOUT: DWORD = 121;
|
||||
pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
|
||||
pub const ERROR_ALREADY_EXISTS: DWORD = 183;
|
||||
pub const ERROR_NO_DATA: DWORD = 232;
|
||||
pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203;
|
||||
pub const ERROR_NO_DATA: DWORD = 232;
|
||||
pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594;
|
||||
pub const ERROR_OPERATION_ABORTED: DWORD = 995;
|
||||
pub const ERROR_IO_PENDING: DWORD = 997;
|
||||
pub const ERROR_TIMEOUT: DWORD = 0x5B4;
|
||||
pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053;
|
||||
pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121;
|
||||
pub const ERROR_TIMEOUT: DWORD = 1460;
|
||||
pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910;
|
||||
pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012;
|
||||
pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040;
|
||||
pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014;
|
||||
pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226;
|
||||
pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705;
|
||||
pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805;
|
||||
pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402;
|
||||
pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403;
|
||||
|
||||
pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT;
|
||||
|
||||
|
|
|
@ -61,7 +61,22 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
|||
c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound,
|
||||
c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound,
|
||||
c::ERROR_NO_DATA => return ErrorKind::BrokenPipe,
|
||||
c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut,
|
||||
c::ERROR_SEM_TIMEOUT
|
||||
| c::WAIT_TIMEOUT
|
||||
| c::ERROR_DRIVER_CANCEL_TIMEOUT
|
||||
| c::ERROR_OPERATION_ABORTED
|
||||
| c::ERROR_SERVICE_REQUEST_TIMEOUT
|
||||
| c::ERROR_COUNTER_TIMEOUT
|
||||
| c::ERROR_TIMEOUT
|
||||
| c::ERROR_RESOURCE_CALL_TIMED_OUT
|
||||
| c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT
|
||||
| c::ERROR_CTX_CLIENT_QUERY_TIMEOUT
|
||||
| c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT
|
||||
| c::ERROR_DS_TIMELIMIT_EXCEEDED
|
||||
| c::DNS_ERROR_RECORD_TIMED_OUT
|
||||
| c::ERROR_IPSEC_IKE_TIMED_OUT
|
||||
| c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
|
||||
| c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Regression test for issue #46099
|
||||
// Tests that we don't emit spurious
|
||||
// 'value moved in previous iteration of loop' message
|
||||
|
||||
macro_rules! test {
|
||||
($v:expr) => {{
|
||||
drop(&$v);
|
||||
$v
|
||||
}}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = Box::new(true);
|
||||
test!({b}); //~ ERROR use of moved value
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
error[E0382]: use of moved value: `b`
|
||||
--> $DIR/issue-46099-move-in-macro.rs:14:12
|
||||
|
|
||||
LL | let b = Box::new(true);
|
||||
| - move occurs because `b` has type `std::boxed::Box<bool>`, which does not implement the `Copy` trait
|
||||
LL | test!({b});
|
||||
| ^
|
||||
| |
|
||||
| value moved here
|
||||
| value used here after move
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
|
@ -5,7 +5,10 @@ LL | let x: Box<_> = box 1;
|
|||
| - move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | (_, 2) if take(x) => (),
|
||||
| ^ value moved here, in previous iteration of loop
|
||||
| ^
|
||||
| |
|
||||
| value moved here
|
||||
| value used here after move
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ fn is_mutable_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span,
|
|||
// primitive types are never mutable
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
|
||||
ty::Adt(ref adt, ref substs) => {
|
||||
tys.insert(adt.did) && !ty.is_freeze(cx.tcx, cx.param_env, span)
|
||||
tys.insert(adt.did) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
|
||||
|| KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path))
|
||||
&& substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
|
||||
},
|
||||
|
|
|
@ -74,9 +74,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
|
|||
let span = stmt.span.to(if_.span);
|
||||
|
||||
let has_interior_mutability = !cx.tables.node_type(canonical_id).is_freeze(
|
||||
cx.tcx,
|
||||
cx.tcx.at(span),
|
||||
cx.param_env,
|
||||
span
|
||||
);
|
||||
if has_interior_mutability { return; }
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ fn is_mutable_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Spa
|
|||
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span)
|
||||
},
|
||||
Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)),
|
||||
Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env, span),
|
||||
Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(span), cx.param_env),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ impl Source {
|
|||
}
|
||||
|
||||
fn verify_ty_bound<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, source: Source) {
|
||||
if ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) || is_copy(cx, ty) {
|
||||
if ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) || is_copy(cx, ty) {
|
||||
// An `UnsafeCell` is `!Copy`, and an `UnsafeCell` is also the only type which
|
||||
// is `!Freeze`, thus if our type is `Copy` we can be sure it must be `Freeze`
|
||||
// as well.
|
||||
|
|
|
@ -137,7 +137,7 @@ impl QuestionMark {
|
|||
fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
|
||||
let expr_ty = cx.tables.expr_ty(expression);
|
||||
|
||||
!expr_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, expression.span)
|
||||
!expr_ty.is_copy_modulo_regions(cx.tcx.at(expression.span), cx.param_env)
|
||||
}
|
||||
|
||||
fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
|
||||
|
|
|
@ -891,7 +891,7 @@ pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx
|
|||
}
|
||||
|
||||
pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_copy_modulo_regions(cx.tcx, cx.param_env, DUMMY_SP)
|
||||
ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
|
||||
}
|
||||
|
||||
/// Checks if an expression is constructing a tuple-like enum variant or struct
|
||||
|
|
Loading…
Reference in New Issue