diff options
| author | bors <bors@rust-lang.org> | 2020-08-11 12:31:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-08-11 12:31:56 +0000 |
| commit | 4b9ac5161781ca6a376daab3d3b2f2623d8f3789 (patch) | |
| tree | 9c0ef96cc28d572f230886ce0b8f66e529aa2e3e /src | |
| parent | 441fd2255763c2aeea616aeac61b2c795a4c5330 (diff) | |
| parent | 532002853d88a7c9f875dc8c401b8b7e019fe10b (diff) | |
| download | rust-4b9ac5161781ca6a376daab3d3b2f2623d8f3789.tar.gz rust-4b9ac5161781ca6a376daab3d3b2f2623d8f3789.zip | |
Auto merge of #75388 - JohnTitor:rollup-9tgkxnl, r=JohnTitor
Rollup of 10 pull requests Successful merges: - #74744 (Update RELEASES.md for 1.46.0) - #75085 (Transmute big endian `s6_addr` and `[u16; 8]`) - #75226 (Miri: Renamed "undef" to "uninit") - #75333 (polymorphize: constrain unevaluated const handling) - #75338 (move stack size check to const_eval machine) - #75347 (Rustdoc: Fix natural ordering to look at all numbers.) - #75352 (Tweak conditions for E0026 and E0769) - #75353 (Tiny cleanup, remove unnecessary `unwrap`) - #75359 (unused_delims: trim expr) - #75360 (Add sample fix for E0749) Failed merges: r? @ghost
Diffstat (limited to 'src')
27 files changed, 188 insertions, 113 deletions
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index acfb294f7c1..024834bfe2a 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -41,7 +41,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll // some arbitrary byte value. // // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset); + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset); llvals.push(cx.const_bytes(bytes)); } let ptr_offset = read_target_uint( @@ -49,7 +49,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll // This `inspect` is okay since it is within the bounds of the allocation, it doesn't // affect interpreter execution (we inspect the result after interpreter execution), // and we properly interpret the relocation as a relocation pointer offset. - alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)), + alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ) .expect("const_alloc_to_llvm: could not read relocation pointer") as u64; @@ -74,7 +74,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll // arbitrary byte value. // // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range); + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); llvals.push(cx.const_bytes(bytes)); } @@ -452,7 +452,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // BSS. let all_bytes_are_zero = alloc.relocations().is_empty() && alloc - .inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()) + .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()) .iter() .all(|&byte| byte == 0); @@ -480,7 +480,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // because we are doing this access to inspect the final interpreter state (not // as part of the interpreter execution). let bytes = - alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()); + alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, bytes.as_ptr().cast(), diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md index 7a1a745b53c..dfe90ae89e4 100644 --- a/src/librustc_error_codes/error_codes/E0749.md +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -11,9 +11,19 @@ trait MyTrait { impl !MyTrait for u32 { type Foo = i32; // error! } -# fn main() {} ``` Negative impls are not allowed to have any items. Negative impls declare that a trait is **not** implemented (and never will be) and hence there is no need to specify the values for trait methods or other items. + +One way to fix this is to remove the items in negative impls: + +``` +# #![feature(negative_impls)] +trait MyTrait { + type Foo; +} + +impl !MyTrait for u32 {} +``` diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 5de9a16e098..ecc8a192f18 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -481,25 +481,27 @@ trait UnusedDelimLint { let mut err = lint.build(&span_msg); let mut ate_left_paren = false; let mut ate_right_paren = false; - let parens_removed = pattern.trim_matches(|c| match c { - '(' | '{' => { - if ate_left_paren { - false - } else { - ate_left_paren = true; - true + let parens_removed = pattern + .trim_matches(|c| match c { + '(' | '{' => { + if ate_left_paren { + false + } else { + ate_left_paren = true; + true + } } - } - ')' | '}' => { - if ate_right_paren { - false - } else { - ate_right_paren = true; - true + ')' | '}' => { + if ate_right_paren { + false + } else { + ate_right_paren = true; + true + } } - } - _ => false, - }); + _ => false, + }) + .trim(); let replace = { let mut replace = if keep_space.0 { diff --git a/src/librustc_middle/mir/interpret/allocation.rs b/src/librustc_middle/mir/interpret/allocation.rs index dd4fc7adff1..b23deb2e3bc 100644 --- a/src/librustc_middle/mir/interpret/allocation.rs +++ b/src/librustc_middle/mir/interpret/allocation.rs @@ -154,10 +154,10 @@ impl<Tag, Extra> Allocation<Tag, Extra> { } /// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs - /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the + /// from `get_bytes_with_uninit_and_ptr` in that it does no relocation checks (even on the /// edges) at all. It further ignores `AllocationExtra` callbacks. /// This must not be used for reads affecting the interpreter execution. - pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range<usize>) -> &[u8] { + pub fn inspect_with_uninit_and_ptr_outside_interpreter(&self, range: Range<usize>) -> &[u8] { &self.bytes[range] } @@ -194,7 +194,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { /// The last argument controls whether we error out when there are uninitialized /// or pointer bytes. You should never call this, call `get_bytes` or - /// `get_bytes_with_undef_and_ptr` instead, + /// `get_bytes_with_uninit_and_ptr` instead, /// /// This function also guarantees that the resulting pointer will remain stable /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies @@ -244,7 +244,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { /// /// It is the caller's responsibility to check bounds and alignment beforehand. #[inline] - pub fn get_bytes_with_undef_and_ptr( + pub fn get_bytes_with_uninit_and_ptr( &self, cx: &impl HasDataLayout, ptr: Pointer<Tag>, @@ -302,19 +302,19 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { } /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a - /// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the + /// relocation. If `allow_uninit_and_ptr` is `false`, also enforces that the memory in the /// given range contains neither relocations nor uninitialized bytes. pub fn check_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer<Tag>, size: Size, - allow_ptr_and_undef: bool, + allow_uninit_and_ptr: bool, ) -> InterpResult<'tcx> { // Check bounds and relocations on the edges. - self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; + self.get_bytes_with_uninit_and_ptr(cx, ptr, size)?; // Check uninit and ptr. - if !allow_ptr_and_undef { + if !allow_uninit_and_ptr { self.check_init(ptr, size)?; self.check_relocations(cx, ptr, size)?; } @@ -361,7 +361,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { size: Size, ) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> { // `get_bytes_unchecked` tests relocation edges. - let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; + let bytes = self.get_bytes_with_uninit_and_ptr(cx, ptr, size)?; // Uninit check happens *after* we established that the alignment is correct. // We must not return `Ok()` for unaligned pointers! if self.is_init(ptr, size).is_err() { @@ -594,7 +594,7 @@ impl InitMaskCompressed { /// Transferring the initialization mask to other allocations. impl<Tag, Extra> Allocation<Tag, Extra> { /// Creates a run-length encoding of the initialization mask. - pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed { + pub fn compress_uninit_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed { // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from // the source and write it to the destination. Even if we optimized the memory accesses, @@ -636,8 +636,8 @@ impl<Tag, Extra> Allocation<Tag, Extra> { size: Size, repeat: u64, ) { - // An optimization where we can just overwrite an entire range of definedness bits if - // they are going to be uniformly `1` or `0`. + // An optimization where we can just overwrite an entire range of initialization + // bits if they are going to be uniformly `1` or `0`. if defined.ranges.len() <= 1 { self.init_mask.set_range_inbounds( dest.offset, diff --git a/src/librustc_middle/mir/interpret/value.rs b/src/librustc_middle/mir/interpret/value.rs index b4e7a5b98e3..50c76e29663 100644 --- a/src/librustc_middle/mir/interpret/value.rs +++ b/src/librustc_middle/mir/interpret/value.rs @@ -58,7 +58,7 @@ impl<'tcx> ConstValue<'tcx> { pub fn try_to_str_slice(&self) -> Option<&'tcx str> { if let ConstValue::Slice { data, start, end } = *self { - ::std::str::from_utf8(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) + ::std::str::from_utf8(data.inspect_with_uninit_and_ptr_outside_interpreter(start..end)) .ok() } else { None diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 3bb9c20370e..87944db60de 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -1107,7 +1107,7 @@ pub trait PrettyPrinter<'tcx>: // The `inspect` here is okay since we checked the bounds, and there are // no relocations (we have an active slice reference here). We don't use // this result to affect interpreter execution. - let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let byte_str = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end); self.pretty_print_byte_str(byte_str) } ( @@ -1117,7 +1117,7 @@ pub trait PrettyPrinter<'tcx>: // The `inspect` here is okay since we checked the bounds, and there are no // relocations (we have an active `str` reference here). We don't use this // result to affect interpreter execution. - let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end); let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); p!(write("{:?}", s)); Ok(self) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 0dac8b64910..3a753a0edb6 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -301,6 +301,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(()) } + fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + // Enforce stack size limit. + if !ecx.tcx.sess.recursion_limit().value_within_limit(ecx.stack().len()) { + throw_exhaust!(StackFrameLimitReached) + } else { + Ok(()) + } + } + #[inline(always)] fn stack( ecx: &'a InterpCx<'mir, 'tcx, Self>, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 7c2f749c156..bcf2899b439 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -687,11 +687,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::after_stack_push(self)?; info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance); - if !self.tcx.sess.recursion_limit().value_within_limit(self.stack().len()) { - throw_exhaust!(StackFrameLimitReached) - } else { - Ok(()) - } + Ok(()) } /// Jump to the given block. diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 7dfa913fd08..705a547262f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -926,7 +926,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // first copy the relocations to a temporary buffer, because // `get_bytes_mut` will clear the relocations, which is correct, // since we don't want to keep any relocations at the target. - // (`get_bytes_with_undef_and_ptr` below checks that there are no + // (`get_bytes_with_uninit_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). let relocations = self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length); @@ -935,7 +935,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // This checks relocation edges on the src. let src_bytes = - self.get_raw(src.alloc_id)?.get_bytes_with_undef_and_ptr(&tcx, src, size)?.as_ptr(); + self.get_raw(src.alloc_id)?.get_bytes_with_uninit_and_ptr(&tcx, src, size)?.as_ptr(); let dest_bytes = self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?; // `Size` multiplication @@ -948,7 +948,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let dest_bytes = dest_bytes.as_mut_ptr(); // Prepare a copy of the initialization mask. - let compressed = self.get_raw(src.alloc_id)?.compress_undef_range(src, size); + let compressed = self.get_raw(src.alloc_id)?.compress_uninit_range(src, size); if compressed.no_bytes_init() { // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 49fde400913..0b58caef54d 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -106,7 +106,7 @@ impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> { } ScalarMaybeUninit::Uninit => cx.typed_value( |mut this| { - this.write_str("{undef ")?; + this.write_str("{uninit ")?; Ok(this) }, |this| this.print_type(ty), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 15e341d9c4c..20fd8e43361 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -61,7 +61,7 @@ impl<Tag> MemPlaceMeta<Tag> { pub struct MemPlace<Tag = ()> { /// A place may have an integral pointer for ZSTs, and since it might /// be turned back into a reference before ever being dereferenced. - /// However, it may never be undef. + /// However, it may never be uninit. pub ptr: Scalar<Tag>, pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. @@ -729,7 +729,7 @@ where "Size mismatch when writing bits" ) } - Immediate::Scalar(ScalarMaybeUninit::Uninit) => {} // undef can have any size + Immediate::Scalar(ScalarMaybeUninit::Uninit) => {} // uninit can have any size Immediate::ScalarPair(_, _) => { // FIXME: Can we check anything here? } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index f1c5a67ed33..9cd20340138 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -508,12 +508,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } } else { // At run-time, for now, we accept *anything* for these types, including - // undef. We should fix that, but let's start low. + // uninit. We should fix that, but let's start low. } Ok(true) } ty::RawPtr(..) => { - // We are conservative with undef for integers, but try to + // We are conservative with uninit for integers, but try to // actually enforce the strict rules for raw pointers (mostly because // that lets us re-use `ref_to_mplace`). let place = try_validation!( @@ -807,12 +807,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // reject it. However, that's good: We don't inherently want // to reject those pointers, we just do not have the machinery to // talk about parts of a pointer. - // We also accept undef, for consistency with the slow path. + // We also accept uninit, for consistency with the slow path. match self.ecx.memory.get_raw(ptr.alloc_id)?.check_bytes( self.ecx, ptr, size, - /*allow_ptr_and_undef*/ self.ref_tracking_for_consts.is_none(), + /*allow_uninit_and_ptr*/ self.ref_tracking_for_consts.is_none(), ) { // In the happy case, we needn't check anything else. Ok(()) => {} diff --git a/src/librustc_mir/monomorphize/polymorphize.rs b/src/librustc_mir/monomorphize/polymorphize.rs index a996b6fb9d9..fc9f7f1af62 100644 --- a/src/librustc_mir/monomorphize/polymorphize.rs +++ b/src/librustc_mir/monomorphize/polymorphize.rs @@ -269,15 +269,21 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { self.unused_parameters.clear(param.index); false } - ty::ConstKind::Unevaluated(_, _, Some(p)) => { + ty::ConstKind::Unevaluated(def, _, Some(p)) + // Avoid considering `T` unused when constants are of the form: + // `<Self as Foo<T>>::foo::promoted[p]` + if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => + { // If there is a promoted, don't look at the substs - since it will always contain // the generic parameters, instead, traverse the promoted MIR. - let promoted = self.tcx.promoted_mir(self.def_id); + let promoted = self.tcx.promoted_mir(def.did); self.visit_body(&promoted[p]); false } - ty::ConstKind::Unevaluated(def_id, unevaluated_substs, None) => { - self.visit_child_body(def_id.did, unevaluated_substs); + ty::ConstKind::Unevaluated(def, unevaluated_substs, None) + if self.tcx.def_kind(def.did) == DefKind::AnonConst => + { + self.visit_child_body(def.did, unevaluated_substs); false } _ => c.super_visit_with(self), diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index bff83b3c6db..07b13af6ba7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -1076,7 +1076,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // ```rust // let mut x = 42; // x = SOME_MUTABLE_STATIC; - // // x must now be undefined + // // x must now be uninit // ``` // FIXME: we overzealously erase the entire local, because that's easier to // implement. diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 25657ba98b8..c3dbac08ed8 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -743,8 +743,8 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>( if let Some(&(tag, target_id)) = alloc.relocations().get(&i) { // Memory with a relocation must be defined let j = i.bytes_usize(); - let offset = - alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); + let offset = alloc + .inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap(); let offset = Size::from_bytes(offset); let relocation_width = |bytes| bytes * 3; @@ -803,7 +803,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>( // Checked definedness (and thus range) and relocations. This access also doesn't // influence interpreter execution but is only for debugging. - let c = alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + 1)[0]; + let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0]; write!(w, "{:02x}", c)?; if c.is_ascii_control() || c >= 0x80 { ascii.push('.'); diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index dcab0858a75..c57c0e51941 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -392,15 +392,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { /// return the span of whole call and the span for all arguments expect the first one (`self`). fn call_has_self_arg(&self, source: PathSource<'_>) -> Option<(Span, Option<Span>)> { let mut has_self_arg = None; - if let PathSource::Expr(parent) = source { - match &parent?.kind { + if let PathSource::Expr(Some(parent)) = source { + match &parent.kind { ExprKind::Call(_, args) if !args.is_empty() => { let mut expr_kind = &args[0].kind; loop { match expr_kind { ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => { if arg_name.segments[0].ident.name == kw::SelfLower { - let call_span = parent.unwrap().span; + let call_span = parent.span; let tail_args_span = if args.len() > 1 { Some(Span::new( args[1].span.lo(), diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index f598ada900f..1c78bef9852 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1229,8 +1229,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); - // we don't want to throw `E0027` in case we have thrown `E0026` for them - unmentioned_fields.retain(|&x| x.name != suggested_name); + // When we have a tuple struct used with struct we don't want to suggest using + // the (valid) struct syntax with numeric field names. Instead we want to + // suggest the expected syntax. We infer that this is the case by parsing the + // `Ident` into an unsized integer. The suggestion will be emitted elsewhere in + // `smart_resolve_context_dependent_help`. + if suggested_name.to_ident_string().parse::<usize>().is_err() { + // We don't want to throw `E0027` in case we have thrown `E0026` for them. + unmentioned_fields.retain(|&x| x.name != suggested_name); + } } } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 4cbc56333b1..36357539692 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1903,23 +1903,41 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } } -fn name_key(name: &str) -> (&str, u64, usize) { - let end = name.bytes().rposition(|b| b.is_ascii_digit()).map_or(name.len(), |i| i + 1); - - // find number at end - let split = name[0..end].bytes().rposition(|b| !b.is_ascii_digit()).map_or(0, |i| i + 1); - - // count leading zeroes - let after_zeroes = - name[split..end].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra); - - // sort leading zeroes last - let num_zeroes = after_zeroes - split; - - match name[split..end].parse() { - Ok(n) => (&name[..split], n, num_zeroes), - Err(_) => (name, 0, num_zeroes), +/// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order). +pub fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering { + /// Takes a non-numeric and a numeric part from the given &str. + fn take_parts<'a>(s: &mut &'a str) -> (&'a str, &'a str) { + let i = s.find(|c: char| c.is_ascii_digit()); + let (a, b) = s.split_at(i.unwrap_or(s.len())); + let i = b.find(|c: char| !c.is_ascii_digit()); + let (b, c) = b.split_at(i.unwrap_or(b.len())); + *s = c; + (a, b) + } + + while !lhs.is_empty() || !rhs.is_empty() { + let (la, lb) = take_parts(&mut lhs); + let (ra, rb) = take_parts(&mut rhs); + // First process the non-numeric part. + match la.cmp(ra) { + Ordering::Equal => (), + x => return x, + } + // Then process the numeric part, if both sides have one (and they fit in a u64). + if let (Ok(ln), Ok(rn)) = (lb.parse::<u64>(), rb.parse::<u64>()) { + match ln.cmp(&rn) { + Ordering::Equal => (), + x => return x, + } + } + // Then process the numeric part again, but this time as strings. + match lb.cmp(rb) { + Ordering::Equal => (), + x => return x, + } } + + Ordering::Equal } fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { @@ -1962,7 +1980,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean: } let lhs = i1.name.as_ref().map_or("", |s| &**s); let rhs = i2.name.as_ref().map_or("", |s| &**s); - name_key(lhs).cmp(&name_key(rhs)) + compare_names(lhs, rhs) } if cx.shared.sort_modules_alphabetically { @@ -2395,7 +2413,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { let rhs = format!("{}", rhs.inner_impl().print()); // lhs and rhs are formatted as HTML, which may be unnecessary - name_key(&lhs).cmp(&name_key(&rhs)) + compare_names(&lhs, &rhs) } fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, cache: &Cache) { diff --git a/src/librustdoc/html/render/tests.rs b/src/librustdoc/html/render/tests.rs index 99ad26549f5..abf5f05fe58 100644 --- a/src/librustdoc/html/render/tests.rs +++ b/src/librustdoc/html/render/tests.rs @@ -1,24 +1,40 @@ use super::*; #[test] -fn test_name_key() { - assert_eq!(name_key("0"), ("", 0, 1)); - assert_eq!(name_key("123"), ("", 123, 0)); - assert_eq!(name_key("Fruit"), ("Fruit", 0, 0)); - assert_eq!(name_key("Fruit0"), ("Fruit", 0, 1)); - assert_eq!(name_key("Fruit0000"), ("Fruit", 0, 4)); - assert_eq!(name_key("Fruit01"), ("Fruit", 1, 1)); - assert_eq!(name_key("Fruit10"), ("Fruit", 10, 0)); - assert_eq!(name_key("Fruit123"), ("Fruit", 123, 0)); +fn test_compare_names() { + for &(a, b) in &[ + ("hello", "world"), + ("", "world"), + ("123", "hello"), + ("123", ""), + ("123test", "123"), + ("hello", ""), + ("hello", "hello"), + ("hello123", "hello123"), + ("hello123", "hello12"), + ("hello12", "hello123"), + ("hello01abc", "hello01xyz"), + ("hello0abc", "hello0"), + ("hello0", "hello0abc"), + ("01", "1"), + ] { + assert_eq!(compare_names(a, b), a.cmp(b), "{:?} - {:?}", a, b); + } + assert_eq!(compare_names("u8", "u16"), Ordering::Less); + assert_eq!(compare_names("u32", "u16"), Ordering::Greater); + assert_eq!(compare_names("u8_to_f64", "u16_to_f64"), Ordering::Less); + assert_eq!(compare_names("u32_to_f64", "u16_to_f64"), Ordering::Greater); + assert_eq!(compare_names("u16_to_f64", "u16_to_f64"), Ordering::Equal); + assert_eq!(compare_names("u16_to_f32", "u16_to_f64"), Ordering::Less); } #[test] fn test_name_sorting() { let names = [ - "Apple", "Banana", "Fruit", "Fruit0", "Fruit00", "Fruit1", "Fruit01", "Fruit2", "Fruit02", + "Apple", "Banana", "Fruit", "Fruit0", "Fruit00", "Fruit01", "Fruit1", "Fruit02", "Fruit2", "Fruit20", "Fruit30x", "Fruit100", "Pear", ]; let mut sorted = names.to_owned(); - sorted.sort_by_key(|&s| name_key(s)); + sorted.sort_by(|&l, r| compare_names(l, r)); assert_eq!(names, sorted); } diff --git a/src/test/ui/const-generics/unused_braces.fixed b/src/test/ui/const-generics/unused_braces.fixed index 5c2b9267af5..836f26efc96 100644 --- a/src/test/ui/const-generics/unused_braces.fixed +++ b/src/test/ui/const-generics/unused_braces.fixed @@ -10,6 +10,6 @@ struct A<const N: usize>; fn main() { let _: A<7>; // ok - let _: A< 7 >; //~ WARN unnecessary braces + let _: A<7>; //~ WARN unnecessary braces let _: A<{ 3 + 5 }>; // ok } diff --git a/src/test/ui/issues/issue-17800.rs b/src/test/ui/issues/issue-17800.rs index 45879d68b35..5254f45d7c2 100644 --- a/src/test/ui/issues/issue-17800.rs +++ b/src/test/ui/issues/issue-17800.rs @@ -6,7 +6,7 @@ enum MyOption<T> { fn main() { match MyOption::MySome(42) { MyOption::MySome { x: 42 } => (), - //~^ ERROR variant `MyOption::MySome` does not have a field named `x` + //~^ ERROR tuple variant `MyOption::MySome` written as struct variant _ => (), } } diff --git a/src/test/ui/issues/issue-17800.stderr b/src/test/ui/issues/issue-17800.stderr index 6efc7f0c06e..fc034a0cbf3 100644 --- a/src/test/ui/issues/issue-17800.stderr +++ b/src/test/ui/issues/issue-17800.stderr @@ -1,12 +1,9 @@ -error[E0026]: variant `MyOption::MySome` does not have a field named `x` - --> $DIR/issue-17800.rs:8:28 +error[E0769]: tuple variant `MyOption::MySome` written as struct variant + --> $DIR/issue-17800.rs:8:9 | LL | MyOption::MySome { x: 42 } => (), - | ^ - | | - | variant `MyOption::MySome` does not have this field - | help: a field with a similar name exists: `0` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyOption::MySome(42)` error: aborting due to previous error -For more information about this error, try `rustc --explain E0026`. +For more information about this error, try `rustc --explain E0769`. diff --git a/src/test/ui/lint/unused_braces.fixed b/src/test/ui/lint/unused_braces.fixed index c0225911c6e..1a88d985dd8 100644 --- a/src/test/ui/lint/unused_braces.fixed +++ b/src/test/ui/lint/unused_braces.fixed @@ -23,18 +23,18 @@ fn main() { } } - if true { + if true { //~^ WARN unnecessary braces } - while false { + while false { //~^ WARN unnecessary braces } - let _: [u8; 3 ]; + let _: [u8; 3]; //~^ WARN unnecessary braces - consume( 7 ); + consume(7); //~^ WARN unnecessary braces // Do not emit lint for multiline blocks. diff --git a/src/test/ui/lint/unused_braces_borrow.fixed b/src/test/ui/lint/unused_braces_borrow.fixed index 25950334549..583506f891d 100644 --- a/src/test/ui/lint/unused_braces_borrow.fixed +++ b/src/test/ui/lint/unused_braces_borrow.fixed @@ -21,6 +21,6 @@ fn main() { }; consume(&{ a.b }); - consume( a.b ); + consume(a.b); //~^ WARN unnecessary braces } diff --git a/src/test/ui/polymorphization/promoted-function-3.rs b/src/test/ui/polymorphization/promoted-function-3.rs new file mode 100644 index 00000000000..1c84df13e10 --- /dev/null +++ b/src/test/ui/polymorphization/promoted-function-3.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -Zpolymorphize=on -Zmir-opt-level=3 + +fn caller<T, U>() -> &'static usize { + callee::<U>() +} + +fn callee<T>() -> &'static usize { + &std::mem::size_of::<T>() +} + +fn main() { + assert_eq!(caller::<(), ()>(), &0); +} diff --git a/src/test/ui/try-block/try-block-unused-delims.fixed b/src/test/ui/try-block/try-block-unused-delims.fixed index c8b03c20068..756081738c3 100644 --- a/src/test/ui/try-block/try-block-unused-delims.fixed +++ b/src/test/ui/try-block/try-block-unused-delims.fixed @@ -11,7 +11,7 @@ fn main() { consume(try {}); //~^ WARN unnecessary parentheses - consume( try {} ); + consume(try {}); //~^ WARN unnecessary braces match try {} { diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs index 49ff86a205d..c77b80bc237 100644 --- a/src/tools/clippy/clippy_lints/src/consts.rs +++ b/src/tools/clippy/clippy_lints/src/consts.rs @@ -517,7 +517,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty.kind { ty::Ref(_, tam, _) => match tam.kind { ty::Str => String::from_utf8( - data.inspect_with_undef_and_ptr_outside_interpreter(start..end) + data.inspect_with_uninit_and_ptr_outside_interpreter(start..end) .to_owned(), ) .ok() @@ -530,7 +530,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { ty::Array(sub_type, len) => match sub_type.kind { ty::Float(FloatTy::F32) => match miri_to_const(len) { Some(Constant::Int(len)) => alloc - .inspect_with_undef_and_ptr_outside_interpreter(0..(4 * len as usize)) + .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize)) .to_owned() .chunks(4) .map(|chunk| { @@ -544,7 +544,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { }, ty::Float(FloatTy::F64) => match miri_to_const(len) { Some(Constant::Int(len)) => alloc - .inspect_with_undef_and_ptr_outside_interpreter(0..(8 * len as usize)) + .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize)) .to_owned() .chunks(8) .map(|chunk| { |
