diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index b87dd449a1e57..91fa4595241dc 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -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) => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 63ffcb3ec4587..fe34d6e7ca9dd 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -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) => { diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index fc2f04f146e9d..b16f5af66f249 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -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); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 6f960ca44cdd3..679c45767018d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -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(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index fef0e00e507eb..30e9cbe440354 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -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 { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 246807a112a40..0fc3827d16c7e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -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, 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). diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 6a03b699d47d4..23ec3875cbc1a 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -212,12 +212,6 @@ pub trait Machine<'mir, 'tcx>: Sized { right: &ImmTy<'tcx, Self::PointerTag>, ) -> InterpResult<'tcx, (Scalar, 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. diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 6e37aae0f5e5c..3daa1d3c2b3e8 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -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)?; } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 1d5f463015294..dd749c0393473 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -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) => { diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 1537de993d197..55fba5d7ddf69 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -508,7 +508,6 @@ impl<'tcx> Validator<'_, 'tcx> { } Rvalue::NullaryOp(op, _) => match op { - NullOp::Box => return Err(Unpromotable), NullOp::SizeOf => {} NullOp::AlignOf => {} }, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index fb11aaf24c4b8..c17286dfbe38e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -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) => { diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 66e6b571beb2b..3351564299ca5 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -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), } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index c7c306e7d06cc..52ef380001cb0 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -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)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index e577df4820556..dc53dc8de9de9 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -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, } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index feb85d4ffdfa8..2e00b4f9a5e7c 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -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, _) => {} } } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 7e56e062fc989..ecc8e7a6f1a39 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -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>, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b1fa9041342a6..b70c24b76d524 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -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); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5098cef11e83b..5730502313838 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -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); }) }); diff --git a/library/core/src/option.rs b/library/core/src/option.rs index e6312b8b2d947..0022df4f65ff7 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -810,6 +810,45 @@ impl Option { } } + /// 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 Option { } } + /// Converts from `Option` (or `&Option`) 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 = Some("hey".to_owned()); + /// assert_eq!(x.as_deref(), Some("hey")); + /// + /// let x: Option = 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` (or `&mut Option`) 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 = 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 Option<(T, U)> { } } -impl Option<&T> { +impl Option<&T> { /// Maps an `Option<&T>` to an `Option` by copying the contents of the /// option. /// @@ -1597,7 +1688,10 @@ impl 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 { + pub const fn copied(self) -> Option + 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 Option<&T> { None => None, } } -} -impl Option<&mut T> { - /// Maps an `Option<&mut T>` to an `Option` 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 { - match self { - Some(&mut t) => Some(t), - None => None, - } - } -} - -impl Option<&T> { /// Maps an `Option<&T>` to an `Option` by cloning the contents of the /// option. /// @@ -1658,8 +1726,8 @@ impl Option<&T> { } } -impl Option<&mut T> { - /// Maps an `Option<&mut T>` to an `Option` by cloning the contents of the +impl Option<&mut T> { + /// Maps an `Option<&mut T>` to an `Option` by copying the contents of the /// option. /// /// # Examples @@ -1668,115 +1736,43 @@ impl Option<&mut T> { /// let mut x = 12; /// let opt_x = Some(&mut x); /// assert_eq!(opt_x, Some(&mut 12)); - /// let cloned = opt_x.cloned(); - /// assert_eq!(cloned, Some(12)); + /// let copied = opt_x.copied(); + /// assert_eq!(copied, Some(12)); /// ``` #[must_use = "`self` will be dropped if the result is not used"] - #[stable(since = "1.26.0", feature = "option_ref_mut_cloned")] - #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")] - pub const fn cloned(self) -> Option - where - T: ~const Clone, - { - match self { - Some(t) => Some(t.clone()), - None => None, - } - } -} - -impl Option { - /// 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")] + #[stable(feature = "copied", since = "1.35.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] - pub const fn unwrap_or_default(self) -> T + pub const fn copied(self) -> Option where - T: ~const Default, + T: Copy, { match self { - Some(x) => x, - None => Default::default(), - } - } -} - -impl Option { - /// Converts from `Option` (or `&Option`) 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 = Some("hey".to_owned()); - /// assert_eq!(x.as_deref(), Some("hey")); - /// - /// let x: Option = 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()), + Some(&mut t) => Some(t), None => None, } } -} -impl Option { - /// Converts from `Option` (or `&mut Option`) 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. + /// Maps an `Option<&mut T>` to an `Option` by cloning the contents of the + /// option. /// /// # Examples /// /// ``` - /// let mut x: Option = Some("hey".to_owned()); - /// assert_eq!(x.as_deref_mut().map(|x| { - /// x.make_ascii_uppercase(); - /// x - /// }), Some("HEY".to_owned().as_mut_str())); + /// let mut x = 12; + /// let opt_x = Some(&mut x); + /// assert_eq!(opt_x, Some(&mut 12)); + /// let cloned = opt_x.cloned(); + /// assert_eq!(cloned, Some(12)); /// ``` - #[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> + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(since = "1.26.0", feature = "option_ref_mut_cloned")] + #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")] + pub const fn cloned(self) -> Option where - T: ~const DerefMut, + T: ~const Clone, { - match self.as_mut() { - Some(t) => Some(t.deref_mut()), + match self { + Some(t) => Some(t.clone()), None => None, } } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 3cde63493d322..f46632e7a8d20 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -901,6 +901,56 @@ impl Result { self } + /// Converts from `Result` (or `&Result`) to `Result<&::Target, &E>`. + /// + /// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref) + /// and returns the new [`Result`]. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok("hello".to_string()); + /// let y: Result<&str, &u32> = Ok("hello"); + /// assert_eq!(x.as_deref(), y); + /// + /// let x: Result = 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` (or `&mut Result`) to `Result<&mut ::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 = 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 = 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,608 +1001,583 @@ impl Result { IterMut { inner: self.as_mut().ok() } } - //////////////////////////////////////////////////////////////////////// - // Boolean operations on the values, eager and lazy + ///////////////////////////////////////////////////////////////////////// + // Extract a value ///////////////////////////////////////////////////////////////////////// - /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. - /// + /// Returns the contained [`Ok`] value, consuming the `self` value. /// - /// # Examples + /// # Panics /// - /// Basic usage: + /// Panics if the value is an [`Err`], with a panic message including the + /// passed message, and the content of the [`Err`]. /// - /// ``` - /// let x: Result = Ok(2); - /// let y: Result<&str, &str> = Err("late error"); - /// assert_eq!(x.and(y), Err("late error")); /// - /// let x: Result = Err("early error"); - /// let y: Result<&str, &str> = Ok("foo"); - /// assert_eq!(x.and(y), Err("early error")); + /// # Examples /// - /// let x: Result = Err("not a 2"); - /// let y: Result<&str, &str> = Err("late error"); - /// assert_eq!(x.and(y), Err("not a 2")); + /// Basic usage: /// - /// let x: Result = Ok(2); - /// let y: Result<&str, &str> = Ok("different result type"); - /// assert_eq!(x.and(y), Ok("different result type")); + /// ```should_panic + /// let x: Result = Err("emergency failure"); + /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure` /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn and(self, res: Result) -> Result { + #[track_caller] + #[stable(feature = "result_expect", since = "1.4.0")] + pub fn expect(self, msg: &str) -> T + where + E: fmt::Debug, + { match self { - Ok(_) => res, - Err(e) => Err(e), + Ok(t) => t, + Err(e) => unwrap_failed(msg, &e), } } - /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. + /// 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. /// - /// This function can be used for control flow based on `Result` values. /// /// # Examples /// /// Basic usage: /// /// ``` - /// fn sq(x: u32) -> Result { Ok(x * x) } - /// fn err(x: u32) -> Result { Err(x) } + /// let x: Result = Ok(2); + /// assert_eq!(x.unwrap(), 2); + /// ``` /// - /// assert_eq!(Ok(2).and_then(sq).and_then(sq), Ok(16)); - /// assert_eq!(Ok(2).and_then(sq).and_then(err), Err(4)); - /// assert_eq!(Ok(2).and_then(err).and_then(sq), Err(2)); - /// assert_eq!(Err(3).and_then(sq).and_then(sq), Err(3)); + /// ```should_panic + /// let x: Result = Err("emergency failure"); + /// x.unwrap(); // panics with `emergency failure` /// ``` #[inline] + #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn and_then Result>(self, op: F) -> Result { + pub fn unwrap(self) -> T + where + E: fmt::Debug, + { match self { - Ok(t) => op(t), - Err(e) => Err(e), + Ok(t) => t, + Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), } } - /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. - /// - /// Arguments passed to `or` are eagerly evaluated; if you are passing the - /// result of a function call, it is recommended to use [`or_else`], which is - /// lazily evaluated. + /// Returns the contained [`Ok`] value or a default /// - /// [`or_else`]: Result::or_else + /// Consumes the `self` argument then, if [`Ok`], returns the contained + /// value, otherwise if [`Err`], returns the default value for that + /// type. /// /// # Examples /// - /// Basic usage: + /// 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 x: Result = Ok(2); - /// let y: Result = Err("late error"); - /// assert_eq!(x.or(y), Ok(2)); - /// - /// let x: Result = Err("early error"); - /// let y: Result = Ok(2); - /// assert_eq!(x.or(y), Ok(2)); - /// - /// let x: Result = Err("not a 2"); - /// let y: Result = Err("late error"); - /// assert_eq!(x.or(y), Err("late 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(); /// - /// let x: Result = Ok(2); - /// let y: Result = Ok(100); - /// assert_eq!(x.or(y), Ok(2)); + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); /// ``` + /// + /// [`parse`]: str::parse + /// [`FromStr`]: crate::str::FromStr #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn or(self, res: Result) -> Result { + #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] + pub fn unwrap_or_default(self) -> T + where + T: Default, + { match self { - Ok(v) => Ok(v), - Err(_) => res, + Ok(x) => x, + Err(_) => Default::default(), } } - /// Calls `op` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. + /// Returns the contained [`Err`] value, consuming the `self` value. /// - /// This function can be used for control flow based on result values. + /// # 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: /// - /// ``` - /// fn sq(x: u32) -> Result { Ok(x * x) } - /// fn err(x: u32) -> Result { Err(x) } - /// - /// assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2)); - /// assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2)); - /// assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9)); - /// assert_eq!(Err(3).or_else(err).or_else(err), Err(3)); + /// ```should_panic + /// let x: Result = Ok(10); + /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_else Result>(self, op: O) -> Result { + #[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) => Ok(t), - Err(e) => op(e), + Ok(t) => unwrap_failed(msg, &t), + Err(e) => e, } } - /// Returns the contained [`Ok`] value or a provided default. + /// Returns the contained [`Err`] value, consuming the `self` value. /// - /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing - /// the result of a function call, it is recommended to use [`unwrap_or_else`], - /// which is lazily evaluated. + /// # Panics /// - /// [`unwrap_or_else`]: Result::unwrap_or_else + /// Panics if the value is an [`Ok`], with a custom panic message provided + /// by the [`Ok`]'s value. /// /// # Examples /// - /// Basic usage: - /// + /// ```should_panic + /// let x: Result = Ok(2); + /// x.unwrap_err(); // panics with `2` /// ``` - /// let default = 2; - /// let x: Result = Ok(9); - /// assert_eq!(x.unwrap_or(default), 9); /// - /// let x: Result = Err("error"); - /// assert_eq!(x.unwrap_or(default), default); + /// ``` + /// let x: Result = Err("emergency failure"); + /// assert_eq!(x.unwrap_err(), "emergency failure"); /// ``` #[inline] + #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or(self, default: T) -> T { + pub fn unwrap_err(self) -> E + where + T: fmt::Debug, + { match self { - Ok(t) => t, - Err(_) => default, + Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), + Err(e) => e, } } - /// Returns the contained [`Ok`] value or computes it from a closure. + /// 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: /// /// ``` - /// fn count(x: &str) -> usize { x.len() } + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] /// - /// assert_eq!(Ok(2).unwrap_or_else(count), 2); - /// assert_eq!(Err("foo").unwrap_or_else(count), 3); + /// fn only_good_news() -> Result { + /// 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] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or_else T>(self, op: F) -> T { + pub fn into_ok(self) -> T + where + E: Into, + { match self { - Ok(t) => t, - Err(e) => op(e), + Ok(x) => x, + Err(e) => e.into(), } } - /// Returns the contained [`Ok`] value, consuming the `self` value, - /// without checking that the value is not an [`Err`]. - /// - /// # Safety + /// Returns the contained [`Err`] value, but never panics. /// - /// Calling this method on an [`Err`] is *[undefined behavior]*. + /// 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. /// - /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// [`unwrap_err`]: Result::unwrap_err /// /// # Examples /// + /// Basic usage: + /// /// ``` - /// let x: Result = Ok(2); - /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2); - /// ``` + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] /// - /// ```no_run - /// let x: Result = Err("emergency failure"); - /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! + /// fn only_bad_news() -> Result { + /// 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] - #[track_caller] - #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - pub unsafe fn unwrap_unchecked(self) -> T { - debug_assert!(self.is_ok()); + pub fn into_err(self) -> E + where + T: Into, + { match self { - Ok(t) => t, - // SAFETY: the safety contract must be upheld by the caller. - Err(_) => unsafe { hint::unreachable_unchecked() }, + Ok(x) => x.into(), + Err(e) => e, } } - /// Returns the contained [`Err`] value, consuming the `self` value, - /// without checking that the value is not an [`Ok`]. - /// - /// # Safety - /// - /// Calling this method on an [`Ok`] is *[undefined behavior]*. + //////////////////////////////////////////////////////////////////////// + // Boolean operations on the values, eager and lazy + ///////////////////////////////////////////////////////////////////////// + + /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. /// - /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// /// # Examples /// - /// ```no_run - /// let x: Result = Ok(2); - /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior! - /// ``` + /// Basic usage: /// /// ``` - /// let x: Result = Err("emergency failure"); - /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure"); + /// let x: Result = Ok(2); + /// let y: Result<&str, &str> = Err("late error"); + /// assert_eq!(x.and(y), Err("late error")); + /// + /// let x: Result = Err("early error"); + /// let y: Result<&str, &str> = Ok("foo"); + /// assert_eq!(x.and(y), Err("early error")); + /// + /// let x: Result = Err("not a 2"); + /// let y: Result<&str, &str> = Err("late error"); + /// assert_eq!(x.and(y), Err("not a 2")); + /// + /// let x: Result = Ok(2); + /// let y: Result<&str, &str> = Ok("different result type"); + /// assert_eq!(x.and(y), Ok("different result type")); /// ``` #[inline] - #[track_caller] - #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - pub unsafe fn unwrap_err_unchecked(self) -> E { - debug_assert!(self.is_err()); + #[stable(feature = "rust1", since = "1.0.0")] + pub fn and(self, res: Result) -> Result { match self { - // SAFETY: the safety contract must be upheld by the caller. - Ok(_) => unsafe { hint::unreachable_unchecked() }, - Err(e) => e, + Ok(_) => res, + Err(e) => Err(e), } } -} -impl Result<&T, E> { - /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the - /// `Ok` part. + /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. /// - /// # Examples /// - /// ``` - /// #![feature(result_copied)] - /// let val = 12; - /// let x: Result<&i32, i32> = Ok(&val); - /// assert_eq!(x, Ok(&12)); - /// let copied = x.copied(); - /// assert_eq!(copied, Ok(12)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.map(|&t| t) - } -} - -impl Result<&mut T, E> { - /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the - /// `Ok` part. + /// This function can be used for control flow based on `Result` values. /// /// # Examples /// + /// Basic usage: + /// /// ``` - /// #![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)); + /// fn sq(x: u32) -> Result { Ok(x * x) } + /// fn err(x: u32) -> Result { Err(x) } + /// + /// assert_eq!(Ok(2).and_then(sq).and_then(sq), Ok(16)); + /// assert_eq!(Ok(2).and_then(sq).and_then(err), Err(4)); + /// assert_eq!(Ok(2).and_then(err).and_then(sq), Err(2)); + /// assert_eq!(Err(3).and_then(sq).and_then(sq), Err(3)); /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.map(|&mut t| t) + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn and_then Result>(self, op: F) -> Result { + match self { + Ok(t) => op(t), + Err(e) => Err(e), + } } -} -impl Result<&T, E> { - /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the - /// `Ok` part. + /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. /// - /// # Examples + /// Arguments passed to `or` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`or_else`], which is + /// lazily evaluated. /// - /// ``` - /// #![feature(result_cloned)] - /// let val = 12; - /// let x: Result<&i32, i32> = Ok(&val); - /// assert_eq!(x, Ok(&12)); - /// let cloned = x.cloned(); - /// assert_eq!(cloned, Ok(12)); - /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { - self.map(|t| t.clone()) - } -} - -impl Result<&mut T, E> { - /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the - /// `Ok` part. + /// [`or_else`]: Result::or_else /// /// # Examples /// + /// Basic usage: + /// /// ``` - /// #![feature(result_cloned)] - /// let mut val = 12; - /// let x: Result<&mut i32, i32> = Ok(&mut val); - /// assert_eq!(x, Ok(&mut 12)); - /// let cloned = x.cloned(); - /// assert_eq!(cloned, Ok(12)); + /// let x: Result = Ok(2); + /// let y: Result = Err("late error"); + /// assert_eq!(x.or(y), Ok(2)); + /// + /// let x: Result = Err("early error"); + /// let y: Result = Ok(2); + /// assert_eq!(x.or(y), Ok(2)); + /// + /// let x: Result = Err("not a 2"); + /// let y: Result = Err("late error"); + /// assert_eq!(x.or(y), Err("late error")); + /// + /// let x: Result = Ok(2); + /// let y: Result = Ok(100); + /// assert_eq!(x.or(y), Ok(2)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { - self.map(|t| t.clone()) + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or(self, res: Result) -> Result { + match self { + Ok(v) => Ok(v), + Err(_) => res, + } } -} -impl Result { - /// Returns the contained [`Ok`] value, consuming the `self` value. - /// - /// # Panics + /// Calls `op` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. /// - /// Panics if the value is an [`Err`], with a panic message including the - /// passed message, and the content of the [`Err`]. + /// This function can be used for control flow based on result values. /// /// /// # Examples /// /// Basic usage: /// - /// ```should_panic - /// let x: Result = Err("emergency failure"); - /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure` + /// ``` + /// fn sq(x: u32) -> Result { Ok(x * x) } + /// fn err(x: u32) -> Result { Err(x) } + /// + /// assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2)); + /// assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2)); + /// assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9)); + /// assert_eq!(Err(3).or_else(err).or_else(err), Err(3)); /// ``` #[inline] - #[track_caller] - #[stable(feature = "result_expect", since = "1.4.0")] - pub fn expect(self, msg: &str) -> T { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_else Result>(self, op: O) -> Result { match self { - Ok(t) => t, - Err(e) => unwrap_failed(msg, &e), + Ok(t) => Ok(t), + Err(e) => op(e), } } - /// Returns the contained [`Ok`] value, consuming the `self` value. + /// Returns the contained [`Ok`] value or a provided default. /// - /// 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`]. + /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing + /// the result of a function call, it is recommended to use [`unwrap_or_else`], + /// which is lazily evaluated. /// - /// [`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 = Ok(2); - /// assert_eq!(x.unwrap(), 2); - /// ``` + /// let default = 2; + /// let x: Result = Ok(9); + /// assert_eq!(x.unwrap_or(default), 9); /// - /// ```should_panic - /// let x: Result = Err("emergency failure"); - /// x.unwrap(); // panics with `emergency failure` + /// let x: Result = Err("error"); + /// assert_eq!(x.unwrap_or(default), default); /// ``` #[inline] - #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap(self) -> T { + pub fn unwrap_or(self, default: T) -> T { match self { Ok(t) => t, - Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), + Err(_) => default, } } -} -impl Result { - /// 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`]. + /// Returns the contained [`Ok`] value or computes it from a closure. /// /// /// # Examples /// /// Basic usage: /// - /// ```should_panic - /// let x: Result = Ok(10); - /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` + /// ``` + /// fn count(x: &str) -> usize { x.len() } + /// + /// assert_eq!(Ok(2).unwrap_or_else(count), 2); + /// assert_eq!(Err("foo").unwrap_or_else(count), 3); /// ``` #[inline] - #[track_caller] - #[stable(feature = "result_expect_err", since = "1.17.0")] - pub fn expect_err(self, msg: &str) -> E { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_or_else T>(self, op: F) -> T { match self { - Ok(t) => unwrap_failed(msg, &t), - Err(e) => e, + Ok(t) => t, + Err(e) => op(e), } } - /// Returns the contained [`Err`] value, consuming the `self` value. + /// Returns the contained [`Ok`] value, consuming the `self` value, + /// without checking that the value is not an [`Err`]. /// - /// # Panics + /// # Safety /// - /// Panics if the value is an [`Ok`], with a custom panic message provided - /// by the [`Ok`]'s value. + /// Calling this method on an [`Err`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// /// # Examples /// - /// ```should_panic + /// ``` /// let x: Result = Ok(2); - /// x.unwrap_err(); // panics with `2` + /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2); /// ``` /// - /// ``` + /// ```no_run /// let x: Result = Err("emergency failure"); - /// assert_eq!(x.unwrap_err(), "emergency failure"); + /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! /// ``` #[inline] #[track_caller] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_err(self) -> E { + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] + pub unsafe fn unwrap_unchecked(self) -> T { + debug_assert!(self.is_ok()); match self { - Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), - Err(e) => e, + Ok(t) => t, + // SAFETY: the safety contract must be upheld by the caller. + Err(_) => unsafe { hint::unreachable_unchecked() }, } } -} -impl Result { - /// Returns the contained [`Ok`] value or a default + /// Returns the contained [`Err`] value, consuming the `self` value, + /// without checking that the value is not an [`Ok`]. /// - /// Consumes the `self` argument then, if [`Ok`], returns the contained - /// value, otherwise if [`Err`], returns the default value for that - /// type. + /// # Safety /// - /// # Examples + /// Calling this method on an [`Ok`] is *[undefined behavior]*. /// - /// 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. + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// - /// ``` - /// 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(); + /// # Examples /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); + /// ```no_run + /// let x: Result = Ok(2); + /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior! /// ``` /// - /// [`parse`]: str::parse - /// [`FromStr`]: crate::str::FromStr + /// ``` + /// let x: Result = Err("emergency failure"); + /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure"); + /// ``` #[inline] - #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] - pub fn unwrap_or_default(self) -> T { + #[track_caller] + #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] + pub unsafe fn unwrap_err_unchecked(self) -> E { + debug_assert!(self.is_err()); match self { - Ok(x) => x, - Err(_) => Default::default(), + // SAFETY: the safety contract must be upheld by the caller. + Ok(_) => unsafe { hint::unreachable_unchecked() }, + Err(e) => e, } } } -#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] -impl> Result { - /// 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 +impl Result<&T, E> { + /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the + /// `Ok` part. /// /// # Examples /// - /// Basic usage: - /// /// ``` - /// # #![feature(never_type)] - /// # #![feature(unwrap_infallible)] - /// - /// fn only_good_news() -> Result { - /// Ok("this is fine".into()) - /// } - /// - /// let s: String = only_good_news().into_ok(); - /// println!("{}", s); + /// #![feature(result_copied)] + /// let val = 12; + /// let x: Result<&i32, i32> = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); /// ``` - #[inline] - pub fn into_ok(self) -> T { - match self { - Ok(x) => x, - Err(e) => e.into(), - } + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result + where + T: Copy, + { + self.map(|&t| t) } -} -#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] -impl, E> Result { - /// 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 + /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. /// /// # Examples /// - /// Basic usage: - /// /// ``` - /// # #![feature(never_type)] - /// # #![feature(unwrap_infallible)] - /// - /// fn only_bad_news() -> Result { - /// Err("Oops, it failed".into()) - /// } - /// - /// let error: String = only_bad_news().into_err(); - /// println!("{}", error); + /// #![feature(result_cloned)] + /// let val = 12; + /// let x: Result<&i32, i32> = Ok(&val); + /// assert_eq!(x, Ok(&12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); /// ``` - #[inline] - pub fn into_err(self) -> E { - match self { - Ok(x) => x.into(), - Err(e) => e, - } + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result + where + T: Clone, + { + self.map(|t| t.clone()) } } -impl Result { - /// Converts from `Result` (or `&Result`) to `Result<&::Target, &E>`. - /// - /// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref) - /// and returns the new [`Result`]. +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the + /// `Ok` part. /// /// # Examples /// /// ``` - /// let x: Result = Ok("hello".to_string()); - /// let y: Result<&str, &u32> = Ok("hello"); - /// assert_eq!(x.as_deref(), y); - /// - /// let x: Result = Err(42); - /// let y: Result<&str, &u32> = Err(&42); - /// assert_eq!(x.as_deref(), y); + /// #![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)); /// ``` - #[stable(feature = "inner_deref", since = "1.47.0")] - pub fn as_deref(&self) -> Result<&T::Target, &E> { - self.as_ref().map(|t| t.deref()) + #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] + pub fn copied(self) -> Result + where + T: Copy, + { + self.map(|&mut t| t) } -} -impl Result { - /// Converts from `Result` (or `&mut Result`) to `Result<&mut ::Target, &mut E>`. - /// - /// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut) - /// and returns the new [`Result`]. + /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. /// /// # Examples /// /// ``` - /// let mut s = "HELLO".to_string(); - /// let mut x: Result = 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 = 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); + /// #![feature(result_cloned)] + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let cloned = x.cloned(); + /// assert_eq!(cloned, Ok(12)); /// ``` - #[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()) + #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] + pub fn cloned(self) -> Result + where + T: Clone, + { + self.map(|t| t.clone()) } } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 2516f3452b186..608e587cf34f3 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -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) -> Vec 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) => { diff --git a/library/test/src/stats.rs b/library/test/src/stats.rs index 45fae9c76b44d..40b05704b40cb 100644 --- a/library/test/src/stats.rs +++ b/library/test/src/stats.rs @@ -1,5 +1,4 @@ #![allow(missing_docs)] -#![allow(deprecated)] // Float use std::mem; diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 3512a57e8e4ae..37bb38fb0df4e 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -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), - DynBenchFn(Box), + DynBenchFn(Box), } impl TestFn { diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index e4e9705b07db5..52ee1db5b1571 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -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 diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 98a7091dd0583..018557881ef77 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -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 diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 343a26c14a9b0..90983f35a5ebf 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -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:: {}), "Struct:: { }"); - assert_eq!(stringify_pat!(Struct::<'static> {}), "Struct::<'static> { }"); + assert_eq!(stringify_pat!(Struct {}), "Struct {}"); + assert_eq!(stringify_pat!(Struct:: {}), "Struct:: {}"); + 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!(::Type {}), - "::Type { }", + "::Type {}", ); // PatKind::TupleStruct diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs index f85c10d78c54d..6303c6e6a5db1 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.rs @@ -3,5 +3,5 @@ struct Foo; fn main() { let a: Result<(), Foo> = Ok(()); a.unwrap(); - //~^ ERROR the method + //~^ ERROR `Foo` doesn't implement `Debug` } diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 596b7bfe79c5c..dc73bcd6e4d05 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -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::::unwrap` + --> $SRC_DIR/core/src/result.rs:LL:COL | +LL | E: fmt::Debug, + | ^^^^^^^^^^ required by this bound in `Result::::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`. diff --git a/src/test/ui/suggestions/while-let-typo.rs b/src/test/ui/suggestions/while-let-typo.rs new file mode 100644 index 0000000000000..dbbcdee3c19f6 --- /dev/null +++ b/src/test/ui/suggestions/while-let-typo.rs @@ -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 +} diff --git a/src/test/ui/suggestions/while-let-typo.stderr b/src/test/ui/suggestions/while-let-typo.stderr new file mode 100644 index 0000000000000..7cc2ed3149b14 --- /dev/null +++ b/src/test/ui/suggestions/while-let-typo.stderr @@ -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`. diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1a4da1627b784..836558b07cb02 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -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() {