diff --git a/RELEASES.md b/RELEASES.md index 37aed7735455b..bc96ec6779fdb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -10,7 +10,7 @@ Language function's caller's location information for panic messages.][72445] - [Recursively indexing into tuples no longer needs parentheses.][71322] E.g. `x.0.0` over `(x.0).0`. -- [`mem::transmute` can now be used in static and constants.][72920] **Note** +- [`mem::transmute` can now be used in statics and constants.][72920] **Note** You currently can't use `mem::transmute` in constant functions. Compiler diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 294a3173d0cbf..87a59c873b197 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -34,8 +34,8 @@ use crate::slice::{self, SliceIndex}; /// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr` /// is never used for mutation. /// -/// [`PhantomData`]: ../marker/struct.PhantomData.html -/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html +/// [`PhantomData`]: crate::marker::PhantomData +/// [`UnsafeCell`]: crate::cell::UnsafeCell #[stable(feature = "nonnull", since = "1.25.0")] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -82,8 +82,8 @@ impl NonNull { /// /// For the mutable counterpart see [`as_uninit_mut`]. /// - /// [`as_ref`]: #method.as_ref - /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref`]: NonNull::as_ref + /// [`as_uninit_mut`]: NonNull::as_uninit_mut /// /// # Safety /// @@ -114,8 +114,8 @@ impl NonNull { /// /// For the shared counterpart see [`as_uninit_ref`]. /// - /// [`as_mut`]: #method.as_mut - /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_mut`]: NonNull::as_mut + /// [`as_uninit_ref`]: NonNull::as_uninit_ref /// /// # Safety /// @@ -181,8 +181,8 @@ impl NonNull { /// /// For the mutable counterpart see [`as_mut`]. /// - /// [`as_uninit_ref`]: #method.as_uninit_ref - /// [`as_mut`]: #method.as_mut + /// [`as_uninit_ref`]: NonNull::as_uninit_ref + /// [`as_mut`]: NonNull::as_mut /// /// # Safety /// @@ -217,8 +217,8 @@ impl NonNull { /// /// For the shared counterpart see [`as_ref`]. /// - /// [`as_uninit_mut`]: #method.as_uninit_mut - /// [`as_ref`]: #method.as_ref + /// [`as_uninit_mut`]: NonNull::as_uninit_mut + /// [`as_ref`]: NonNull::as_ref /// /// # Safety /// @@ -266,8 +266,6 @@ impl NonNull<[T]> { /// This function is safe, but dereferencing the return value is unsafe. /// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. /// - /// [`slice::from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html - /// /// # Examples /// /// ```rust @@ -357,8 +355,8 @@ impl NonNull<[T]> { /// /// For the mutable counterpart see [`as_uninit_slice_mut`]. /// - /// [`as_ref`]: #method.as_ref - /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut + /// [`as_ref`]: NonNull::as_ref + /// [`as_uninit_slice_mut`]: NonNull::as_uninit_slice_mut /// /// # Safety /// @@ -386,10 +384,9 @@ impl NonNull<[T]> { /// /// This applies even if the result of this method is unused! /// - /// See also [`slice::from_raw_parts`][]. + /// See also [`slice::from_raw_parts`]. /// /// [valid]: crate::ptr#safety - /// [`NonNull::dangling()`]: NonNull::dangling /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] @@ -403,8 +400,8 @@ impl NonNull<[T]> { /// /// For the shared counterpart see [`as_uninit_slice`]. /// - /// [`as_mut`]: #method.as_mut - /// [`as_uninit_slice`]: #method.as_uninit_slice + /// [`as_mut`]: NonNull::as_mut + /// [`as_uninit_slice`]: NonNull::as_uninit_slice /// /// # Safety /// @@ -432,10 +429,9 @@ impl NonNull<[T]> { /// /// This applies even if the result of this method is unused! /// - /// See also [`slice::from_raw_parts_mut`][]. + /// See also [`slice::from_raw_parts_mut`]. /// /// [valid]: crate::ptr#safety - /// [`NonNull::dangling()`]: NonNull::dangling /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset /// /// # Examples diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 546eb74b2cb5d..794eeafbbbff9 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -118,7 +118,7 @@ target | std | host | notes `thumbv7neon-unknown-linux-gnueabihf` | ✓ | | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23) `thumbv8m.base-none-eabi` | * | | ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | | ARMv8-M Mainline -`thumbv8m.main-none-eabihf` | * | | ARMv8-M Baseline, hardfloat +`thumbv8m.main-none-eabihf` | * | | ARMv8-M Mainline, hardfloat `wasm32-unknown-emscripten` | ✓ | | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | | WebAssembly `wasm32-wasi` | ✓ | | WebAssembly with WASI diff --git a/src/doc/unstable-book/src/compiler-flags/tls-model.md b/src/doc/unstable-book/src/compiler-flags/tls-model.md index 0aefaa7fb0177..cd625f3fd096c 100644 --- a/src/doc/unstable-book/src/compiler-flags/tls-model.md +++ b/src/doc/unstable-book/src/compiler-flags/tls-model.md @@ -22,4 +22,4 @@ The TLS data must not be in a library loaded after startup (via `dlopen`). but not in a shared library, and is accessed only from that executable. `rustc` and LLVM may use a more optimized model than specified if they know that we are producing -and executable rather than a library, or that the `static` item is private enough. +an executable rather than a library, or that the `static` item is private enough. diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 4bcf31ef0bfc5..ea624b9ed3003 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -38,6 +38,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind}; use rustc_hir::{HirId, HirIdSet, Node}; +use rustc_index::vec::Idx; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; @@ -2162,6 +2163,40 @@ impl ClashingExternDeclarations { ckind: CItemKind, ) -> bool { debug!("structurally_same_type_impl(cx, a = {:?}, b = {:?})", a, b); + let tcx = cx.tcx; + + // Given a transparent newtype, reach through and grab the inner + // type unless the newtype makes the type non-null. + let non_transparent_ty = |ty: Ty<'tcx>| -> Ty<'tcx> { + let mut ty = ty; + loop { + if let ty::Adt(def, substs) = ty.kind { + let is_transparent = def.subst(tcx, substs).repr.transparent(); + let is_non_null = crate::types::nonnull_optimization_guaranteed(tcx, &def); + debug!( + "non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}", + ty, is_transparent, is_non_null + ); + if is_transparent && !is_non_null { + debug_assert!(def.variants.len() == 1); + let v = &def.variants[VariantIdx::new(0)]; + ty = v + .transparent_newtype_field(tcx) + .expect( + "single-variant transparent structure with zero-sized field", + ) + .ty(tcx, substs); + continue; + } + } + debug!("non_transparent_ty -> {:?}", ty); + return ty; + } + }; + + let a = non_transparent_ty(a); + let b = non_transparent_ty(b); + if !seen_types.insert((a, b)) { // We've encountered a cycle. There's no point going any further -- the types are // structurally the same. diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 4ca5f23ebfe6c..35c462c24c8e8 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -11,7 +11,7 @@ use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{sign_extend, truncate}; use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable}; +use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -527,22 +527,26 @@ enum FfiResult<'tcx> { FfiUnsafe { ty: Ty<'tcx>, reason: String, help: Option }, } +crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtDef) -> bool { + tcx.get_attrs(def.did) + .iter() + .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed)) +} + /// Is type known to be non-null? -fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool { +crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool { let tcx = cx.tcx; match ty.kind { ty::FnPtr(_) => true, ty::Ref(..) => true, ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true, ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => { - let guaranteed_nonnull_optimization = tcx - .get_attrs(def.did) - .iter() - .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed)); + let marked_non_null = nonnull_optimization_guaranteed(tcx, &def); - if guaranteed_nonnull_optimization { + if marked_non_null { return true; } + for variant in &def.variants { if let Some(field) = variant.transparent_newtype_field(tcx) { if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) { diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index ad4418ddca74a..1573fb967910b 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1545,13 +1545,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { normalized_ty.kind, ); if let ty::Adt(def, _) = normalized_ty.kind { - if def.non_enum_variant().fields.iter().any(|field| field.ident == field_ident) { - err.span_suggestion_verbose( - base.span.shrink_to_hi(), - "consider awaiting before field access", - ".await".to_string(), - Applicability::MaybeIncorrect, - ); + // no field access on enum type + if !def.is_enum() { + if def.non_enum_variant().fields.iter().any(|field| field.ident == field_ident) + { + err.span_suggestion_verbose( + base.span.shrink_to_hi(), + "consider awaiting before field access", + ".await".to_string(), + Applicability::MaybeIncorrect, + ); + } } } } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 57c8d5bff7673..881b27a5d6184 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -344,6 +344,7 @@ function defocusSearchBar() { } function getHelpElement() { + buildHelperPopup(); return document.getElementById("help"); } @@ -2807,8 +2808,8 @@ function defocusSearchBar() { var infos = [ "Prefix searches with a type followed by a colon (e.g., fn:) to \ - restrict the search to a given type.", - "Accepted types are: fn, mod, struct, \ + restrict the search to a given item kind.", + "Accepted kinds are: fn, mod, struct, \ enum, trait, type, macro, \ and const.", "Search functions by type signature (e.g., vec -> usize or \ @@ -2828,12 +2829,12 @@ function defocusSearchBar() { popup.appendChild(container); insertAfter(popup, getSearchElement()); + // So that it's only built once and then it'll do nothing when called! + buildHelperPopup = function() {}; } onHashChange(null); window.onhashchange = onHashChange; - - buildHelperPopup(); }()); // This is required in firefox. Explanations: when going back in the history, firefox doesn't re-run diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 346ceacc928c4..55dcaec8ae1e1 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1290,7 +1290,7 @@ h4 > .notable-traits { #theme-choices > button { border: none; width: 100%; - padding: 4px; + padding: 4px 8px; text-align: center; background: rgba(0,0,0,0); } diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index f7d474b5562be..f910bfffc22f4 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -518,7 +518,7 @@ kbd { } #theme-choices > button:hover, #theme-choices > button:focus { - background-color: rgba(70, 70, 70, 0.33); + background-color: rgba(110, 110, 110, 0.33); } @media (max-width: 700px) { diff --git a/src/test/codegen/issue-27130.rs b/src/test/codegen/issue-27130.rs new file mode 100644 index 0000000000000..466245aa1f456 --- /dev/null +++ b/src/test/codegen/issue-27130.rs @@ -0,0 +1,22 @@ +// compile-flags: -O +// min-llvm-version: 11.0 + +#![crate_type = "lib"] + +// CHECK-LABEL: @trim_in_place +#[no_mangle] +pub fn trim_in_place(a: &mut &[u8]) { + while a.first() == Some(&42) { + // CHECK-NOT: slice_index_order_fail + *a = &a[1..]; + } +} + +// CHECK-LABEL: @trim_in_place2 +#[no_mangle] +pub fn trim_in_place2(a: &mut &[u8]) { + while let Some(&42) = a.first() { + // CHECK-NOT: slice_index_order_fail + *a = &a[1..]; + } +} diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs index 44cef19b0d34b..41f0baecf24a8 100644 --- a/src/test/ui/lint/clashing-extern-fn.rs +++ b/src/test/ui/lint/clashing-extern-fn.rs @@ -182,7 +182,9 @@ mod same_sized_members_clash { y: f32, z: f32, } - extern "C" { fn origin() -> Point3; } + extern "C" { + fn origin() -> Point3; + } } mod b { #[repr(C)] @@ -191,8 +193,9 @@ mod same_sized_members_clash { y: i32, z: i32, // NOTE: Incorrectly redeclared as i32 } - extern "C" { fn origin() -> Point3; } - //~^ WARN `origin` redeclared with a different signature + extern "C" { + fn origin() -> Point3; //~ WARN `origin` redeclared with a different signature + } } } @@ -258,6 +261,78 @@ mod non_zero_and_non_null { } } +// See #75739 +mod non_zero_transparent { + mod a1 { + use std::num::NonZeroUsize; + extern "C" { + fn f1() -> NonZeroUsize; + } + } + + mod b1 { + #[repr(transparent)] + struct X(NonZeroUsize); + use std::num::NonZeroUsize; + extern "C" { + fn f1() -> X; + } + } + + mod a2 { + use std::num::NonZeroUsize; + extern "C" { + fn f2() -> NonZeroUsize; + } + } + + mod b2 { + #[repr(transparent)] + struct X1(NonZeroUsize); + + #[repr(transparent)] + struct X(X1); + + use std::num::NonZeroUsize; + extern "C" { + // Same case as above, but with two layers of newtyping. + fn f2() -> X; + } + } + + mod a3 { + #[repr(transparent)] + struct X(core::ptr::NonNull); + + use std::num::NonZeroUsize; + extern "C" { + fn f3() -> X; + } + } + + mod b3 { + extern "C" { + fn f3() -> core::ptr::NonNull; + } + } + + mod a4 { + #[repr(transparent)] + enum E { + X(std::num::NonZeroUsize), + } + extern "C" { + fn f4() -> E; + } + } + + mod b4 { + extern "C" { + fn f4() -> std::num::NonZeroUsize; + } + } +} + mod null_optimised_enums { mod a { extern "C" { diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr index cca0c4c59eb19..0a18f05ba2903 100644 --- a/src/test/ui/lint/clashing-extern-fn.stderr +++ b/src/test/ui/lint/clashing-extern-fn.stderr @@ -106,19 +106,19 @@ LL | fn draw_point(p: Point); found `unsafe extern "C" fn(sameish_members::b::Point)` warning: `origin` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:194:22 + --> $DIR/clashing-extern-fn.rs:197:13 | -LL | extern "C" { fn origin() -> Point3; } - | ---------------------- `origin` previously declared here +LL | fn origin() -> Point3; + | ---------------------- `origin` previously declared here ... -LL | extern "C" { fn origin() -> Point3; } - | ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration +LL | fn origin() -> Point3; + | ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration | = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3` found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3` warning: `transparent_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:217:13 + --> $DIR/clashing-extern-fn.rs:220:13 | LL | fn transparent_incorrect() -> T; | -------------------------------- `transparent_incorrect` previously declared here @@ -130,7 +130,7 @@ LL | fn transparent_incorrect() -> isize; found `unsafe extern "C" fn() -> isize` warning: `missing_return_type` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:235:13 + --> $DIR/clashing-extern-fn.rs:238:13 | LL | fn missing_return_type() -> usize; | ---------------------------------- `missing_return_type` previously declared here @@ -142,7 +142,7 @@ LL | fn missing_return_type(); found `unsafe extern "C" fn()` warning: `non_zero_usize` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:253:13 + --> $DIR/clashing-extern-fn.rs:256:13 | LL | fn non_zero_usize() -> core::num::NonZeroUsize; | ----------------------------------------------- `non_zero_usize` previously declared here @@ -154,7 +154,7 @@ LL | fn non_zero_usize() -> usize; found `unsafe extern "C" fn() -> usize` warning: `non_null_ptr` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:255:13 + --> $DIR/clashing-extern-fn.rs:258:13 | LL | fn non_null_ptr() -> core::ptr::NonNull; | ----------------------------------------------- `non_null_ptr` previously declared here @@ -166,7 +166,7 @@ LL | fn non_null_ptr() -> *const usize; found `unsafe extern "C" fn() -> *const usize` warning: `option_non_zero_usize_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:281:13 + --> $DIR/clashing-extern-fn.rs:356:13 | LL | fn option_non_zero_usize_incorrect() -> usize; | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here @@ -178,7 +178,7 @@ LL | fn option_non_zero_usize_incorrect() -> isize; found `unsafe extern "C" fn() -> isize` warning: `option_non_null_ptr_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:283:13 + --> $DIR/clashing-extern-fn.rs:358:13 | LL | fn option_non_null_ptr_incorrect() -> *const usize; | --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here