From 1b7f5a38186c968e721a8c541f33f6c41a9593f5 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 26 Sep 2021 17:38:05 +0100 Subject: [PATCH 01/24] Remove NullOp::Box --- compiler/rustc_borrowck/src/lib.rs | 4 --- compiler/rustc_codegen_cranelift/src/base.rs | 25 ----------------- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 27 ------------------- .../rustc_const_eval/src/interpret/step.rs | 5 ---- .../src/transform/check_consts/check.rs | 1 - .../src/transform/promote_consts.rs | 1 - compiler/rustc_middle/src/mir/mod.rs | 2 -- compiler/rustc_middle/src/mir/tcx.rs | 5 +--- .../src/move_paths/builder.rs | 14 +--------- compiler/rustc_monomorphize/src/collector.rs | 9 ------- .../clippy_utils/src/qualify_min_const_fn.rs | 1 - 11 files changed, 2 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 08df87e0488b8..3f88765bf0c7a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1397,10 +1397,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 1b30edd293862..a17d10cff665b 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -708,30 +708,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() @@ -742,7 +718,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()); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f087b9f7815da..8cbaaa3063fb7 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/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index e6037d561dedc..c1ebb4200b912 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -267,10 +267,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)?; @@ -285,7 +281,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 03e60deea2783..e3c508617508d 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -680,7 +680,6 @@ impl Visitor<'tcx> for Checker<'mir, '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 ebcc8213c604b..5940243fd8c3a 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -517,7 +517,6 @@ impl<'tcx> Validator<'_, 'tcx> { } Rvalue::NullaryOp(op, _) => match op { - NullOp::Box => return Err(Unpromotable), NullOp::SizeOf => {} NullOp::AlignOf => {} }, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 971556d446300..9b0b093134ba6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2288,8 +2288,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 c3c5ebe705eff..e419df6c22d1e 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 e404b49ecb931..c2df838f2d64d 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_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5147408210ef5..20168105419b2 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/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index e6d8ba3f02eb0..789418c743ff8 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() { From 037e189783b6c689640b1c177cd32ccb385dc237 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 20 Oct 2021 19:32:54 +0100 Subject: [PATCH 02/24] Remove `box_alloc` from `Machine` trait. --- compiler/rustc_const_eval/src/const_eval/machine.rs | 7 ------- compiler/rustc_const_eval/src/interpret/eval_context.rs | 2 +- compiler/rustc_const_eval/src/interpret/machine.rs | 6 ------ compiler/rustc_mir_transform/src/const_prop.rs | 7 ------- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 8efe3eb868b94..daf81b64ed964 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -406,13 +406,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 cf084faade8cc..5a654207a07f3 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -152,7 +152,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 323e102b8723b..4e13c2ff9f876 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -208,12 +208,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_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 17790ec91c8a3..f3169d7b85f42 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -233,13 +233,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>, From 44fdb98764e13faecbe2c307798bbe97348bddde Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 16 Dec 2021 18:35:15 -0500 Subject: [PATCH 03/24] Use field span in `rustc_macros` when emitting decode call This will cause backtraces to point to the location of the field in the struct/enum, rather than the derive macro. This makes it clear which field was being decoded when the backtrace was captured (which is especially useful if there are multiple fields with the same type). --- compiler/rustc_macros/src/serialize.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) 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), } From 874cd08e230f38e9640f995c0286c540a3a9a60d Mon Sep 17 00:00:00 2001 From: ametisf Date: Wed, 29 Dec 2021 13:23:19 +0100 Subject: [PATCH 04/24] Suggest while let x = y when encountering while x = y Extends #75931 to also detect where the `let` might be missing from `while let` expressions. --- compiler/rustc_resolve/src/late.rs | 2 + src/test/ui/suggestions/while-let-typo.rs | 9 ++++ src/test/ui/suggestions/while-let-typo.stderr | 45 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/test/ui/suggestions/while-let-typo.rs create mode 100644 src/test/ui/suggestions/while-let-typo.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 12123c946cc08..342e230a0ec41 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2376,7 +2376,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/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`. From 75d8339cdd8c5b07982764a9b78952a67b7cd519 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 29 Dec 2021 16:16:18 +0100 Subject: [PATCH 05/24] Replace TDynBenchFn with Fn(&mut Bencher) --- library/test/src/lib.rs | 10 ++++------ library/test/src/types.rs | 7 +------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 2516f3452b186..17e15243afd76 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -444,8 +444,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 +544,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/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 { From 1ea4810c84e0d496bf10ebccc7e2ae5de1fb3590 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 29 Dec 2021 16:36:08 +0100 Subject: [PATCH 06/24] Remove #![crate_name] attribute from libtest The crate name is already set in Cargo.toml. The comment says there is some logic in the compiler that reads #![crate_name] and not --crate-name, but I can't find it. Removing it seems to work fine. --- library/test/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 17e15243afd76..1e8c63b69dbaf 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -13,11 +13,6 @@ // 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)] From f710bc5fc03c6cf8c24ddae71b8ca05234104d44 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 29 Dec 2021 16:36:22 +0100 Subject: [PATCH 07/24] Remove unused feature gates from libtest --- library/test/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 1e8c63b69dbaf..608e587cf34f3 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -15,13 +15,10 @@ #![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)] From e015b9ee80af5cf0386e02477ec8c339e3801e64 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 29 Dec 2021 18:06:01 +0100 Subject: [PATCH 08/24] Remove unused allow deprecated --- library/test/src/stats.rs | 1 - 1 file changed, 1 deletion(-) 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; From 8d7cf1a4cae07489c375af7bd03923012774dadd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 29 Dec 2021 12:37:13 -0800 Subject: [PATCH 09/24] Fix spacing in pretty printed PatKind::Struct with no fields --- compiler/rustc_ast_pretty/src/pprust/state.rs | 10 ++++++++-- compiler/rustc_hir_pretty/src/lib.rs | 10 ++++++++-- src/test/ui/macros/stringify.rs | 8 ++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f0c1d017326cd..f0676caed4665 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2460,7 +2460,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, @@ -2481,7 +2485,9 @@ impl<'a> State<'a> { } self.word(".."); } - self.space(); + if !empty { + self.space(); + } self.word("}"); } PatKind::Tuple(ref elts) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 334fa6f4e5ccf..96754cc3c8f4d 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/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 90bc7dc1da239..c0a030a2ecbf4 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 From eda61d8d8a9a241f90808e6dc5256766721dc608 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:23:46 -0800 Subject: [PATCH 10/24] Move Result::as_deref --- library/core/src/result.rs | 47 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 3cde63493d322..09feb7e0eda26 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -901,6 +901,30 @@ 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()) + } + ///////////////////////////////////////////////////////////////////////// // Iterator constructors ///////////////////////////////////////////////////////////////////////// @@ -1508,29 +1532,6 @@ impl, E> Result { } } -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`]. - /// - /// # 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> { - self.as_ref().map(|t| t.deref()) - } -} - impl Result { /// Converts from `Result` (or `&mut Result`) to `Result<&mut ::Target, &mut E>`. /// From 5aa8f91ff0d376eb25ea52a10d7c4cdadf4407ac Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:24:23 -0800 Subject: [PATCH 11/24] Move Result::as_deref_mut --- library/core/src/result.rs | 51 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 09feb7e0eda26..e74e70125b815 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -925,6 +925,32 @@ impl Result { 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 ///////////////////////////////////////////////////////////////////////// @@ -1532,31 +1558,6 @@ impl, E> Result { } } -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`]. - /// - /// # 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> { - self.as_mut().map(|t| t.deref_mut()) - } -} - impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// From 15f57a6c59125c9f08efa2688675a998a869f9b9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:25:42 -0800 Subject: [PATCH 12/24] Move Result::expect and Result::unwrap --- library/core/src/result.rs | 144 +++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index e74e70125b815..7265f03adbae2 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1001,6 +1001,82 @@ impl Result { 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 = 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 = Ok(2); + /// assert_eq!(x.unwrap(), 2); + /// ``` + /// + /// ```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 unwrap(self) -> T + where + E: fmt::Debug, + { + match self { + Ok(t) => t, + Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), + } + } + //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -1326,74 +1402,6 @@ impl Result<&mut T, E> { } } -impl Result { - /// 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 = 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 = Ok(2); - /// assert_eq!(x.unwrap(), 2); - /// ``` - /// - /// ```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 unwrap(self) -> T { - match self { - Ok(t) => t, - Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), - } - } -} - impl Result { /// Returns the contained [`Err`] value, consuming the `self` value. /// From aa2aca2c8c9b5f07318350ecebcd535d79d0deeb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:26:36 -0800 Subject: [PATCH 13/24] Move Result::unwrap_or_default --- library/core/src/result.rs | 73 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 7265f03adbae2..7d0e647bd91ce 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1077,6 +1077,43 @@ impl Result { } } + /// 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(), + } + } + //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -1458,42 +1495,6 @@ impl Result { } } -impl Result { - /// 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> Result { /// Returns the contained [`Ok`] value, but never panics. From 06ea5ebe4ef89cdb626930c4e8b235d430d47fee Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:27:43 -0800 Subject: [PATCH 14/24] Move Result::expect_err and Result::unwrap_err --- library/core/src/result.rs | 116 +++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 7d0e647bd91ce..9cd949f7a1264 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1114,6 +1114,66 @@ 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`]. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```should_panic + /// let x: Result = 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 = Ok(2); + /// x.unwrap_err(); // panics with `2` + /// ``` + /// + /// ``` + /// 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_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, + } + } + //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -1439,62 +1499,6 @@ impl Result<&mut T, E> { } } -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`]. - /// - /// - /// # Examples - /// - /// Basic usage: - /// - /// ```should_panic - /// let x: Result = 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 = Ok(2); - /// x.unwrap_err(); // panics with `2` - /// ``` - /// - /// ``` - /// 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_err(self) -> E { - match self { - Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), - Err(e) => e, - } - } -} - #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] impl> Result { /// Returns the contained [`Ok`] value, but never panics. From 778ca204a6187eb9db99b06d1fa4c759e4e67f05 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:28:23 -0800 Subject: [PATCH 15/24] Move Result::into_ok --- library/core/src/result.rs | 73 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 9cd949f7a1264..6810e44d81e7d 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1174,6 +1174,43 @@ 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 + /// + /// # 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); + /// ``` + #[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(), + } + } + //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -1499,42 +1536,6 @@ impl Result<&mut T, 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 - /// - /// # 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); - /// ``` - #[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, E> Result { /// Returns the contained [`Err`] value, but never panics. From b2df61fa9f69554f3a1cdc5e02d1259396f8ff53 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:28:54 -0800 Subject: [PATCH 16/24] Move Result::into_err --- library/core/src/result.rs | 73 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 6810e44d81e7d..382a571164162 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1211,6 +1211,43 @@ impl 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 + /// + /// # 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); + /// ``` + #[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 ///////////////////////////////////////////////////////////////////////// @@ -1536,42 +1573,6 @@ impl Result<&mut T, E> { } } -#[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 - /// - /// # 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); - /// ``` - #[inline] - pub fn into_err(self) -> E { - match self { - Ok(x) => x.into(), - Err(e) => e, - } - } -} - impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// From e63e2680dadeb87c9fea78c431e628cf7ed461a6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:30:28 -0800 Subject: [PATCH 17/24] Consolidate impl Result<&T, E> --- library/core/src/result.rs | 48 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 382a571164162..29a0be68083c5 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1493,7 +1493,7 @@ impl Result { } } -impl Result<&T, E> { +impl Result<&T, E> { /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the /// `Ok` part. /// @@ -1508,9 +1508,33 @@ impl Result<&T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { + pub fn copied(self) -> Result + where + T: Copy, + { self.map(|&t| t) } + + /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// #![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 + where + T: Clone, + { + self.map(|t| t.clone()) + } } impl Result<&mut T, E> { @@ -1533,26 +1557,6 @@ impl Result<&mut T, E> { } } -impl Result<&T, E> { - /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the - /// `Ok` part. - /// - /// # Examples - /// - /// ``` - /// #![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. From b7a0ab18f6b506b73cda720553a5710e7170fc7c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:31:26 -0800 Subject: [PATCH 18/24] Consolidate impl Result<&mut T, E> --- library/core/src/result.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 29a0be68083c5..f46632e7a8d20 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1537,7 +1537,7 @@ impl Result<&T, E> { } } -impl Result<&mut T, E> { +impl Result<&mut T, E> { /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the /// `Ok` part. /// @@ -1552,12 +1552,13 @@ impl Result<&mut T, E> { /// assert_eq!(copied, Ok(12)); /// ``` #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { + pub fn copied(self) -> Result + where + T: Copy, + { self.map(|&mut t| t) } -} -impl Result<&mut T, E> { /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the /// `Ok` part. /// @@ -1572,7 +1573,10 @@ impl Result<&mut T, E> { /// assert_eq!(cloned, Ok(12)); /// ``` #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { + pub fn cloned(self) -> Result + where + T: Clone, + { self.map(|t| t.clone()) } } From bbcf09f2fb50c146a4b79a1cfece94bfbe1b159a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:34:35 -0800 Subject: [PATCH 19/24] Move Option::unwrap_or_default --- library/core/src/option.rs | 80 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index e6312b8b2d947..d457d502c25d6 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`]. /// @@ -1685,47 +1724,6 @@ impl Option<&mut T> { } } -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(), - } - } -} - impl Option { /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. /// From 48a91a08d166d293fcc03fdc9f86fa30ecbcc51c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:36:37 -0800 Subject: [PATCH 20/24] Move Option::as_deref --- library/core/src/option.rs | 54 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d457d502c25d6..8feebe11e9788 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1072,6 +1072,32 @@ 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, + } + } + ///////////////////////////////////////////////////////////////////////// // Iterator constructors ///////////////////////////////////////////////////////////////////////// @@ -1724,34 +1750,6 @@ impl Option<&mut T> { } } -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, - } - } -} - impl Option { /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. /// From 9d65bc51c1ea5fc482cc42d79732043201bcf54a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:36:55 -0800 Subject: [PATCH 21/24] Move Option::as_deref_mut --- library/core/src/option.rs | 54 ++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 8feebe11e9788..c3bea55772f40 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1098,6 +1098,32 @@ 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. + /// + /// # 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 ///////////////////////////////////////////////////////////////////////// @@ -1750,34 +1776,6 @@ impl Option<&mut T> { } } -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. - /// - /// # 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, - } - } -} - impl Option> { /// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`. /// From 538fe4b28d3aca5657a95aadf65800d2237276d1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:37:27 -0800 Subject: [PATCH 22/24] Consolidate impl Option<&T> --- library/core/src/option.rs | 57 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c3bea55772f40..9b3b27b68a3cd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1672,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. /// @@ -1688,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 { @@ -1696,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. /// @@ -1749,6 +1726,30 @@ impl Option<&T> { } } +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<&mut T> { /// Maps an `Option<&mut T>` to an `Option` by cloning the contents of the /// option. From dc3291614a7e72b833dcae870f8c9b12ede15549 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 10:37:50 -0800 Subject: [PATCH 23/24] Consolidate impl Option<&mut T> --- library/core/src/option.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 9b3b27b68a3cd..0022df4f65ff7 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1726,7 +1726,7 @@ impl Option<&T> { } } -impl Option<&mut T> { +impl Option<&mut T> { /// Maps an `Option<&mut T>` to an `Option` by copying the contents of the /// option. /// @@ -1742,15 +1742,16 @@ impl Option<&mut 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_ext", issue = "91930")] - pub const fn copied(self) -> Option { + pub const fn copied(self) -> Option + where + T: Copy, + { match self { Some(&mut t) => Some(t), None => None, } } -} -impl Option<&mut T> { /// Maps an `Option<&mut T>` to an `Option` by cloning the contents of the /// option. /// From 5960f7a617647f5204e924304b40592ab4f9f51d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 30 Dec 2021 11:15:50 -0800 Subject: [PATCH 24/24] UI test updates for Result and Option method moves --- .../option-as_deref_mut.stderr | 1 - .../result-as_deref_mut.stderr | 1 - .../method-help-unsatisfied-bound.rs | 2 +- .../method-help-unsatisfied-bound.stderr | 20 +++++++++---------- 4 files changed, 10 insertions(+), 14 deletions(-) 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/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`.