Auto merge of #92518 - matthiaskrgr:rollup-fl8z4e7, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #90102 (Remove `NullOp::Box`)
 - #92011 (Use field span in `rustc_macros` when emitting decode call)
 - #92402 (Suggest while let x = y when encountering while x = y)
 - #92409 (Couple of libtest cleanups)
 - #92418 (Fix spacing in pretty printed PatKind::Struct with no fields)
 - #92444 (Consolidate Result's and Option's methods into fewer impl blocks)

Failed merges:

 - #92483 (Stabilize `result_cloned` and `result_copied`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-01-03 14:30:36 +00:00
commit ddabe0775c
31 changed files with 563 additions and 600 deletions

View file

@ -2461,7 +2461,11 @@ impl<'a> State<'a> {
self.print_path(path, true, 0);
}
self.nbsp();
self.word_space("{");
self.word("{");
let empty = fields.is_empty() && !etc;
if !empty {
self.space();
}
self.commasep_cmnt(
Consistent,
&fields,
@ -2482,7 +2486,9 @@ impl<'a> State<'a> {
}
self.word("..");
}
self.space();
if !empty {
self.space();
}
self.word("}");
}
PatKind::Tuple(ref elts) => {

View file

@ -1394,10 +1394,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Rvalue::NullaryOp(_op, _ty) => {
// nullary ops take no dynamic input; no borrowck effect.
//
// FIXME: is above actually true? Do we want to track
// the fact that uninitialized data can be created via
// `NullOp::Box`?
}
Rvalue::Aggregate(ref aggregate_kind, ref operands) => {

View file

@ -715,30 +715,6 @@ fn codegen_stmt<'tcx>(
let operand = operand.load_scalar(fx);
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
}
Rvalue::NullaryOp(NullOp::Box, content_ty) => {
let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap();
let content_ty = fx.monomorphize(content_ty);
let layout = fx.layout_of(content_ty);
let llsize = fx.bcx.ins().iconst(usize_type, layout.size.bytes() as i64);
let llalign = fx.bcx.ins().iconst(usize_type, layout.align.abi.bytes() as i64);
let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty));
// Allocate space:
let def_id =
match fx.tcx.lang_items().require(rustc_hir::LangItem::ExchangeMalloc) {
Ok(id) => id,
Err(s) => {
fx.tcx
.sess
.fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
}
};
let instance = ty::Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
let func_ref = fx.get_function_ref(instance);
let call = fx.bcx.ins().call(func_ref, &[llsize, llalign]);
let ptr = fx.bcx.inst_results(call)[0];
lval.write_cvalue(fx, CValue::by_val(ptr, box_layout));
}
Rvalue::NullaryOp(null_op, ty) => {
assert!(
lval.layout()
@ -749,7 +725,6 @@ fn codegen_stmt<'tcx>(
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
NullOp::AlignOf => layout.align.abi.bytes(),
NullOp::Box => unreachable!(),
};
let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
lval.write_cvalue(fx, val);

View file

@ -8,7 +8,6 @@ use crate::traits::*;
use crate::MemFlags;
use rustc_apfloat::{ieee, Float, Round, Status};
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir;
use rustc_middle::ty::cast::{CastTy, IntTy};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
@ -486,31 +485,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
)
}
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
let content_ty = self.monomorphize(content_ty);
let content_layout = bx.cx().layout_of(content_ty);
let llsize = bx.cx().const_usize(content_layout.size.bytes());
let llalign = bx.cx().const_usize(content_layout.align.abi.bytes());
let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty));
let llty_ptr = bx.cx().backend_type(box_layout);
// Allocate space:
let def_id = match bx.tcx().lang_items().require(LangItem::ExchangeMalloc) {
Ok(id) => id,
Err(s) => {
bx.cx().sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
}
};
let instance = ty::Instance::mono(bx.tcx(), def_id);
let r = bx.cx().get_fn_addr(instance);
let ty = bx.type_func(&[bx.type_isize(), bx.type_isize()], bx.type_i8p());
let call = bx.call(ty, r, &[llsize, llalign], None);
let val = bx.pointercast(call, llty_ptr);
let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
(bx, operand)
}
mir::Rvalue::NullaryOp(null_op, ty) => {
let ty = self.monomorphize(ty);
assert!(bx.cx().type_is_sized(ty));
@ -518,7 +492,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let val = match null_op {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
mir::NullOp::Box => unreachable!(),
};
let val = bx.cx().const_usize(val);
let tcx = self.cx.tcx();

View file

@ -398,13 +398,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
}
fn box_alloc(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: &PlaceTy<'tcx>,
) -> InterpResult<'tcx> {
Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into())
}
fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
// The step limit has already been hit in a previous call to `before_terminator`.
if ecx.machine.steps_remaining == 0 {

View file

@ -156,7 +156,7 @@ pub enum StackPopCleanup {
/// `ret` stores the block we jump to on a normal return, while `unwind`
/// stores the block used for cleanup during unwinding.
Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind },
/// Just do nothing: Used by Main and for the `box_alloc` hook in miri.
/// Just do nothing: Used by Main and for TLS hooks in miri.
/// `cleanup` says whether locals are deallocated. Static computation
/// wants them leaked to intern what they need (and just throw away
/// the entire `ecx` when it is done).

View file

@ -212,12 +212,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
right: &ImmTy<'tcx, Self::PointerTag>,
) -> InterpResult<'tcx, (Scalar<Self::PointerTag>, bool, Ty<'tcx>)>;
/// Heap allocations via the `box` keyword.
fn box_alloc(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
dest: &PlaceTy<'tcx, Self::PointerTag>,
) -> InterpResult<'tcx>;
/// Called to read the specified `local` from the `frame`.
/// Since reading a ZST is not actually accessing memory or locals, this is never invoked
/// for ZST reads.

View file

@ -271,10 +271,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_immediate(place.to_ref(self), &dest)?;
}
NullaryOp(mir::NullOp::Box, _) => {
M::box_alloc(self, &dest)?;
}
NullaryOp(null_op, ty) => {
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
let layout = self.layout_of(ty)?;
@ -289,7 +285,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let val = match null_op {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
mir::NullOp::Box => unreachable!(),
};
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
}

View file

@ -632,7 +632,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
Rvalue::ShallowInitBox(_, _) => {}
Rvalue::UnaryOp(_, ref operand) => {

View file

@ -508,7 +508,6 @@ impl<'tcx> Validator<'_, 'tcx> {
}
Rvalue::NullaryOp(op, _) => match op {
NullOp::Box => return Err(Unpromotable),
NullOp::SizeOf => {}
NullOp::AlignOf => {}
},

View file

@ -1874,7 +1874,11 @@ impl<'a> State<'a> {
PatKind::Struct(ref qpath, ref fields, etc) => {
self.print_qpath(qpath, true);
self.nbsp();
self.word_space("{");
self.word("{");
let empty = fields.is_empty() && !etc;
if !empty {
self.space();
}
self.commasep_cmnt(
Consistent,
&fields,
@ -1895,7 +1899,9 @@ impl<'a> State<'a> {
}
self.word("..");
}
self.space();
if !empty {
self.space();
}
self.word("}");
}
PatKind::Or(ref pats) => {

View file

@ -1,6 +1,7 @@
use proc_macro2::TokenStream;
use quote::quote;
use quote::{quote, quote_spanned};
use syn::parse_quote;
use syn::spanned::Spanned;
pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
let decoder_ty = quote! { __D };
@ -104,6 +105,8 @@ fn decodable_body(
}
fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream {
let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span());
let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
} else {
@ -111,20 +114,21 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro
};
let (decode_method, opt_field_name) = if is_struct {
let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string());
(
proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()),
quote! { #field_name, },
)
(proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, })
} else {
(
proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()),
quote! {},
)
(proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {})
};
let __decoder = quote! { __decoder };
// Use the span of the field for the method call, so
// that backtraces will point to the field.
let decode_call = quote_spanned! {field_span=>
::rustc_serialize::Decoder::#decode_method(
#__decoder, #opt_field_name #decode_inner_method)
};
quote! {
match ::rustc_serialize::Decoder::#decode_method(
__decoder, #opt_field_name #decode_inner_method) {
match #decode_call {
::std::result::Result::Ok(__res) => __res,
::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
}

View file

@ -2336,8 +2336,6 @@ pub enum NullOp {
SizeOf,
/// Returns the minimum alignment of a type
AlignOf,
/// Creates a new uninitialized box for a value of that type
Box,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]

View file

@ -195,7 +195,6 @@ impl<'tcx> Rvalue<'tcx> {
}
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
@ -215,9 +214,7 @@ impl<'tcx> Rvalue<'tcx> {
/// whether its only shallowly initialized (`Rvalue::Box`).
pub fn initialization_state(&self) -> RvalueInitializationState {
match *self {
Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => {
RvalueInitializationState::Shallow
}
Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow,
_ => RvalueInitializationState::Deep,
}
}

View file

@ -343,19 +343,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| Rvalue::AddressOf(..)
| Rvalue::Discriminant(..)
| Rvalue::Len(..)
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
| Rvalue::NullaryOp(NullOp::Box, _) => {
// This returns an rvalue with uninitialized contents. We can't
// move out of it here because it is an rvalue - assignments always
// completely initialize their place.
//
// However, this does not matter - MIR building is careful to
// only emit a shallow free for the partially-initialized
// temporary.
//
// In any case, if we want to fix this, we have to register a
// special move and change the `statement_effect` functions.
}
| Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
}
}

View file

@ -239,13 +239,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp")
}
fn box_alloc(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: &PlaceTy<'tcx>,
) -> InterpResult<'tcx> {
throw_machine_stop_str!("can't const prop heap allocations")
}
fn access_local(
_ecx: &InterpCx<'mir, 'tcx, Self>,
frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,

View file

@ -688,15 +688,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
_ => bug!(),
}
}
mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => {
let tcx = self.tcx;
let exchange_malloc_fn_def_id =
tcx.require_lang_item(LangItem::ExchangeMalloc, None);
let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(self.tcx, instance, span));
}
}
mir::Rvalue::ThreadLocalRef(def_id) => {
assert!(self.tcx.is_thread_local_static(def_id));
let instance = Instance::mono(self.tcx, def_id);

View file

@ -2379,7 +2379,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::While(ref cond, ref block, label) => {
self.with_resolved_label(label, expr.id, |this| {
this.with_rib(ValueNS, NormalRibKind, |this| {
let old = this.diagnostic_metadata.in_if_condition.replace(cond);
this.visit_expr(cond);
this.diagnostic_metadata.in_if_condition = old;
this.visit_block(block);
})
});

View file

@ -810,6 +810,45 @@ impl<T> Option<T> {
}
}
/// Returns the contained [`Some`] value or a default.
///
/// Consumes the `self` argument then, if [`Some`], returns the contained
/// value, otherwise if [`None`], returns the [default value] for that
/// type.
///
/// # Examples
///
/// Converts a string to an integer, turning poorly-formed strings
/// into 0 (the default value for integers). [`parse`] converts
/// a string to any other type that implements [`FromStr`], returning
/// [`None`] on error.
///
/// ```
/// let good_year_from_input = "1909";
/// let bad_year_from_input = "190blarg";
/// let good_year = good_year_from_input.parse().ok().unwrap_or_default();
/// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default();
///
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
///
/// [default value]: Default::default
/// [`parse`]: str::parse
/// [`FromStr`]: crate::str::FromStr
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn unwrap_or_default(self) -> T
where
T: ~const Default,
{
match self {
Some(x) => x,
None => Default::default(),
}
}
/// Returns the contained [`Some`] value, consuming the `self` value,
/// without checking that the value is not [`None`].
///
@ -1033,6 +1072,58 @@ impl<T> Option<T> {
}
}
/// Converts from `Option<T>` (or `&Option<T>`) to `Option<&T::Target>`.
///
/// Leaves the original Option in-place, creating a new one with a reference
/// to the original one, additionally coercing the contents via [`Deref`].
///
/// # Examples
///
/// ```
/// let x: Option<String> = Some("hey".to_owned());
/// assert_eq!(x.as_deref(), Some("hey"));
///
/// let x: Option<String> = None;
/// assert_eq!(x.as_deref(), None);
/// ```
#[stable(feature = "option_deref", since = "1.40.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn as_deref(&self) -> Option<&T::Target>
where
T: ~const Deref,
{
match self.as_ref() {
Some(t) => Some(t.deref()),
None => None,
}
}
/// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
///
/// Leaves the original `Option` in-place, creating a new one containing a mutable reference to
/// the inner type's [`Deref::Target`] type.
///
/// # Examples
///
/// ```
/// let mut x: Option<String> = Some("hey".to_owned());
/// assert_eq!(x.as_deref_mut().map(|x| {
/// x.make_ascii_uppercase();
/// x
/// }), Some("HEY".to_owned().as_mut_str()));
/// ```
#[stable(feature = "option_deref", since = "1.40.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn as_deref_mut(&mut self) -> Option<&mut T::Target>
where
T: ~const DerefMut,
{
match self.as_mut() {
Some(t) => Some(t.deref_mut()),
None => None,
}
}
/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////
@ -1581,7 +1672,7 @@ impl<T, U> Option<(T, U)> {
}
}
impl<T: Copy> Option<&T> {
impl<T> Option<&T> {
/// Maps an `Option<&T>` to an `Option<T>` by copying the contents of the
/// option.
///
@ -1597,7 +1688,10 @@ impl<T: Copy> Option<&T> {
#[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "copied", since = "1.35.0")]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn copied(self) -> Option<T> {
pub const fn copied(self) -> Option<T>
where
T: Copy,
{
// FIXME: this implementation, which sidesteps using `Option::map` since it's not const
// ready yet, should be reverted when possible to avoid code repetition
match self {
@ -1605,33 +1699,7 @@ impl<T: Copy> Option<&T> {
None => None,
}
}
}
impl<T: Copy> Option<&mut T> {
/// Maps an `Option<&mut T>` to an `Option<T>` by copying the contents of the
/// option.
///
/// # Examples
///
/// ```
/// let mut x = 12;
/// let opt_x = Some(&mut x);
/// assert_eq!(opt_x, Some(&mut 12));
/// let copied = opt_x.copied();
/// assert_eq!(copied, Some(12));
/// ```
#[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "copied", since = "1.35.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn copied(self) -> Option<T> {
match self {
Some(&mut t) => Some(t),
None => None,
}
}
}
impl<T: Clone> Option<&T> {
/// Maps an `Option<&T>` to an `Option<T>` by cloning the contents of the
/// option.
///
@ -1658,7 +1726,32 @@ impl<T: Clone> Option<&T> {
}
}
impl<T: Clone> Option<&mut T> {
impl<T> Option<&mut T> {
/// Maps an `Option<&mut T>` to an `Option<T>` by copying the contents of the
/// option.
///
/// # Examples
///
/// ```
/// let mut x = 12;
/// let opt_x = Some(&mut x);
/// assert_eq!(opt_x, Some(&mut 12));
/// let copied = opt_x.copied();
/// assert_eq!(copied, Some(12));
/// ```
#[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "copied", since = "1.35.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn copied(self) -> Option<T>
where
T: Copy,
{
match self {
Some(&mut t) => Some(t),
None => None,
}
}
/// Maps an `Option<&mut T>` to an `Option<T>` by cloning the contents of the
/// option.
///
@ -1685,103 +1778,6 @@ impl<T: Clone> Option<&mut T> {
}
}
impl<T: Default> Option<T> {
/// Returns the contained [`Some`] value or a default.
///
/// Consumes the `self` argument then, if [`Some`], returns the contained
/// value, otherwise if [`None`], returns the [default value] for that
/// type.
///
/// # Examples
///
/// Converts a string to an integer, turning poorly-formed strings
/// into 0 (the default value for integers). [`parse`] converts
/// a string to any other type that implements [`FromStr`], returning
/// [`None`] on error.
///
/// ```
/// let good_year_from_input = "1909";
/// let bad_year_from_input = "190blarg";
/// let good_year = good_year_from_input.parse().ok().unwrap_or_default();
/// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default();
///
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
///
/// [default value]: Default::default
/// [`parse`]: str::parse
/// [`FromStr`]: crate::str::FromStr
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn unwrap_or_default(self) -> T
where
T: ~const Default,
{
match self {
Some(x) => x,
None => Default::default(),
}
}
}
impl<T: Deref> Option<T> {
/// Converts from `Option<T>` (or `&Option<T>`) to `Option<&T::Target>`.
///
/// Leaves the original Option in-place, creating a new one with a reference
/// to the original one, additionally coercing the contents via [`Deref`].
///
/// # Examples
///
/// ```
/// let x: Option<String> = Some("hey".to_owned());
/// assert_eq!(x.as_deref(), Some("hey"));
///
/// let x: Option<String> = None;
/// assert_eq!(x.as_deref(), None);
/// ```
#[stable(feature = "option_deref", since = "1.40.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn as_deref(&self) -> Option<&T::Target>
where
T: ~const Deref,
{
match self.as_ref() {
Some(t) => Some(t.deref()),
None => None,
}
}
}
impl<T: DerefMut> Option<T> {
/// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
///
/// Leaves the original `Option` in-place, creating a new one containing a mutable reference to
/// the inner type's [`Deref::Target`] type.
///
/// # Examples
///
/// ```
/// let mut x: Option<String> = Some("hey".to_owned());
/// assert_eq!(x.as_deref_mut().map(|x| {
/// x.make_ascii_uppercase();
/// x
/// }), Some("HEY".to_owned().as_mut_str()));
/// ```
#[stable(feature = "option_deref", since = "1.40.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
pub const fn as_deref_mut(&mut self) -> Option<&mut T::Target>
where
T: ~const DerefMut,
{
match self.as_mut() {
Some(t) => Some(t.deref_mut()),
None => None,
}
}
}
impl<T, E> Option<Result<T, E>> {
/// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`.
///

View file

@ -901,6 +901,56 @@ impl<T, E> Result<T, E> {
self
}
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&<T as Deref>::Target, &E>`.
///
/// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
/// and returns the new [`Result`].
///
/// # Examples
///
/// ```
/// let x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&str, &u32> = Ok("hello");
/// assert_eq!(x.as_deref(), y);
///
/// let x: Result<String, u32> = Err(42);
/// let y: Result<&str, &u32> = Err(&42);
/// assert_eq!(x.as_deref(), y);
/// ```
#[stable(feature = "inner_deref", since = "1.47.0")]
pub fn as_deref(&self) -> Result<&T::Target, &E>
where
T: Deref,
{
self.as_ref().map(|t| t.deref())
}
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut <T as DerefMut>::Target, &mut E>`.
///
/// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
/// and returns the new [`Result`].
///
/// # Examples
///
/// ```
/// let mut s = "HELLO".to_string();
/// let mut x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&mut str, &mut u32> = Ok(&mut s);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
///
/// let mut i = 42;
/// let mut x: Result<String, u32> = Err(42);
/// let y: Result<&mut str, &mut u32> = Err(&mut i);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
/// ```
#[stable(feature = "inner_deref", since = "1.47.0")]
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E>
where
T: DerefMut,
{
self.as_mut().map(|t| t.deref_mut())
}
/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////
@ -951,6 +1001,253 @@ impl<T, E> Result<T, E> {
IterMut { inner: self.as_mut().ok() }
}
/////////////////////////////////////////////////////////////////////////
// Extract a value
/////////////////////////////////////////////////////////////////////////
/// Returns the contained [`Ok`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is an [`Err`], with a panic message including the
/// passed message, and the content of the [`Err`].
///
///
/// # Examples
///
/// Basic usage:
///
/// ```should_panic
/// let x: Result<u32, &str> = Err("emergency failure");
/// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
/// ```
#[inline]
#[track_caller]
#[stable(feature = "result_expect", since = "1.4.0")]
pub fn expect(self, msg: &str) -> T
where
E: fmt::Debug,
{
match self {
Ok(t) => t,
Err(e) => unwrap_failed(msg, &e),
}
}
/// Returns the contained [`Ok`] value, consuming the `self` value.
///
/// Because this function may panic, its use is generally discouraged.
/// Instead, prefer to use pattern matching and handle the [`Err`]
/// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or
/// [`unwrap_or_default`].
///
/// [`unwrap_or`]: Result::unwrap_or
/// [`unwrap_or_else`]: Result::unwrap_or_else
/// [`unwrap_or_default`]: Result::unwrap_or_default
///
/// # Panics
///
/// Panics if the value is an [`Err`], with a panic message provided by the
/// [`Err`]'s value.
///
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.unwrap(), 2);
/// ```
///
/// ```should_panic
/// let x: Result<u32, &str> = Err("emergency failure");
/// x.unwrap(); // panics with `emergency failure`
/// ```
#[inline]
#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap(self) -> T
where
E: fmt::Debug,
{
match self {
Ok(t) => t,
Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e),
}
}
/// Returns the contained [`Ok`] value or a default
///
/// Consumes the `self` argument then, if [`Ok`], returns the contained
/// value, otherwise if [`Err`], returns the default value for that
/// type.
///
/// # Examples
///
/// Converts a string to an integer, turning poorly-formed strings
/// into 0 (the default value for integers). [`parse`] converts
/// a string to any other type that implements [`FromStr`], returning an
/// [`Err`] on error.
///
/// ```
/// let good_year_from_input = "1909";
/// let bad_year_from_input = "190blarg";
/// let good_year = good_year_from_input.parse().unwrap_or_default();
/// let bad_year = bad_year_from_input.parse().unwrap_or_default();
///
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
///
/// [`parse`]: str::parse
/// [`FromStr`]: crate::str::FromStr
#[inline]
#[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
pub fn unwrap_or_default(self) -> T
where
T: Default,
{
match self {
Ok(x) => x,
Err(_) => Default::default(),
}
}
/// Returns the contained [`Err`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is an [`Ok`], with a panic message including the
/// passed message, and the content of the [`Ok`].
///
///
/// # Examples
///
/// Basic usage:
///
/// ```should_panic
/// let x: Result<u32, &str> = Ok(10);
/// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
/// ```
#[inline]
#[track_caller]
#[stable(feature = "result_expect_err", since = "1.17.0")]
pub fn expect_err(self, msg: &str) -> E
where
T: fmt::Debug,
{
match self {
Ok(t) => unwrap_failed(msg, &t),
Err(e) => e,
}
}
/// Returns the contained [`Err`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is an [`Ok`], with a custom panic message provided
/// by the [`Ok`]'s value.
///
/// # Examples
///
/// ```should_panic
/// let x: Result<u32, &str> = Ok(2);
/// x.unwrap_err(); // panics with `2`
/// ```
///
/// ```
/// let x: Result<u32, &str> = Err("emergency failure");
/// assert_eq!(x.unwrap_err(), "emergency failure");
/// ```
#[inline]
#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_err(self) -> E
where
T: fmt::Debug,
{
match self {
Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t),
Err(e) => e,
}
}
/// Returns the contained [`Ok`] value, but never panics.
///
/// Unlike [`unwrap`], this method is known to never panic on the
/// result types it is implemented for. Therefore, it can be used
/// instead of `unwrap` as a maintainability safeguard that will fail
/// to compile if the error type of the `Result` is later changed
/// to an error that can actually occur.
///
/// [`unwrap`]: Result::unwrap
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
///
/// fn only_good_news() -> Result<String, !> {
/// Ok("this is fine".into())
/// }
///
/// let s: String = only_good_news().into_ok();
/// println!("{}", s);
/// ```
#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
#[inline]
pub fn into_ok(self) -> T
where
E: Into<!>,
{
match self {
Ok(x) => x,
Err(e) => e.into(),
}
}
/// Returns the contained [`Err`] value, but never panics.
///
/// Unlike [`unwrap_err`], this method is known to never panic on the
/// result types it is implemented for. Therefore, it can be used
/// instead of `unwrap_err` as a maintainability safeguard that will fail
/// to compile if the ok type of the `Result` is later changed
/// to a type that can actually occur.
///
/// [`unwrap_err`]: Result::unwrap_err
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
///
/// fn only_bad_news() -> Result<!, String> {
/// Err("Oops, it failed".into())
/// }
///
/// let error: String = only_bad_news().into_err();
/// println!("{}", error);
/// ```
#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
#[inline]
pub fn into_err(self) -> E
where
T: Into<!>,
{
match self {
Ok(x) => x.into(),
Err(e) => e,
}
}
////////////////////////////////////////////////////////////////////////
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
@ -1196,7 +1493,7 @@ impl<T, E> Result<T, E> {
}
}
impl<T: Copy, E> Result<&T, E> {
impl<T, E> Result<&T, E> {
/// Maps a `Result<&T, E>` to a `Result<T, E>` by copying the contents of the
/// `Ok` part.
///
@ -1211,32 +1508,13 @@ impl<T: Copy, E> Result<&T, E> {
/// assert_eq!(copied, Ok(12));
/// ```
#[unstable(feature = "result_copied", reason = "newly added", issue = "63168")]
pub fn copied(self) -> Result<T, E> {
pub fn copied(self) -> Result<T, E>
where
T: Copy,
{
self.map(|&t| t)
}
}
impl<T: Copy, E> Result<&mut T, E> {
/// Maps a `Result<&mut T, E>` to a `Result<T, E>` by copying the contents of the
/// `Ok` part.
///
/// # Examples
///
/// ```
/// #![feature(result_copied)]
/// let mut val = 12;
/// let x: Result<&mut i32, i32> = Ok(&mut val);
/// assert_eq!(x, Ok(&mut 12));
/// let copied = x.copied();
/// assert_eq!(copied, Ok(12));
/// ```
#[unstable(feature = "result_copied", reason = "newly added", issue = "63168")]
pub fn copied(self) -> Result<T, E> {
self.map(|&mut t| t)
}
}
impl<T: Clone, E> Result<&T, E> {
/// Maps a `Result<&T, E>` to a `Result<T, E>` by cloning the contents of the
/// `Ok` part.
///
@ -1251,12 +1529,36 @@ impl<T: Clone, E> Result<&T, E> {
/// assert_eq!(cloned, Ok(12));
/// ```
#[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")]
pub fn cloned(self) -> Result<T, E> {
pub fn cloned(self) -> Result<T, E>
where
T: Clone,
{
self.map(|t| t.clone())
}
}
impl<T: Clone, E> Result<&mut T, E> {
impl<T, E> Result<&mut T, E> {
/// Maps a `Result<&mut T, E>` to a `Result<T, E>` by copying the contents of the
/// `Ok` part.
///
/// # Examples
///
/// ```
/// #![feature(result_copied)]
/// let mut val = 12;
/// let x: Result<&mut i32, i32> = Ok(&mut val);
/// assert_eq!(x, Ok(&mut 12));
/// let copied = x.copied();
/// assert_eq!(copied, Ok(12));
/// ```
#[unstable(feature = "result_copied", reason = "newly added", issue = "63168")]
pub fn copied(self) -> Result<T, E>
where
T: Copy,
{
self.map(|&mut t| t)
}
/// Maps a `Result<&mut T, E>` to a `Result<T, E>` by cloning the contents of the
/// `Ok` part.
///
@ -1271,291 +1573,14 @@ impl<T: Clone, E> Result<&mut T, E> {
/// assert_eq!(cloned, Ok(12));
/// ```
#[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")]
pub fn cloned(self) -> Result<T, E> {
pub fn cloned(self) -> Result<T, E>
where
T: Clone,
{
self.map(|t| t.clone())
}
}
impl<T, E: fmt::Debug> Result<T, E> {
/// Returns the contained [`Ok`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is an [`Err`], with a panic message including the
/// passed message, and the content of the [`Err`].
///
///
/// # Examples
///
/// Basic usage:
///
/// ```should_panic
/// let x: Result<u32, &str> = Err("emergency failure");
/// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
/// ```
#[inline]
#[track_caller]
#[stable(feature = "result_expect", since = "1.4.0")]
pub fn expect(self, msg: &str) -> T {
match self {
Ok(t) => t,
Err(e) => unwrap_failed(msg, &e),
}
}
/// Returns the contained [`Ok`] value, consuming the `self` value.
///
/// Because this function may panic, its use is generally discouraged.
/// Instead, prefer to use pattern matching and handle the [`Err`]
/// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or
/// [`unwrap_or_default`].
///
/// [`unwrap_or`]: Result::unwrap_or
/// [`unwrap_or_else`]: Result::unwrap_or_else
/// [`unwrap_or_default`]: Result::unwrap_or_default
///
/// # Panics
///
/// Panics if the value is an [`Err`], with a panic message provided by the
/// [`Err`]'s value.
///
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.unwrap(), 2);
/// ```
///
/// ```should_panic
/// let x: Result<u32, &str> = Err("emergency failure");
/// x.unwrap(); // panics with `emergency failure`
/// ```
#[inline]
#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e),
}
}
}
impl<T: fmt::Debug, E> Result<T, E> {
/// Returns the contained [`Err`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is an [`Ok`], with a panic message including the
/// passed message, and the content of the [`Ok`].
///
///
/// # Examples
///
/// Basic usage:
///
/// ```should_panic
/// let x: Result<u32, &str> = Ok(10);
/// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
/// ```
#[inline]
#[track_caller]
#[stable(feature = "result_expect_err", since = "1.17.0")]
pub fn expect_err(self, msg: &str) -> E {
match self {
Ok(t) => unwrap_failed(msg, &t),
Err(e) => e,
}
}
/// Returns the contained [`Err`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the value is an [`Ok`], with a custom panic message provided
/// by the [`Ok`]'s value.
///
/// # Examples
///
/// ```should_panic
/// let x: Result<u32, &str> = Ok(2);
/// x.unwrap_err(); // panics with `2`
/// ```
///
/// ```
/// let x: Result<u32, &str> = Err("emergency failure");
/// assert_eq!(x.unwrap_err(), "emergency failure");
/// ```
#[inline]
#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_err(self) -> E {
match self {
Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t),
Err(e) => e,
}
}
}
impl<T: Default, E> Result<T, E> {
/// Returns the contained [`Ok`] value or a default
///
/// Consumes the `self` argument then, if [`Ok`], returns the contained
/// value, otherwise if [`Err`], returns the default value for that
/// type.
///
/// # Examples
///
/// Converts a string to an integer, turning poorly-formed strings
/// into 0 (the default value for integers). [`parse`] converts
/// a string to any other type that implements [`FromStr`], returning an
/// [`Err`] on error.
///
/// ```
/// let good_year_from_input = "1909";
/// let bad_year_from_input = "190blarg";
/// let good_year = good_year_from_input.parse().unwrap_or_default();
/// let bad_year = bad_year_from_input.parse().unwrap_or_default();
///
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
///
/// [`parse`]: str::parse
/// [`FromStr`]: crate::str::FromStr
#[inline]
#[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
pub fn unwrap_or_default(self) -> T {
match self {
Ok(x) => x,
Err(_) => Default::default(),
}
}
}
#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
impl<T, E: Into<!>> Result<T, E> {
/// Returns the contained [`Ok`] value, but never panics.
///
/// Unlike [`unwrap`], this method is known to never panic on the
/// result types it is implemented for. Therefore, it can be used
/// instead of `unwrap` as a maintainability safeguard that will fail
/// to compile if the error type of the `Result` is later changed
/// to an error that can actually occur.
///
/// [`unwrap`]: Result::unwrap
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
///
/// fn only_good_news() -> Result<String, !> {
/// Ok("this is fine".into())
/// }
///
/// let s: String = only_good_news().into_ok();
/// println!("{}", s);
/// ```
#[inline]
pub fn into_ok(self) -> T {
match self {
Ok(x) => x,
Err(e) => e.into(),
}
}
}
#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
impl<T: Into<!>, E> Result<T, E> {
/// Returns the contained [`Err`] value, but never panics.
///
/// Unlike [`unwrap_err`], this method is known to never panic on the
/// result types it is implemented for. Therefore, it can be used
/// instead of `unwrap_err` as a maintainability safeguard that will fail
/// to compile if the ok type of the `Result` is later changed
/// to a type that can actually occur.
///
/// [`unwrap_err`]: Result::unwrap_err
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
///
/// fn only_bad_news() -> Result<!, String> {
/// Err("Oops, it failed".into())
/// }
///
/// let error: String = only_bad_news().into_err();
/// println!("{}", error);
/// ```
#[inline]
pub fn into_err(self) -> E {
match self {
Ok(x) => x.into(),
Err(e) => e,
}
}
}
impl<T: Deref, E> Result<T, E> {
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&<T as Deref>::Target, &E>`.
///
/// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
/// and returns the new [`Result`].
///
/// # Examples
///
/// ```
/// let x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&str, &u32> = Ok("hello");
/// assert_eq!(x.as_deref(), y);
///
/// let x: Result<String, u32> = Err(42);
/// let y: Result<&str, &u32> = Err(&42);
/// assert_eq!(x.as_deref(), y);
/// ```
#[stable(feature = "inner_deref", since = "1.47.0")]
pub fn as_deref(&self) -> Result<&T::Target, &E> {
self.as_ref().map(|t| t.deref())
}
}
impl<T: DerefMut, E> Result<T, E> {
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut <T as DerefMut>::Target, &mut E>`.
///
/// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
/// and returns the new [`Result`].
///
/// # Examples
///
/// ```
/// let mut s = "HELLO".to_string();
/// let mut x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&mut str, &mut u32> = Ok(&mut s);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
///
/// let mut i = 42;
/// let mut x: Result<String, u32> = Err(42);
/// let y: Result<&mut str, &mut u32> = Err(&mut i);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
/// ```
#[stable(feature = "inner_deref", since = "1.47.0")]
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
self.as_mut().map(|t| t.deref_mut())
}
}
impl<T, E> Result<Option<T>, E> {
/// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
///

View file

@ -13,20 +13,12 @@
// running tests while providing a base that other test frameworks may
// build off of.
// N.B., this is also specified in this crate's Cargo.toml, but librustc_ast contains logic specific to
// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
// cargo) to detect this crate.
#![crate_name = "test"]
#![unstable(feature = "test", issue = "50297")]
#![doc(test(attr(deny(warnings))))]
#![feature(libc)]
#![feature(rustc_private)]
#![feature(nll)]
#![feature(available_parallelism)]
#![feature(bench_black_box)]
#![feature(internal_output_capture)]
#![feature(panic_unwind)]
#![feature(staged_api)]
#![feature(termination_trait_lib)]
#![feature(test)]
@ -444,8 +436,8 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
.into_iter()
.map(|x| {
let testfn = match x.testfn {
DynBenchFn(bench) => DynTestFn(Box::new(move || {
bench::run_once(|b| __rust_begin_short_backtrace(|| bench.run(b)))
DynBenchFn(benchfn) => DynTestFn(Box::new(move || {
bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
})),
StaticBenchFn(benchfn) => DynTestFn(Box::new(move || {
bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b)))
@ -544,11 +536,9 @@ pub fn run_test(
TestRunOpts { strategy, nocapture: opts.nocapture, concurrency, time: opts.time_options };
match testfn {
DynBenchFn(bencher) => {
DynBenchFn(benchfn) => {
// Benchmarks aren't expected to panic, so we run them all in-process.
crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, |harness| {
bencher.run(harness)
});
crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn);
None
}
StaticBenchFn(benchfn) => {

View file

@ -1,5 +1,4 @@
#![allow(missing_docs)]
#![allow(deprecated)] // Float
use std::mem;

View file

@ -74,11 +74,6 @@ impl fmt::Display for TestName {
}
}
/// Represents a benchmark function.
pub trait TDynBenchFn: Send {
fn run(&self, harness: &mut Bencher);
}
// A function that runs a test. If the function returns successfully,
// the test succeeds; if the function panics then the test fails. We
// may need to come up with a more clever definition of test in order
@ -87,7 +82,7 @@ pub enum TestFn {
StaticTestFn(fn()),
StaticBenchFn(fn(&mut Bencher)),
DynTestFn(Box<dyn FnOnce() + Send>),
DynBenchFn(Box<dyn TDynBenchFn + 'static>),
DynBenchFn(Box<dyn Fn(&mut Bencher) + Send>),
}
impl TestFn {

View file

@ -5,7 +5,6 @@ LL | let _result = &mut Some(42).as_deref_mut();
| ^^^^^^^^^^^^ method cannot be called on `Option<{integer}>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`{integer}: DerefMut`
`{integer}: Deref`
error: aborting due to previous error

View file

@ -5,7 +5,6 @@ LL | let _result = &mut Ok(42).as_deref_mut();
| ^^^^^^^^^^^^ method cannot be called on `Result<{integer}, _>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`{integer}: DerefMut`
`{integer}: Deref`
error: aborting due to previous error

View file

@ -661,9 +661,9 @@ fn test_pat() {
assert_eq!(stringify_pat!(ref mut _x @ _), "ref mut _x @ _");
// PatKind::Struct
assert_eq!(stringify_pat!(Struct {}), "Struct { }"); // FIXME
assert_eq!(stringify_pat!(Struct::<u8> {}), "Struct::<u8> { }");
assert_eq!(stringify_pat!(Struct::<'static> {}), "Struct::<'static> { }");
assert_eq!(stringify_pat!(Struct {}), "Struct {}");
assert_eq!(stringify_pat!(Struct::<u8> {}), "Struct::<u8> {}");
assert_eq!(stringify_pat!(Struct::<'static> {}), "Struct::<'static> {}");
assert_eq!(stringify_pat!(Struct { x }), "Struct { x }");
assert_eq!(stringify_pat!(Struct { x: _x }), "Struct { x: _x }");
assert_eq!(stringify_pat!(Struct { .. }), "Struct { .. }");
@ -672,7 +672,7 @@ fn test_pat() {
#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151
assert_eq!(
stringify_pat!(<Struct as Trait>::Type {}),
"<Struct as Trait>::Type { }",
"<Struct as Trait>::Type {}",
);
// PatKind::TupleStruct

View file

@ -3,5 +3,5 @@ struct Foo;
fn main() {
let a: Result<(), Foo> = Ok(());
a.unwrap();
//~^ ERROR the method
//~^ ERROR `Foo` doesn't implement `Debug`
}

View file

@ -1,19 +1,17 @@
error[E0599]: the method `unwrap` exists for enum `Result<(), Foo>`, but its trait bounds were not satisfied
error[E0277]: `Foo` doesn't implement `Debug`
--> $DIR/method-help-unsatisfied-bound.rs:5:7
|
LL | struct Foo;
| ----------- doesn't satisfy `Foo: Debug`
...
LL | a.unwrap();
| ^^^^^^ method cannot be called on `Result<(), Foo>` due to unsatisfied trait bounds
| ^^^^^^ `Foo` cannot be formatted using `{:?}`
|
= note: the following trait bounds were not satisfied:
`Foo: Debug`
help: consider annotating `Foo` with `#[derive(Debug)]`
|
LL | #[derive(Debug)]
= help: the trait `Debug` is not implemented for `Foo`
= note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
note: required by a bound in `Result::<T, E>::unwrap`
--> $SRC_DIR/core/src/result.rs:LL:COL
|
LL | E: fmt::Debug,
| ^^^^^^^^^^ required by this bound in `Result::<T, E>::unwrap`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,9 @@
fn main() {
let foo = Some(0);
let bar = None;
while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope
while Some(foo) = bar {}
while 3 = foo {} //~ ERROR mismatched types
while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment
while x = 5 {} //~ ERROR cannot find value `x` in this scope
}

View file

@ -0,0 +1,45 @@
error[E0425]: cannot find value `x` in this scope
--> $DIR/while-let-typo.rs:4:16
|
LL | while Some(x) = foo {}
| ^ not found in this scope
|
help: you might have meant to use pattern matching
|
LL | while let Some(x) = foo {}
| +++
error[E0425]: cannot find value `x` in this scope
--> $DIR/while-let-typo.rs:8:11
|
LL | while x = 5 {}
| ^ not found in this scope
|
help: you might have meant to use pattern matching
|
LL | while let x = 5 {}
| +++
error[E0308]: mismatched types
--> $DIR/while-let-typo.rs:6:11
|
LL | while 3 = foo {}
| ^^^^^^^ expected `bool`, found `()`
error[E0070]: invalid left-hand side of assignment
--> $DIR/while-let-typo.rs:7:19
|
LL | while Some(3) = foo {}
| - ^
| |
| cannot assign to this expression
|
help: you might have meant to use pattern destructuring
|
LL | while let Some(3) = foo {}
| +++
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0070, E0308, E0425.
For more information about an error, try `rustc --explain E0070`.

View file

@ -193,7 +193,6 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv
}
},
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()),
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx);
if ty.is_integral() || ty.is_bool() {