diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 692f39368243a..ca7a64e254e14 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -247,12 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl( - &decl, - Some((fn_def_id.to_def_id(), idty)), - true, - ret_id, - ) + this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) }, ); let sig = hir::FnSig { @@ -1264,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id.to_def_id(), idty)), + Some((fn_def_id, idty)), impl_trait_return_allow, is_async, ) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d0fbc2d0f11d4..c04b0471cb72f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -228,7 +228,7 @@ enum ImplTraitContext<'b, 'a> { ReturnPositionOpaqueTy { /// `DefId` for the parent function, used to look up necessary /// information later. - fn_def_id: DefId, + fn_def_id: LocalDefId, /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, }, @@ -646,31 +646,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_def_id: LocalDefId, - anonymous_lifetime_mode: AnonymousLifetimeMode, - f: impl FnOnce(&mut Self) -> (Vec>, T), - ) -> (Vec>, T) { - assert!(!self.is_collecting_in_band_lifetimes); - assert!(self.lifetimes_to_define.is_empty()); - let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; - - self.anonymous_lifetime_mode = anonymous_lifetime_mode; - self.is_collecting_in_band_lifetimes = true; - - let (in_band_ty_params, res) = f(self); - - self.is_collecting_in_band_lifetimes = false; - self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - - let lifetimes_to_define = self.lifetimes_to_define.split_off(0); + f: impl FnOnce(&mut Self) -> T, + ) -> (Vec<(Span, ParamName)>, T) { + let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true); + let len = self.lifetimes_to_define.len(); - let params = lifetimes_to_define - .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) - .chain(in_band_ty_params.into_iter()) - .collect(); + let res = f(self); - (params, res) + let lifetimes_to_define = self.lifetimes_to_define.split_off(len); + self.is_collecting_in_band_lifetimes = was_collecting; + (lifetimes_to_define, res) } /// Converts a lifetime into a new generic parameter. @@ -785,27 +770,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { - let (in_band_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { - let mut params = Vec::new(); - // Note: it is necessary to lower generics *before* calling `f`. - // When lowering `async fn`, there's a final step when lowering - // the return type that assumes that all in-scope lifetimes have - // already been added to either `in_scope_lifetimes` or - // `lifetimes_to_define`. If we swapped the order of these two, - // in-band-lifetimes introduced by generics or where-clauses - // wouldn't have been added yet. - let generics = this.lower_generics_mut( - generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), - ); - let res = f(this, &mut params); - (params, (generics, res)) + let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self + .collect_in_band_defs(|this| { + this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| { + this.with_in_scope_lifetime_defs(&generics.params, |this| { + let mut impl_trait_defs = Vec::new(); + // Note: it is necessary to lower generics *before* calling `f`. + // When lowering `async fn`, there's a final step when lowering + // the return type that assumes that all in-scope lifetimes have + // already been added to either `in_scope_lifetimes` or + // `lifetimes_to_define`. If we swapped the order of these two, + // in-band-lifetimes introduced by generics or where-clauses + // wouldn't have been added yet. + let generics = this.lower_generics_mut( + generics, + ImplTraitContext::Universal( + &mut impl_trait_defs, + this.current_hir_id_owner, + ), + ); + let res = f(this, &mut impl_trait_defs); + (generics, impl_trait_defs, res) + }) }) }); - lowered_generics.params.extend(in_band_defs); + lowered_generics.params.extend( + lifetimes_to_define + .into_iter() + .map(|(span, hir_name)| { + self.lifetime_to_generic_param(span, hir_name, parent_def_id) + }) + .chain(impl_trait_defs), + ); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) @@ -1380,7 +1377,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_opaque_impl_trait( &mut self, span: Span, - fn_def_id: Option, + fn_def_id: Option, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, capturable_lifetimes: Option<&FxHashSet>, @@ -1452,7 +1449,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: lctx.lower_span(span), }, bounds: hir_bounds, - impl_trait_fn: fn_def_id, origin, }; @@ -1522,7 +1518,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec>)>, + mut in_band_ty_params: Option<(LocalDefId, &mut Vec>)>, impl_trait_return_allow: bool, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { @@ -1580,7 +1576,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Some((def_id, _)) if impl_trait_return_allow => { ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id: def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(def_id), } } _ => ImplTraitContext::disallowed(), @@ -1635,7 +1631,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { debug!( @@ -1689,18 +1685,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // this is because the elided lifetimes from the return type // should be figured out using the ordinary elision rules, and // this desugaring achieves that. + + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define); + + // Calculate all the lifetimes that should be captured + // by the opaque type. This should include all in-scope + // lifetime parameters, including those defined in-band. // - // The variable `input_lifetimes_count` tracks the number of - // lifetime parameters to the opaque type *not counting* those - // lifetimes elided in the return type. This includes those - // that are explicitly declared (`in_scope_lifetimes`) and - // those elided lifetimes we found in the arguments (current - // content of `lifetimes_to_define`). Next, we will process - // the return type, which will cause `lifetimes_to_define` to - // grow. - let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); - - let mut lifetime_params = Vec::new(); + // `lifetime_params` is a vector of tuple (span, parameter name, lifetime name). + + // Input lifetime like `'a` or `'1`: + let mut lifetime_params: Vec<_> = self + .in_scope_lifetimes + .iter() + .cloned() + .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name))) + .chain( + self.lifetimes_to_define + .iter() + .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))), + ) + .collect(); + self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each @@ -1710,34 +1717,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = this - .with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + let (lifetimes_to_define, future_bound) = + this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { + this.collect_in_band_defs(|this| { + this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + }) }); - debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define); - // Calculate all the lifetimes that should be captured - // by the opaque type. This should include all in-scope - // lifetime parameters, including those defined in-band. - // - // Note: this must be done after lowering the output type, - // as the output type may introduce new in-band lifetimes. - lifetime_params = this - .in_scope_lifetimes - .iter() - .cloned() - .map(|name| (name.ident().span, name)) - .chain(this.lifetimes_to_define.iter().cloned()) - .collect(); - - debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + lifetime_params.extend( + // Output lifetime like `'_`: + lifetimes_to_define + .into_iter() + .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))), + ); debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); let generic_params = - this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) + this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| { + this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1747,8 +1746,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: this.lower_span(span), }, bounds: arena_vec![this; future_bound], - impl_trait_fn: Some(fn_def_id), - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1771,25 +1769,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // For the "output" lifetime parameters, we just want to // generate `'_`. - let mut generic_args = Vec::with_capacity(lifetime_params.len()); - generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map( - |&(span, hir_name)| { - // Input lifetime like `'a` or `'1`: + let generic_args = + self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| { GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Param(hir_name), + name, }) - }, - )); - generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)| - // Output lifetime like `'_`. - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span: self.lower_span(span), - name: hir::LifetimeName::Implicit(false), - }))); - let generic_args = self.arena.alloc_from_iter(generic_args); + })); // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the @@ -1805,7 +1792,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, span: Span, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. @@ -1816,7 +1803,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; self.lower_ty(ty, context) } @@ -2453,17 +2440,12 @@ impl<'hir> GenericArgsCtor<'hir> { } } +#[tracing::instrument(level = "debug")] fn lifetimes_from_impl_trait_bounds( opaque_ty_id: NodeId, bounds: hir::GenericBounds<'_>, lifetimes_to_include: Option<&FxHashSet>, ) -> Vec<(hir::LifetimeName, Span)> { - debug!( - "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - bounds={:#?})", - opaque_ty_id, bounds, - ); - // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4eb7be542e7a1..76b3be7976c61 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -173,7 +173,7 @@ fn check_opaque_type_parameter_valid( // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. // // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, // Check these OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 487ae87052ba3..d393ea6893849 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2248,7 +2248,6 @@ pub struct BareFnTy<'hir> { pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, - pub impl_trait_fn: Option, pub origin: OpaqueTyOrigin, } @@ -2256,9 +2255,9 @@ pub struct OpaqueTy<'hir> { #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` - FnReturn, + FnReturn(LocalDefId), /// `async fn` - AsyncFn, + AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias, } @@ -2809,7 +2808,9 @@ impl ItemKind<'_> { Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: OpaqueTyOrigin::TyAlias, .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 90bc5b3b2fed1..04eceecc5f072 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(..), .. }), .. diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index d9ab4ae1eda29..c2ef0b41e27bf 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -276,7 +276,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?concrete_ty); let first_own_region = match opaque_defn.origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> @@ -461,35 +461,29 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = self.infcx.defining_use_anchor; - let (in_definition_scope, origin) = match tcx.hir().expect_item(def_id).kind - { + let item_kind = &tcx.hir().expect_item(def_id).kind; + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { + span_bug!( + self.value_span, + "weird opaque type: {:#?}, {:#?}", + ty.kind(), + item_kind + ) + }; + let in_definition_scope = match *origin { + // Async `impl Trait` + hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, - .. - }) => (parent == parent_def_id.to_def_id(), origin), + hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, - .. - }) => { - (may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), origin) - } - ref itemkind => { - span_bug!( - self.value_span, - "weird opaque type: {:#?}, {:#?}", - ty.kind(), - itemkind - ) + hir::OpaqueTyOrigin::TyAlias => { + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id) } }; if in_definition_scope { let opaque_type_key = OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); + return self.fold_opaque_ty(ty, opaque_type_key, *origin); } debug!( diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 1dceda6c7aad0..adba7d131592e 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,7 +1,5 @@ use crate::arena::Arena; - use rustc_serialize::{Encodable, Encoder}; - use std::alloc::Layout; use std::cmp::Ordering; use std::fmt; @@ -12,49 +10,69 @@ use std::ops::Deref; use std::ptr; use std::slice; -extern "C" { - /// A dummy type used to force `List` to be unsized while not requiring references to it be wide - /// pointers. - type OpaqueListContents; -} - -/// A wrapper for slices with the additional invariant -/// that the slice is interned and no other slice with -/// the same contents can exist in the same context. -/// This means we can use pointer for both -/// equality comparisons and hashing. -/// -/// Unlike slices, the types contained in `List` are expected to be `Copy` -/// and iterating over a `List` returns `T` instead of a reference. -/// -/// Note: `Slice` was already taken by the `Ty`. +/// `List` is a bit like `&[T]`, but with some critical differences. +/// - IMPORTANT: Every `List` is *required* to have unique contents. The +/// type's correctness relies on this, *but it does not enforce it*. +/// Therefore, any code that creates a `List` must ensure uniqueness +/// itself. In practice this is achieved by interning. +/// - The length is stored within the `List`, so `&List` is a thin +/// pointer. +/// - Because of this, you cannot get a `List` that is a sub-list of another +/// `List`. You can get a sub-slice `&[T]`, however. +/// - `List` can be used with `CopyTaggedPtr`, which is useful within +/// structs whose size must be minimized. +/// - Because of the uniqueness assumption, we can use the address of a +/// `List` for faster equality comparisons and hashing. +/// - `T` must be `Copy`. This lets `List` be stored in a dropless arena and +/// iterators return a `T` rather than a `&T`. +/// - `T` must not be zero-sized. #[repr(C)] pub struct List { len: usize, + + /// Although this claims to be a zero-length array, in practice `len` + /// elements are actually present. data: [T; 0], + opaque: OpaqueListContents, } -unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - #[inline] - fn into_usize(self) -> usize { - self as *const List as usize - } - #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - &*(ptr as *const List) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - // Self: Copy so this is fine - let ptr = Self::from_usize(ptr); - f(&ptr) - } +extern "C" { + /// A dummy type used to force `List` to be unsized while not requiring + /// references to it be wide pointers. + type OpaqueListContents; } -unsafe impl Sync for List {} +impl List { + /// Returns a reference to the (unique, static) empty list. + #[inline(always)] + pub fn empty<'a>() -> &'a List { + #[repr(align(64))] + struct MaxAlign; + + assert!(mem::align_of::() <= mem::align_of::()); + + #[repr(C)] + struct InOrder(T, U); + + // The empty slice is static and contains a single `0` usize (for the + // length) that is 64-byte aligned, thus featuring the necessary + // trailing padding for elements with up to 64-byte alignment. + static EMPTY_SLICE: InOrder = InOrder(0, MaxAlign); + unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } + } +} impl List { + /// Allocates a list from `arena` and copies the contents of `slice` into it. + /// + /// WARNING: the contents *must be unique*, such that no list with these + /// contents has been previously created. If not, operations such as `eq` + /// and `hash` might give incorrect results. + /// + /// Panics if `T` is `Drop`, or `T` is zero-sized, or the slice is empty + /// (because the empty list exists statically, and is available via + /// `empty()`). #[inline] pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List { assert!(!mem::needs_drop::()); @@ -73,7 +91,7 @@ impl List { .cast::() .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); - &mut *mem + &*mem } } @@ -107,11 +125,24 @@ impl> Encodable for &List { } } +impl PartialEq for List { + #[inline] + fn eq(&self, other: &List) -> bool { + // Pointer equality implies list equality (due to the unique contents + // assumption). + ptr::eq(self, other) + } +} + +impl Eq for List {} + impl Ord for List where T: Ord, { fn cmp(&self, other: &List) -> Ordering { + // Pointer equality implies list equality (due to the unique contents + // assumption), but the contents must be compared otherwise. if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) } } } @@ -121,6 +152,8 @@ where T: PartialOrd, { fn partial_cmp(&self, other: &List) -> Option { + // Pointer equality implies list equality (due to the unique contents + // assumption), but the contents must be compared otherwise. if self == other { Some(Ordering::Equal) } else { @@ -129,17 +162,11 @@ where } } -impl PartialEq for List { - #[inline] - fn eq(&self, other: &List) -> bool { - ptr::eq(self, other) - } -} -impl Eq for List {} - impl Hash for List { #[inline] fn hash(&self, s: &mut H) { + // Pointer hashing is sufficient (due to the unique contents + // assumption). (self as *const List).hash(s) } } @@ -168,13 +195,24 @@ impl<'a, T: Copy> IntoIterator for &'a List { } } -impl List { - #[inline(always)] - pub fn empty<'a>() -> &'a List { - #[repr(align(64), C)] - struct EmptySlice([u8; 64]); - static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); - assert!(mem::align_of::() <= 64); - unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } +unsafe impl Sync for List {} + +unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { + const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; + + #[inline] + fn into_usize(self) -> usize { + self as *const List as usize + } + + #[inline] + unsafe fn from_usize(ptr: usize) -> &'a List { + &*(ptr as *const List) + } + + unsafe fn with_ref R>(ptr: usize, f: F) -> R { + // `Self` is `&'a List` which impls `Copy`, so this is fine. + let ptr = Self::from_usize(ptr); + f(&ptr) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7e1804673df2c..fd1409949f0a7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2055,13 +2055,17 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if let Some(def_id) = def_id.as_local() { - if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return opaque_ty.impl_trait_fn; - } +/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. +pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let def_id = def_id.as_local()?; + if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { + if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { + return match opaque_ty.origin { + hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { + Some(parent) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; } } None diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index c6661e9c74e9b..23d59c8007135 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -105,6 +105,11 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { a misaligned reference is undefined behavior (even if that \ reference is never dereferenced)", ) + .help( + "copy the field contents to a local variable, or replace the \ + reference with a raw pointer and use `read_unaligned`/`write_unaligned` \ + (loads and stores via `*p` must be properly aligned even when using raw pointers)" + ) .emit() }, ); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 1ff33689b53c7..c94c56df75b78 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -968,7 +968,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (generics, bounds) = match opaque_ty.kind { // Named opaque `impl Trait` types are reached via `TyKind::Path`. // This arm is for `impl Trait` in the types of statics, constants and locals. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) => { intravisit::walk_ty(self, ty); // Elided lifetimes are not allowed in non-return @@ -985,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } // RPIT (return position impl trait) hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(_), + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), ref generics, bounds, .. @@ -1695,7 +1698,11 @@ fn compute_object_lifetime_defaults( hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Trait(_, _, ref generics, ..) => { let result = object_lifetime_defaults_for_item(tcx, generics); @@ -2067,7 +2074,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .. }) = self.tcx.hir().get(parent_hir_id) { - if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) { continue 'lifetimes; } // We want to do this only if the liftime identifier is already defined diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 711a6f2fbebdd..74a015d4c348e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -248,7 +248,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent); + return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -313,7 +313,7 @@ fn well_formed_types_in_env<'tcx>( // The environment of an impl Trait type is its defining function's environment. if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return well_formed_types_in_env(tcx, parent); + return well_formed_types_in_env(tcx, parent.to_def_id()); } // Compute the bounds on `Self` and the type parameters. diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 427268d6d63f7..dc52c49499a58 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2336,9 +2336,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some()) - } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self + .impl_trait_ty_to_ty( + def_id, + lifetimes, + matches!( + origin, + hir::OpaqueTyOrigin::FnReturn(..) + | hir::OpaqueTyOrigin::AsyncFn(..) + ), + ), ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 2061f955d968f..a6b16e7f0d4d8 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -541,7 +541,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } if let ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), .. }) = item.kind { @@ -567,7 +567,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( visitor.visit_item(&item); let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn) + matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) } _ => unreachable!(), }; @@ -604,7 +604,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( ) -> Result<(), ErrorReported> { if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { match origin { - hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), + hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span), _ => opaque_type_cycle_error(tcx, def_id, span), } Err(ErrorReported) @@ -635,7 +635,7 @@ fn check_opaque_meets_bounds<'tcx>( ) { match origin { // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index fda96e49eb967..1334328f4e2ae 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -594,7 +594,11 @@ fn type_param_predicates( ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(hir::Impl { ref generics, .. }) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, @@ -793,7 +797,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } // Desugared from `impl Trait`, so visited by the function's return type. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {} + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), + .. + }) => {} // Don't call `type_of` on opaque types, since that depends on type // checking function bodies. `check_item_type` ensures that it's called @@ -1488,15 +1495,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - impl_trait_fn.or_else(|| { - let parent_id = tcx.hir().get_parent_item(hir_id); - assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); - debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); - // Opaque types are always nested within another item, and - // inherit the generics of the item. - Some(tcx.hir().local_def_id(parent_id).to_def_id()) - }) + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + .. + }) => Some(fn_def_id.to_def_id()), + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + let parent_id = tcx.hir().get_parent_item(hir_id); + assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); + debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); + // Opaque types are always nested within another item, and + // inherit the generics of the item. + Some(tcx.hir().local_def_id(parent_id).to_def_id()) } _ => None, }, @@ -2051,31 +2061,32 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP generics } ItemKind::OpaqueTy(OpaqueTy { - bounds: _, - impl_trait_fn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), + .. + }) => { + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; + } + ItemKind::OpaqueTy(OpaqueTy { ref generics, - origin: _, + origin: hir::OpaqueTyOrigin::TyAlias, + .. }) => { - if impl_trait_fn.is_some() { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; - } else { - // type-alias impl trait - generics - } + // type-alias impl trait + generics } _ => NO_GENERICS, diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index b684844744de3..af199ca99460f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -394,13 +394,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { find_opaque_ty_constraints(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { let concrete_ty = tcx - .mir_borrowck(owner.expect_local()) + .mir_borrowck(owner) .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() @@ -413,7 +413,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ), ); if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors + tcx.typeck(owner).tainted_by_errors { // Some error in the // owner fn prevented us from populating diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 4b89bc363268d..920fa59c8ad6e 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -45,15 +45,23 @@ impl Zip { /// /// let xs = [1, 2, 3]; /// let ys = [4, 5, 6]; -/// for (x, y) in zip(&xs, &ys) { -/// println!("x:{}, y:{}", x, y); -/// } +/// +/// let mut iter = zip(xs, ys); +/// +/// assert_eq!(iter.next().unwrap(), (1, 4)); +/// assert_eq!(iter.next().unwrap(), (2, 5)); +/// assert_eq!(iter.next().unwrap(), (3, 6)); +/// assert!(iter.next().is_none()); /// /// // Nested zips are also possible: /// let zs = [7, 8, 9]; -/// for ((x, y), z) in zip(zip(&xs, &ys), &zs) { -/// println!("x:{}, y:{}, z:{}", x, y, z); -/// } +/// +/// let mut iter = zip(zip(xs, ys), zs); +/// +/// assert_eq!(iter.next().unwrap(), ((1, 4), 7)); +/// assert_eq!(iter.next().unwrap(), ((2, 5), 8)); +/// assert_eq!(iter.next().unwrap(), ((3, 6), 9)); +/// assert!(iter.next().is_none()); /// ``` #[unstable(feature = "iter_zip", issue = "83574")] pub fn zip(a: A, b: B) -> Zip diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 014d5119b05fd..dae85027b6c29 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1058,7 +1058,7 @@ impl Metadata { /// } /// ``` #[must_use] - #[stable(feature = "is_symlink", since = "1.57.0")] + #[stable(feature = "is_symlink", since = "1.58.0")] pub fn is_symlink(&self) -> bool { self.file_type().is_symlink() } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 9ade2847e8ea9..7d401cff591c1 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2817,7 +2817,7 @@ impl Path { /// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call /// [`fs::Metadata::is_symlink`] if it was [`Ok`]. #[must_use] - #[stable(feature = "is_symlink", since = "1.57.0")] + #[stable(feature = "is_symlink", since = "1.58.0")] pub fn is_symlink(&self) -> bool { fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index ee19567be102f..35df5fa1b7470 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -327,6 +327,19 @@ impl Options { return Err(0); } + let color = config::parse_color(matches); + let config::JsonConfig { json_rendered, json_unused_externs, .. } = + config::parse_json(matches); + let error_format = config::parse_error_format(matches, color, json_rendered); + + let codegen_options = CodegenOptions::build(matches, error_format); + let debugging_opts = DebuggingOptions::build(matches, error_format); + + let diag = new_handler(error_format, None, &debugging_opts); + + // check for deprecated options + check_deprecated_options(matches, &diag); + if matches.opt_strs("passes") == ["list"] { println!("Available passes for running rustdoc:"); for pass in passes::PASSES { @@ -359,19 +372,6 @@ impl Options { return Err(0); } - let color = config::parse_color(matches); - let config::JsonConfig { json_rendered, json_unused_externs, .. } = - config::parse_json(matches); - let error_format = config::parse_error_format(matches, color, json_rendered); - - let codegen_options = CodegenOptions::build(matches, error_format); - let debugging_opts = DebuggingOptions::build(matches, error_format); - - let diag = new_handler(error_format, None, &debugging_opts); - - // check for deprecated options - check_deprecated_options(matches, &diag); - let mut emit = Vec::new(); for list in matches.opt_strs("emit") { for kind in list.split(',') { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 1691de93bdda2..9943e23b9281c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -976,6 +976,7 @@ fn item_typedef( // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + document_type_layout(w, cx, def_id); } fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { diff --git a/src/test/rustdoc-ui/issue-91713.rs b/src/test/rustdoc-ui/issue-91713.rs new file mode 100644 index 0000000000000..b7057d868c275 --- /dev/null +++ b/src/test/rustdoc-ui/issue-91713.rs @@ -0,0 +1,3 @@ +// check-pass +// compile-flags: --passes list +// error-pattern: the `passes` flag is deprecated diff --git a/src/test/rustdoc-ui/issue-91713.stderr b/src/test/rustdoc-ui/issue-91713.stderr new file mode 100644 index 0000000000000..70c22b3c01e9e --- /dev/null +++ b/src/test/rustdoc-ui/issue-91713.stderr @@ -0,0 +1,4 @@ +warning: the `passes` flag is deprecated + | + = note: see issue #44136 for more information + diff --git a/src/test/rustdoc-ui/issue-91713.stdout b/src/test/rustdoc-ui/issue-91713.stdout new file mode 100644 index 0000000000000..d0372d4945f3a --- /dev/null +++ b/src/test/rustdoc-ui/issue-91713.stdout @@ -0,0 +1,31 @@ +Available passes for running rustdoc: +check_doc_test_visibility - run various visibility-related lints on doctests + strip-hidden - strips all `#[doc(hidden)]` items from the output + unindent-comments - removes excess indentation on comments in order for markdown to like it + strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports + strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate + propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items +collect-intra-doc-links - resolves intra-doc links +check-code-block-syntax - validates syntax inside Rust code blocks + collect-trait-impls - retrieves trait impls for items in the crate +calculate-doc-coverage - counts the number of items with and without documentation +check-invalid-html-tags - detects invalid HTML tags in doc comments + check-bare-urls - detects URLs that are not hyperlinks + +Default passes for rustdoc: + collect-trait-impls + unindent-comments +check_doc_test_visibility + strip-hidden (when not --document-hidden-items) + strip-private (when not --document-private-items) + strip-priv-imports (when --document-private-items) +collect-intra-doc-links +check-code-block-syntax +check-invalid-html-tags + propagate-doc-cfg + check-bare-urls + +Passes run with `--show-coverage`: + strip-hidden (when not --document-hidden-items) + strip-private (when not --document-private-items) +calculate-doc-coverage diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 0868486fa59cd..4eea9809ac58f 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -50,6 +50,18 @@ pub struct GenericLifetimes<'a>(&'a str); // @has - '(unsized)' pub struct Unsized([u8]); +// @has type_layout/type.TypeAlias.html 'Size: ' +// @has - ' bytes' +pub type TypeAlias = X; + +// @has type_layout/type.GenericTypeAlias.html 'Size: ' +// @has - '8 bytes' +pub type GenericTypeAlias = (Generic<(u32, ())>, Generic); + +// Regression test for the rustdoc equivalent of #85103. +// @has type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.' +pub type Edges<'a, E> = std::borrow::Cow<'a, [E]>; + // @!has type_layout/trait.MyTrait.html 'Size: ' pub trait MyTrait {} diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs index 963b19b34a620..90ab0c01f5450 100644 --- a/src/test/ui/async-await/generics-and-bounds.rs +++ b/src/test/ui/async-await/generics-and-bounds.rs @@ -2,6 +2,8 @@ // edition:2018 // compile-flags: --crate-type lib +#![feature(in_band_lifetimes)] + use std::future::Future; pub async fn simple_generic() {} @@ -71,6 +73,10 @@ pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future impl Future + 'a { + async move { f.foo() } +} + pub fn async_block_with_same_generic_params_unifies() { let mut a = call_generic_bound_block(FooType); a = call_generic_bound_block(FooType); @@ -85,4 +91,9 @@ pub fn async_block_with_same_generic_params_unifies() { let f_two = FooType; let mut d = call_with_ref_block(&f_one); d = call_with_ref_block(&f_two); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref_block_in_band(&f_one); + d = call_with_ref_block_in_band(&f_two); } diff --git a/src/test/ui/binding/issue-53114-safety-checks.stderr b/src/test/ui/binding/issue-53114-safety-checks.stderr index 9e7deea4524cb..84cdb1453f82d 100644 --- a/src/test/ui/binding/issue-53114-safety-checks.stderr +++ b/src/test/ui/binding/issue-53114-safety-checks.stderr @@ -8,6 +8,7 @@ LL | let _ = &p.b; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) warning: reference to packed field is unaligned --> $DIR/issue-53114-safety-checks.rs:29:17 @@ -18,6 +19,7 @@ LL | let (_,) = (&p.b,); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) warning: reference to packed field is unaligned --> $DIR/issue-53114-safety-checks.rs:39:11 @@ -28,6 +30,7 @@ LL | match &p.b { _ => { } } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) warning: reference to packed field is unaligned --> $DIR/issue-53114-safety-checks.rs:45:12 @@ -38,6 +41,7 @@ LL | match (&p.b,) { (_,) => { } } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:26:13 diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr index 5acf3797ab53f..fc0179d2cb4ca 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -8,6 +8,7 @@ LL | println!("{}", foo.x); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/src/test/ui/lint/unaligned_references.stderr b/src/test/ui/lint/unaligned_references.stderr index 6a5cc91963da0..53c9380fb7efb 100644 --- a/src/test/ui/lint/unaligned_references.stderr +++ b/src/test/ui/lint/unaligned_references.stderr @@ -12,6 +12,7 @@ LL | #![deny(unaligned_references)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:24:17 @@ -22,6 +23,7 @@ LL | let _ = &good.data; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:27:17 @@ -32,6 +34,7 @@ LL | let _ = &good.data as *const _; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:29:27 @@ -42,6 +45,7 @@ LL | let _: *const _ = &good.data; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:32:17 @@ -52,6 +56,7 @@ LL | let _ = good.data.clone(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:35:17 @@ -62,6 +67,7 @@ LL | let _ = &good.data2[0]; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:45:17 @@ -72,6 +78,7 @@ LL | let _ = &packed2.x; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: aborting due to 7 previous errors diff --git a/src/test/ui/lint/unaligned_references_external_macro.stderr b/src/test/ui/lint/unaligned_references_external_macro.stderr index 5e84fdca1d3ce..01e2395049df4 100644 --- a/src/test/ui/lint/unaligned_references_external_macro.stderr +++ b/src/test/ui/lint/unaligned_references_external_macro.stderr @@ -24,6 +24,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/packed/issue-27060.stderr b/src/test/ui/packed/issue-27060.stderr index 09297884ed377..bba056d59f831 100644 --- a/src/test/ui/packed/issue-27060.stderr +++ b/src/test/ui/packed/issue-27060.stderr @@ -12,6 +12,7 @@ LL | #[deny(unaligned_references)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/issue-27060.rs:18:13 @@ -22,6 +23,7 @@ LL | let _ = &good.data2[0]; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/issue-27060.rs:21:13 @@ -32,6 +34,7 @@ LL | let _ = &good.data; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: reference to packed field is unaligned --> $DIR/issue-27060.rs:23:13 @@ -42,6 +45,7 @@ LL | let _ = &good.data2[0]; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error: aborting due to 4 previous errors diff --git a/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr index 766d8a72c349e..04585b499862b 100644 --- a/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr +++ b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr @@ -8,6 +8,7 @@ LL | let brw = &foo.baz; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) warning: 1 warning emitted diff --git a/src/test/ui/packed/packed-struct-borrow-element.stderr b/src/test/ui/packed/packed-struct-borrow-element.stderr index 5764e951a4600..a50b130200151 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.stderr +++ b/src/test/ui/packed/packed-struct-borrow-element.stderr @@ -8,6 +8,7 @@ LL | let brw = &foo.baz; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) warning: reference to packed field is unaligned --> $DIR/packed-struct-borrow-element.rs:30:15 @@ -18,6 +19,7 @@ LL | let brw = &foo.baz; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) warning: 2 warnings emitted