diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 12ef166b8b051..5ef68c6aeaa59 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -19,7 +19,6 @@ pub fn expand_deriving_copy( path: path_std!(marker::Copy), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: true, methods: Vec::new(), associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 8331710699063..1c507678489fe 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -15,23 +15,22 @@ pub fn expand_deriving_clone( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - // check if we can use a short form + // The simple form is `fn clone(&self) -> Self { *self }`, possibly with + // some additional `AssertParamIsClone` assertions. // - // the short form is `fn clone(&self) -> Self { *self }` - // - // we can use the short form if: - // - the item is Copy (unfortunately, all we can check is whether it's also deriving Copy) - // - there are no generic parameters (after specialization this limitation can be removed) - // if we used the short form with generics, we'd have to bound the generics with - // Clone + Copy, and then there'd be no Clone impl at all if the user fills in something - // that is Clone but not Copy. and until specialization we can't write both impls. - // - the item is a union with Copy fields - // Unions with generic parameters still can derive Clone because they require Copy - // for deriving, Clone alone is not enough. - // Wherever Clone is implemented for fields is irrelevant so we don't assert it. + // We can use the simple form if either of the following are true. + // - The type derives Copy and there are no generic parameters. (If we + // used the simple form with generics, we'd have to bound the generics + // with Clone + Copy, and then there'd be no Clone impl at all if the + // user fills in something that is Clone but not Copy. After + // specialization we can remove this no-generics limitation.) + // - The item is a union. (Unions with generic parameters still can derive + // Clone because they require Copy for deriving, Clone alone is not + // enough. Whether Clone is implemented for fields is irrelevant so we + // don't assert it.) let bounds; let substructure; - let is_shallow; + let is_simple; match *item { Annotatable::Item(ref annitem) => match annitem.kind { ItemKind::Struct(_, Generics { ref params, .. }) @@ -44,30 +43,25 @@ pub fn expand_deriving_clone( .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })) { bounds = vec![]; - is_shallow = true; + is_simple = true; substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, false) + cs_clone_simple("Clone", c, s, sub, false) })); } else { bounds = vec![]; - is_shallow = false; + is_simple = false; substructure = combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub))); } } ItemKind::Union(..) => { - bounds = vec![Literal(path_std!(marker::Copy))]; - is_shallow = true; + bounds = vec![Path(path_std!(marker::Copy))]; + is_simple = true; substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, true) + cs_clone_simple("Clone", c, s, sub, true) })); } - _ => { - bounds = vec![]; - is_shallow = false; - substructure = - combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub))); - } + _ => cx.span_bug(span, "`#[derive(Clone)]` on wrong item kind"), }, _ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"), @@ -81,26 +75,24 @@ pub fn expand_deriving_clone( path: path_std!(clone::Clone), additional_bounds: bounds, generics: Bounds::empty(), - is_unsafe: false, supports_unions: true, methods: vec![MethodDef { name: sym::clone, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), + explicit_self: true, args: Vec::new(), ret_ty: Self_, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: substructure, }], associated_types: Vec::new(), }; - trait_def.expand_ext(cx, mitem, item, push, is_shallow) + trait_def.expand_ext(cx, mitem, item, push, is_simple) } -fn cs_clone_shallow( +fn cs_clone_simple( name: &str, cx: &mut ExtCtxt<'_>, trait_span: Span, @@ -143,7 +135,7 @@ fn cs_clone_shallow( } _ => cx.span_bug( trait_span, - &format!("unexpected substructure in shallow `derive({})`", name), + &format!("unexpected substructure in simple `derive({})`", name), ), } } diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index f54ded3c87cab..cb2ad283a1971 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -27,16 +27,14 @@ pub fn expand_deriving_eq( path: path_std!(cmp::Eq), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: true, methods: vec![MethodDef { name: sym::assert_receiver_is_total_eq, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), + explicit_self: true, args: vec![], - ret_ty: nil_ty(), + ret_ty: Unit, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { cs_total_eq_assert(a, b, c) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 2b3ac0a86c16c..c7850cd4b4cf6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -23,16 +23,14 @@ pub fn expand_deriving_ord( path: path_std!(cmp::Ord), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::cmp, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), sym::other)], - ret_ty: Literal(path_std!(cmp::Ordering)), + explicit_self: true, + args: vec![(self_ref(), sym::other)], + ret_ty: Path(path_std!(cmp::Ordering)), attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), }], @@ -99,8 +97,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< cx.expr_match(span, new, vec![eq_arm, neq_arm]) }, cx.expr_path(equals_path.clone()), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { + Box::new(|cx, span, tag_tuple| { + if tag_tuple.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`") } else { ordering_collapsed(cx, span, tag_tuple) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index eead8b37024c0..ca5ca29eb826a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -48,7 +48,7 @@ pub fn expand_deriving_partial_eq( None => cx.expr_bool(span, base), } }, - Box::new(|cx, span, _, _| cx.expr_bool(span, !base)), + Box::new(|cx, span, _| cx.expr_bool(span, !base)), cx, span, substr, @@ -69,11 +69,10 @@ pub fn expand_deriving_partial_eq( MethodDef { name: $name, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), sym::other)], - ret_ty: Literal(path_local!(bool)), + explicit_self: true, + args: vec![(self_ref(), sym::other)], + ret_ty: Path(path_local!(bool)), attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| $f(a, b, c))), } @@ -102,7 +101,6 @@ pub fn expand_deriving_partial_eq( path: path_std!(cmp::PartialEq), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods, associated_types: Vec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index d28ac822a1ed9..07db82fee935b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -15,13 +15,9 @@ pub fn expand_deriving_partial_ord( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let ordering_ty = Literal(path_std!(cmp::Ordering)); - let ret_ty = Literal(Path::new_( - pathvec_std!(option::Option), - None, - vec![Box::new(ordering_ty)], - PathKind::Std, - )); + let ordering_ty = Path(path_std!(cmp::Ordering)); + let ret_ty = + Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); let inline = cx.meta_word(span, sym::inline); let attrs = vec![cx.attribute(inline)]; @@ -29,11 +25,10 @@ pub fn expand_deriving_partial_ord( let partial_cmp_def = MethodDef { name: sym::partial_cmp, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![(borrowed_self(), sym::other)], + explicit_self: true, + args: vec![(self_ref(), sym::other)], ret_ty, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_partial_cmp(cx, span, substr) @@ -46,7 +41,6 @@ pub fn expand_deriving_partial_ord( path: path_std!(cmp::PartialOrd), additional_bounds: vec![], generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![partial_cmp_def], associated_types: Vec::new(), @@ -102,8 +96,8 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_ cx.expr_match(span, new, vec![eq_arm, neq_arm]) }, equals_expr, - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { + Box::new(|cx, span, tag_tuple| { + if tag_tuple.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") } else { let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0])); diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 1fffd6f9727d7..1411c60c0bfd5 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -16,8 +16,7 @@ pub fn expand_deriving_debug( push: &mut dyn FnMut(Annotatable), ) { // &mut ::std::fmt::Formatter - let fmtr = - Ptr(Box::new(Literal(path_std!(fmt::Formatter))), Borrowed(None, ast::Mutability::Mut)); + let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut); let trait_def = TraitDef { span, @@ -25,16 +24,14 @@ pub fn expand_deriving_debug( path: path_std!(fmt::Debug), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::fmt, generics: Bounds::empty(), - explicit_self: borrowed_explicit_self(), + explicit_self: true, args: vec![(fmtr, sym::f)], - ret_ty: Literal(path_std!(fmt::Result)), + ret_ty: Path(path_std!(fmt::Result)), attributes: Vec::new(), - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { show_substructure(a, b, c) @@ -64,8 +61,6 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let (is_struct, args_per_field) = match vdata { ast::VariantData::Unit(..) => { // Special fast path for unit variants. - //let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); - //return cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]); assert!(fields.is_empty()); (false, 0) } diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index b39f35a9d4056..16154fb4d031b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -23,40 +23,29 @@ pub fn expand_deriving_rustc_decodable( let trait_def = TraitDef { span, attributes: Vec::new(), - path: Path::new_(vec![krate, sym::Decodable], None, vec![], PathKind::Global), + path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::decode, generics: Bounds { bounds: vec![( typaram, - vec![Path::new_(vec![krate, sym::Decoder], None, vec![], PathKind::Global)], + vec![Path::new_(vec![krate, sym::Decoder], vec![], PathKind::Global)], )], }, - explicit_self: None, - args: vec![( - Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - sym::d, - )], - ret_ty: Literal(Path::new_( + explicit_self: false, + args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::d)], + ret_ty: Path(Path::new_( pathvec_std!(result::Result), - None, vec![ Box::new(Self_), - Box::new(Literal(Path::new_( - vec![typaram, sym::Error], - None, - vec![], - PathKind::Local, - ))), + Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))), ], PathKind::Std, )), attributes: Vec::new(), - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { decodable_substructure(a, b, c, krate) diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index b49331e28753d..d41b25343b08e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -30,16 +30,14 @@ pub fn expand_deriving_default( path: Path::new(vec![kw::Default, sym::Default]), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: kw::Default, generics: Bounds::empty(), - explicit_self: None, + explicit_self: false, args: Vec::new(), ret_ty: Self_, attributes: attrs, - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| { match substr.fields { diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 6151a80a56d58..7dc0584618d66 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -108,40 +108,29 @@ pub fn expand_deriving_rustc_encodable( let trait_def = TraitDef { span, attributes: Vec::new(), - path: Path::new_(vec![krate, sym::Encodable], None, vec![], PathKind::Global), + path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::encode, generics: Bounds { bounds: vec![( typaram, - vec![Path::new_(vec![krate, sym::Encoder], None, vec![], PathKind::Global)], + vec![Path::new_(vec![krate, sym::Encoder], vec![], PathKind::Global)], )], }, - explicit_self: borrowed_explicit_self(), - args: vec![( - Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)), - sym::s, - )], - ret_ty: Literal(Path::new_( + explicit_self: true, + args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::s)], + ret_ty: Path(Path::new_( pathvec_std!(result::Result), - None, vec![ - Box::new(Tuple(Vec::new())), - Box::new(Literal(Path::new_( - vec![typaram, sym::Error], - None, - vec![], - PathKind::Local, - ))), + Box::new(Unit), + Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))), ], PathKind::Std, )), attributes: Vec::new(), - is_unsafe: false, unify_fieldless_variants: false, combine_substructure: combine_substructure(Box::new(|a, b, c| { encodable_substructure(a, b, c, krate) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8347cded2fe0b..ff431c8de5d3f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -146,8 +146,6 @@ //! //! ```{.text} //! EnumNonMatchingCollapsed( -//! vec![, ], -//! &[, ], //! &[, ]) //! ``` //! @@ -190,7 +188,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; -use ty::{Bounds, Path, Ptr, PtrTy, Self_, Ty}; +use ty::{Bounds, Path, Ref, Self_, Ty}; use crate::deriving; @@ -212,9 +210,6 @@ pub struct TraitDef<'a> { /// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder` pub generics: Bounds, - /// Is it an `unsafe` trait? - pub is_unsafe: bool, - /// Can this trait be derived for unions? pub supports_unions: bool, @@ -229,10 +224,8 @@ pub struct MethodDef<'a> { /// List of generics, e.g., `R: rand::Rng` pub generics: Bounds, - /// Whether there is a self argument (outer Option) i.e., whether - /// this is a static function, and whether it is a pointer (inner - /// Option) - pub explicit_self: Option>, + /// Is there is a `&self` argument? If not, it is a static function. + pub explicit_self: bool, /// Arguments other than the self argument pub args: Vec<(Ty, Symbol)>, @@ -242,9 +235,6 @@ pub struct MethodDef<'a> { pub attributes: Vec, - // Is it an `unsafe fn`? - pub is_unsafe: bool, - /// Can we combine fieldless variants for enums into a single match arm? pub unify_fieldless_variants: bool, @@ -255,14 +245,7 @@ pub struct MethodDef<'a> { pub struct Substructure<'a> { /// ident of self pub type_ident: Ident, - /// ident of the method - pub method_ident: Ident, - /// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)`][ptr] arguments - /// - /// [`Self_`]: ty::Ty::Self_ - /// [ptr]: ty::Ty::Ptr - pub self_args: &'a [P], - /// verbatim access to any other arguments + /// verbatim access to any non-self arguments pub nonself_args: &'a [P], pub fields: &'a SubstructureFields<'a>, } @@ -299,13 +282,10 @@ pub enum SubstructureFields<'a> { /// variant. EnumMatching(usize, usize, &'a ast::Variant, Vec>), - /// Non-matching variants of the enum, but with all state hidden from - /// the consequent code. The first component holds `Ident`s for all of - /// the `Self` arguments; the second component is a slice of all of the - /// variants for the enum itself, and the third component is a list of - /// `Ident`s bound to the variant index values for each of the actual - /// input `Self` arguments. - EnumNonMatchingCollapsed(Vec, &'a [ast::Variant], &'a [Ident]), + /// Non-matching variants of the enum, but with all state hidden from the + /// consequent code. The field is a list of `Ident`s bound to the variant + /// index values for each of the actual input `Self` arguments. + EnumNonMatchingCollapsed(&'a [Ident]), /// A static method where `Self` is a struct. StaticStruct(&'a ast::VariantData, StaticFields), @@ -318,13 +298,10 @@ pub enum SubstructureFields<'a> { pub type CombineSubstructureFunc<'a> = Box, Span, &Substructure<'_>) -> P + 'a>; -/// Deal with non-matching enum variants. The tuple is a list of -/// identifiers (one for each `Self` argument, which could be any of the -/// variants since they have been collapsed together) and the identifiers -/// holding the variant index value for each of the `Self` arguments. The -/// last argument is all the non-`Self` args of the method being derived. +/// Deal with non-matching enum variants. The slice is the identifiers holding +/// the variant index value for each of the `Self` arguments. pub type EnumNonMatchCollapsedFunc<'a> = - Box, Span, (&[Ident], &[Ident]), &[P]) -> P + 'a>; + Box, Span, &[Ident]) -> P + 'a>; pub fn combine_substructure( f: CombineSubstructureFunc<'_>, @@ -727,14 +704,12 @@ impl<'a> TraitDef<'a> { let mut a = vec![attr, unused_qual]; a.extend(self.attributes.iter().cloned()); - let unsafety = if self.is_unsafe { ast::Unsafe::Yes(self.span) } else { ast::Unsafe::No }; - cx.item( self.span, Ident::empty(), a, ast::ItemKind::Impl(Box::new(ast::Impl { - unsafety, + unsafety: ast::Unsafe::No, polarity: ast::ImplPolarity::Positive, defaultness: ast::Defaultness::Final, constness: ast::Const::No, @@ -771,7 +746,6 @@ impl<'a> TraitDef<'a> { self, struct_def, type_ident, - &self_args, &nonself_args, ) } else { @@ -820,7 +794,6 @@ impl<'a> TraitDef<'a> { self, enum_def, type_ident, - &self_args, &nonself_args, ) } else { @@ -848,18 +821,11 @@ impl<'a> MethodDef<'a> { cx: &mut ExtCtxt<'_>, trait_: &TraitDef<'_>, type_ident: Ident, - self_args: &[P], nonself_args: &[P], fields: &SubstructureFields<'_>, ) -> P { let span = trait_.span; - let substructure = Substructure { - type_ident, - method_ident: Ident::new(self.name, span), - self_args, - nonself_args, - fields, - }; + let substructure = Substructure { type_ident, nonself_args, fields }; let mut f = self.combine_substructure.borrow_mut(); let f: &mut CombineSubstructureFunc<'_> = &mut *f; f(cx, span, &substructure) @@ -876,7 +842,7 @@ impl<'a> MethodDef<'a> { } fn is_static(&self) -> bool { - self.explicit_self.is_none() + !self.explicit_self } fn split_self_nonself_args( @@ -889,17 +855,15 @@ impl<'a> MethodDef<'a> { let mut self_args = Vec::new(); let mut nonself_args = Vec::new(); let mut arg_tys = Vec::new(); - let mut nonstatic = false; let span = trait_.span; - let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { - let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr); - + let ast_explicit_self = if self.explicit_self { + let (self_expr, explicit_self) = ty::get_explicit_self(cx, span); self_args.push(self_expr); - nonstatic = true; - - explicit_self - }); + Some(explicit_self) + } else { + None + }; for (ty, name) in self.args.iter() { let ast_ty = ty.to_ty(cx, span, type_ident, generics); @@ -911,10 +875,10 @@ impl<'a> MethodDef<'a> { match *ty { // for static methods, just treat any Self // arguments as a normal arg - Self_ if nonstatic => { + Self_ if !self.is_static() => { self_args.push(arg_expr); } - Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => { + Ref(ref ty, _) if matches!(**ty, Self_) && !self.is_static() => { self_args.push(cx.expr_deref(span, arg_expr)) } _ => { @@ -955,15 +919,9 @@ impl<'a> MethodDef<'a> { let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); - let unsafety = if self.is_unsafe { ast::Unsafe::Yes(span) } else { ast::Unsafe::No }; - let trait_lo_sp = span.shrink_to_lo(); - let sig = ast::FnSig { - header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() }, - decl: fn_decl, - span, - }; + let sig = ast::FnSig { header: ast::FnHeader::default(), decl: fn_decl, span }; let defaultness = ast::Defaultness::Final; // Create the method. @@ -1083,7 +1041,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - self_args, nonself_args, &Struct(struct_def, fields), ); @@ -1104,7 +1061,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, struct_def: &VariantData, type_ident: Ident, - self_args: &[P], nonself_args: &[P], ) -> P { let summary = trait_.summarise_struct(cx, struct_def); @@ -1113,7 +1069,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - self_args, nonself_args, &StaticStruct(struct_def, summary), ) @@ -1184,11 +1139,6 @@ impl<'a> MethodDef<'a> { ) .collect::>(); - let self_arg_idents = self_arg_names - .iter() - .map(|name| Ident::from_str_and_span(name, span)) - .collect::>(); - // The `vi_idents` will be bound, solely in the catch-all, to // a series of let statements mapping each self_arg to an int // value corresponding to its discriminant. @@ -1203,8 +1153,7 @@ impl<'a> MethodDef<'a> { // Builds, via callback to call_substructure_method, the // delegated expression that handles the catch-all case, // using `__variants_tuple` to drive logic if necessary. - let catch_all_substructure = - EnumNonMatchingCollapsed(self_arg_idents, &variants, &vi_idents); + let catch_all_substructure = EnumNonMatchingCollapsed(&vi_idents); let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); @@ -1303,7 +1252,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - &self_args[..], nonself_args, &substructure, ); @@ -1322,7 +1270,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - &self_args[..], nonself_args, &substructure, )) @@ -1393,7 +1340,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - &self_args[..], nonself_args, &catch_all_substructure, ); @@ -1491,7 +1437,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, enum_def: &EnumDef, type_ident: Ident, - self_args: &[P], nonself_args: &[P], ) -> P { let summary = enum_def @@ -1507,7 +1452,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - self_args, nonself_args, &StaticEnum(enum_def, summary), ) @@ -1628,7 +1572,7 @@ impl<'a> TraitDef<'a> { // helpful premade recipes -pub fn cs_fold_fields<'a, F>( +fn cs_fold_fields<'a, F>( use_foldl: bool, mut f: F, base: P, @@ -1650,21 +1594,19 @@ where } } -pub fn cs_fold_enumnonmatch( +fn cs_fold_enumnonmatch( mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>, cx: &mut ExtCtxt<'_>, trait_span: Span, substructure: &Substructure<'_>, ) -> P { match *substructure.fields { - EnumNonMatchingCollapsed(ref all_args, _, tuple) => { - enum_nonmatch_f(cx, trait_span, (&all_args[..], tuple), substructure.nonself_args) - } + EnumNonMatchingCollapsed(tuple) => enum_nonmatch_f(cx, trait_span, tuple), _ => cx.span_bug(trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed"), } } -pub fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P { +fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P { cx.span_bug(trait_span, "static function in `derive`") } @@ -1717,22 +1659,21 @@ where { match *substructure.fields { EnumMatching(.., ref all_fields) | Struct(_, ref all_fields) => { - let (base, all_fields) = match (all_fields.is_empty(), use_foldl) { + let (base, rest) = match (all_fields.is_empty(), use_foldl) { (false, true) => { - let field = &all_fields[0]; - let args = (field.span, field.self_.clone(), &field.other[..]); - (b(cx, Some(args)), &all_fields[1..]) + let (first, rest) = all_fields.split_first().unwrap(); + let args = (first.span, first.self_.clone(), &first.other[..]); + (b(cx, Some(args)), rest) } (false, false) => { - let idx = all_fields.len() - 1; - let field = &all_fields[idx]; - let args = (field.span, field.self_.clone(), &field.other[..]); - (b(cx, Some(args)), &all_fields[..idx]) + let (last, rest) = all_fields.split_last().unwrap(); + let args = (last.span, last.self_.clone(), &last.other[..]); + (b(cx, Some(args)), rest) } (true, _) => (b(cx, None), &all_fields[..]), }; - cs_fold_fields(use_foldl, f, base, cx, all_fields) + cs_fold_fields(use_foldl, f, base, cx, rest) } EnumNonMatchingCollapsed(..) => { cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 7a41800325084..4b20d87629d96 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -1,7 +1,6 @@ //! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use //! when specifying impls to be derived. -pub use PtrTy::*; pub use Ty::*; use rustc_ast::ptr::P; @@ -11,22 +10,11 @@ use rustc_span::source_map::{respan, DUMMY_SP}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; -/// The types of pointers -#[derive(Clone)] -pub enum PtrTy { - /// &'lifetime mut - Borrowed(Option, ast::Mutability), - /// *mut - #[allow(dead_code)] - Raw(ast::Mutability), -} - /// A path, e.g., `::std::option::Option::` (global). Has support -/// for type parameters and a lifetime. +/// for type parameters. #[derive(Clone)] pub struct Path { path: Vec, - lifetime: Option, params: Vec>, kind: PathKind, } @@ -40,18 +28,13 @@ pub enum PathKind { impl Path { pub fn new(path: Vec) -> Path { - Path::new_(path, None, Vec::new(), PathKind::Std) + Path::new_(path, Vec::new(), PathKind::Std) } pub fn new_local(path: Symbol) -> Path { - Path::new_(vec![path], None, Vec::new(), PathKind::Local) + Path::new_(vec![path], Vec::new(), PathKind::Local) } - pub fn new_( - path: Vec, - lifetime: Option, - params: Vec>, - kind: PathKind, - ) -> Path { - Path { path, lifetime, params, kind } + pub fn new_(path: Vec, params: Vec>, kind: PathKind) -> Path { + Path { path, params, kind } } pub fn to_ty( @@ -71,10 +54,8 @@ impl Path { self_generics: &Generics, ) -> ast::Path { let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect(); - let lt = mk_lifetimes(cx, span, &self.lifetime); let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)); - let params = - lt.into_iter().map(GenericArg::Lifetime).chain(tys.map(GenericArg::Type)).collect(); + let params = tys.map(GenericArg::Type).collect(); match self.kind { PathKind::Global => cx.path_all(span, true, idents, params), @@ -92,40 +73,17 @@ impl Path { #[derive(Clone)] pub enum Ty { Self_, - /// &/Box/ Ty - Ptr(Box, PtrTy), + /// A reference. + Ref(Box, ast::Mutability), /// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type /// parameter, and things like `i32` - Literal(Path), - /// includes unit - Tuple(Vec), -} - -pub fn borrowed_ptrty() -> PtrTy { - Borrowed(None, ast::Mutability::Not) -} -pub fn borrowed(ty: Box) -> Ty { - Ptr(ty, borrowed_ptrty()) -} - -pub fn borrowed_explicit_self() -> Option> { - Some(Some(borrowed_ptrty())) -} - -pub fn borrowed_self() -> Ty { - borrowed(Box::new(Self_)) + Path(Path), + /// For () return types. + Unit, } -pub fn nil_ty() -> Ty { - Tuple(Vec::new()) -} - -fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option) -> Option { - lt.map(|ident| cx.lifetime(span, ident)) -} - -fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option) -> Vec { - mk_lifetime(cx, span, lt).into_iter().collect() +pub fn self_ref() -> Ty { + Ref(Box::new(Self_), ast::Mutability::Not) } impl Ty { @@ -136,23 +94,15 @@ impl Ty { self_ty: Ident, self_generics: &Generics, ) -> P { - match *self { - Ptr(ref ty, ref ptr) => { + match self { + Ref(ty, mutbl) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); - match *ptr { - Borrowed(ref lt, mutbl) => { - let lt = mk_lifetime(cx, span, lt); - cx.ty_rptr(span, raw_ty, lt, mutbl) - } - Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl), - } + cx.ty_rptr(span, raw_ty, None, *mutbl) } - Literal(ref p) => p.to_ty(cx, span, self_ty, self_generics), + Path(p) => p.to_ty(cx, span, self_ty, self_generics), Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)), - Tuple(ref fields) => { - let ty = ast::TyKind::Tup( - fields.iter().map(|f| f.to_ty(cx, span, self_ty, self_generics)).collect(), - ); + Unit => { + let ty = ast::TyKind::Tup(vec![]); cx.ty(span, ty) } } @@ -185,9 +135,9 @@ impl Ty { cx.path_all(span, false, vec![self_ty], params) } - Literal(ref p) => p.to_path(cx, span, self_ty, generics), - Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"), - Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"), + Path(ref p) => p.to_path(cx, span, self_ty, generics), + Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"), + Unit => cx.span_bug(span, "unit in a path in generic `derive`"), } } } @@ -245,28 +195,10 @@ impl Bounds { } } -pub fn get_explicit_self( - cx: &ExtCtxt<'_>, - span: Span, - self_ptr: &Option, -) -> (P, ast::ExplicitSelf) { +pub fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P, ast::ExplicitSelf) { // this constructs a fresh `self` path let self_path = cx.expr_self(span); - match *self_ptr { - None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Not))), - Some(ref ptr) => { - let self_ty = respan( - span, - match *ptr { - Borrowed(ref lt, mutbl) => { - let lt = lt.map(|s| cx.lifetime(span, s)); - SelfKind::Region(lt, mutbl) - } - Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition"), - }, - ); - let self_expr = cx.expr_deref(span, self_path); - (self_expr, self_ty) - } - } + let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not)); + let self_expr = cx.expr_deref(span, self_path); + (self_expr, self_ty) } diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1d46f03bad8f..9790449c4b331 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -15,7 +15,7 @@ pub fn expand_deriving_hash( item: &Annotatable, push: &mut dyn FnMut(Annotatable), ) { - let path = Path::new_(pathvec_std!(hash::Hash), None, vec![], PathKind::Std); + let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std); let typaram = sym::__H; @@ -26,16 +26,14 @@ pub fn expand_deriving_hash( path, additional_bounds: Vec::new(), generics: Bounds::empty(), - is_unsafe: false, supports_unions: false, methods: vec![MethodDef { name: sym::hash, generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] }, - explicit_self: borrowed_explicit_self(), - args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), sym::state)], - ret_ty: nil_ty(), + explicit_self: true, + args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], + ret_ty: Unit, attributes: vec![], - is_unsafe: false, unify_fieldless_variants: true, combine_substructure: combine_substructure(Box::new(|a, b, c| { hash_substructure(a, b, c) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 09a2977af0403..0dac4f8978e0d 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -19,11 +19,9 @@ use rustc_target::abi::{self, Abi}; use std::borrow::Cow; use std::convert::TryInto; -pub fn note_on_undefined_behavior_error() -> &'static str { - "The rules on what exactly is undefined behavior aren't clear, \ +const NOTE_ON_UNDEFINED_BEHAVIOR_ERROR: &str = "The rules on what exactly is undefined behavior aren't clear, \ so this check might be overzealous. Please open an issue on the rustc \ - repository if you believe it should not be considered undefined behavior." -} + repository if you believe it should not be considered undefined behavior."; // Returns a pointer to where the result lives fn eval_body_using_ecx<'mir, 'tcx>( @@ -375,7 +373,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( ecx.tcx, "it is undefined behavior to use this value", |diag| { - diag.note(note_on_undefined_behavior_error()); + diag.note(NOTE_ON_UNDEFINED_BEHAVIOR_ERROR); diag.note(&format!( "the raw bytes of the constant ({}", display_allocation( diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8266f1566c423..c0cf8c6b76b78 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1098,12 +1098,12 @@ impl EarlyLintPass for UnusedDocComment { } fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { - warn_if_doc(cx, block.span, "block", &block.attrs()); + warn_if_doc(cx, block.span, "blocks", &block.attrs()); } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { if let ast::ItemKind::ForeignMod(_) = item.kind { - warn_if_doc(cx, item.span, "extern block", &item.attrs); + warn_if_doc(cx, item.span, "extern blocks", &item.attrs); } } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index eec3b24aec260..37958cc0f4032 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -38,7 +38,9 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; -use rustc_trait_selection::traits::error_reporting::report_object_safety_error; +use rustc_trait_selection::traits::error_reporting::{ + report_object_safety_error, suggestions::NextTypeParamName, +}; use rustc_trait_selection::traits::wf::object_region_bounds; use smallvec::SmallVec; @@ -2986,6 +2988,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Some(r) } + /// Make sure that we are in the condition to suggest the blanket implementation. + fn maybe_lint_blanket_trait_impl( + &self, + self_ty: &hir::Ty<'_>, + diag: &mut DiagnosticBuilder<'_, T>, + ) { + let tcx = self.tcx(); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id); + if let hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Impl(hir::Impl { + self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. + }), + .. + }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id + { + if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) { + return; + } + let of_trait_span = of_trait_ref.path.span; + // make sure that we are not calling unwrap to abort during the compilation + let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; + let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; + // check if the trait has generics, to make a correct suggestion + let param_name = generics.params.next_type_param_name(None); + + let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { + (span, format!(", {}: {}", param_name, impl_trait_name)) + } else { + (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) + }; + diag.multipart_suggestion( + format!("alternatively use a blanket \ + implementation to implement `{of_trait_name}` for \ + all types that also implement `{impl_trait_name}`"), + vec![ + (self_ty.span, param_name), + add_generic_sugg, + ], + Applicability::MaybeIncorrect, + ); + } + } + fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { let tcx = self.tcx(); if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = @@ -3021,9 +3067,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if self_ty.span.edition() >= Edition::Edition2021 { let msg = "trait objects must include the `dyn` keyword"; let label = "add `dyn` keyword before this trait"; - rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg) - .multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable) - .emit(); + let mut diag = + rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); + diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable); + // check if the impl trait that we are considering is a impl of a local trait + self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); + diag.emit(); } else { let msg = "trait objects without an explicit `dyn` are deprecated"; tcx.struct_span_lint_hir( @@ -3031,13 +3080,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty.hir_id, self_ty.span, |lint| { - lint.build(msg) - .multipart_suggestion_verbose( - "use `dyn`", - sugg, - Applicability::MachineApplicable, - ) - .emit(); + let mut diag = lint.build(msg); + diag.multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + self.maybe_lint_blanket_trait_impl::<()>(&self_ty, &mut diag); + diag.emit(); }, ); } diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 0837d9c4a2024..87f85a9842f34 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -1707,12 +1707,14 @@ fn drop_location_span<'tcx>(tcx: TyCtxt<'tcx>, hir_id: hir::HirId) -> Span { hir::Node::Item(item) => match item.kind { hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id), _ => { - bug!("Drop location span error: need to handle more ItemKind {:?}", item.kind); + bug!("Drop location span error: need to handle more ItemKind '{:?}'", item.kind); } }, hir::Node::Block(block) => tcx.hir().span(block.hir_id), + hir::Node::TraitItem(item) => tcx.hir().span(item.hir_id()), + hir::Node::ImplItem(item) => tcx.hir().span(item.hir_id()), _ => { - bug!("Drop location span error: need to handle more Node {:?}", owner_node); + bug!("Drop location span error: need to handle more Node '{:?}'", owner_node); } }; tcx.sess.source_map().end_point(owner_span) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 09308d4d0906d..649ccfcaa9ed8 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -31,7 +31,9 @@ use core::ptr::{self, NonNull}; /// ``` #[unstable(feature = "thin_box", issue = "92791")] pub struct ThinBox { - ptr: WithHeader<::Metadata>, + // This is essentially `WithHeader<::Metadata>`, + // but that would be invariant in `T`, and we want covariance. + ptr: WithOpaqueHeader, _marker: PhantomData, } @@ -59,7 +61,7 @@ impl ThinBox { #[cfg(not(no_global_oom_handling))] pub fn new(value: T) -> Self { let meta = ptr::metadata(&value); - let ptr = WithHeader::new(meta, value); + let ptr = WithOpaqueHeader::new(meta, value); ThinBox { ptr, _marker: PhantomData } } } @@ -83,7 +85,7 @@ impl ThinBox { T: Unsize, { let meta = ptr::metadata(&value as &Dyn); - let ptr = WithHeader::new(meta, value); + let ptr = WithOpaqueHeader::new(meta, value); ThinBox { ptr, _marker: PhantomData } } } @@ -130,7 +132,7 @@ impl Drop for ThinBox { unsafe { let value = self.deref_mut(); let value = value as *mut T; - self.ptr.drop::(value); + self.with_header().drop::(value); } } } @@ -140,11 +142,16 @@ impl ThinBox { fn meta(&self) -> ::Metadata { // Safety: // - NonNull and valid. - unsafe { *self.ptr.header() } + unsafe { *self.with_header().header() } } fn data(&self) -> *mut u8 { - self.ptr.value() + self.with_header().value() + } + + fn with_header(&self) -> &WithHeader<::Metadata> { + // SAFETY: both types are transparent to `NonNull` + unsafe { &*((&self.ptr) as *const WithOpaqueHeader as *const WithHeader<_>) } } } @@ -153,8 +160,22 @@ impl ThinBox { /// metadata (`H`) are ZSTs. /// 2. A pointer to a valid `T` that has a header `H` directly before the /// pointed-to location. +#[repr(transparent)] struct WithHeader(NonNull, PhantomData); +/// An opaque representation of `WithHeader` to avoid the +/// projection invariance of `::Metadata`. +#[repr(transparent)] +struct WithOpaqueHeader(NonNull); + +impl WithOpaqueHeader { + #[cfg(not(no_global_oom_handling))] + fn new(header: H, value: T) -> Self { + let ptr = WithHeader::new(header, value); + Self(ptr.0) + } +} + impl WithHeader { #[cfg(not(no_global_oom_handling))] fn new(header: H, value: T) -> WithHeader { diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs index 70d1db8b45766..368aa564f9436 100644 --- a/library/alloc/tests/thin_box.rs +++ b/library/alloc/tests/thin_box.rs @@ -26,6 +26,13 @@ fn want_thin() { assert!(is_thin::()); } +#[allow(dead_code)] +fn assert_covariance() { + fn thin_box<'new>(b: ThinBox<[&'static str]>) -> ThinBox<[&'new str]> { + b + } +} + #[track_caller] fn verify_aligned(ptr: *const T) { // Use `black_box` to attempt to obscure the fact that we're calling this diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr index 30a96af583af7..1a022c30938f2 100644 --- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr +++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr @@ -71,7 +71,7 @@ LL | LL | / extern "C" { LL | | fn foo(); LL | | } - | |_- rustdoc does not generate documentation for extern block + | |_- rustdoc does not generate documentation for extern blocks | = help: use `//` for a plain comment diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs new file mode 100644 index 0000000000000..b280c8ab6e2b2 --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -0,0 +1,18 @@ +// compile-flags: -Wrust-2021-incompatible-closure-captures + +pub struct A {} + +impl A { + async fn create(path: impl AsRef) { //~ ERROR `async fn` is not permitted in Rust 2015 + //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + ; + crate(move || {} ).await //~ ERROR expected function, found module `crate` + } +} + +trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 +//~^ ERROR functions in traits cannot be declared `async` +//~^^ ERROR cannot find type `T` in this scope +//~^^^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + +//~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr new file mode 100644 index 0000000000000..50de2322907ed --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -0,0 +1,93 @@ +error: this file contains an unclosed delimiter + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + | +LL | trait C{async fn new(val: T) {} + | - unclosed delimiter +... +LL | + | ^ + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5 + | +LL | async fn create(path: impl AsRef) { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + +error[E0423]: expected function, found module `crate` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 + | +LL | crate(move || {} ).await + | ^^^^^ not a function + +error[E0412]: cannot find type `T` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27 + | +LL | pub struct A {} + | ------------ similarly named struct `A` defined here +... +LL | trait C{async fn new(val: T) {} + | ^ help: a struct with a similar name exists: `A` + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 + | +LL | async fn create(path: impl AsRef) { + | _____________________----_____________________________-__^ + | | | | + | | | in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure + | | in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect +LL | | +LL | | ; +LL | | crate(move || {} ).await +LL | | } + | |_____^ + | + = note: requested on the command line with `-W rust-2021-incompatible-closure-captures` + = note: for more information, see +help: add a dummy let to cause `path` to be fully captured + | +LL | async fn create(path: impl AsRef) { let _ = &path; + | ++++++++++++++ + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | --- - ^^ + | | | + | | in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure + | in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect + | + = note: for more information, see +help: add a dummy let to cause `val` to be fully captured + | +LL | trait C{async fn new(val: T) { let _ = &val;} + | +++++++++++++ + +error: aborting due to 6 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs new file mode 100644 index 0000000000000..a776e5089075c --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs @@ -0,0 +1,15 @@ +// compile-flags -Wrust-2021-incompatible-closure-captures + +fn main() {} + +pub(crate) struct Numberer {} + +impl Numberer { + pub(crate) async fn new( + //~^ ERROR `async fn` is not permitted in Rust 2015 + interval: Duration, + //~^ ERROR cannot find type `Duration` in this scope + ) -> Numberer { + Numberer {} + } +} diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr new file mode 100644 index 0000000000000..37b2f4138603d --- /dev/null +++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr @@ -0,0 +1,24 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:8:16 + | +LL | pub(crate) async fn new( + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0412]: cannot find type `Duration` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:10:19 + | +LL | interval: Duration, + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::time::Duration; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0670. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs new file mode 100644 index 0000000000000..7cf536f7966e0 --- /dev/null +++ b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -0,0 +1,58 @@ +// Ensure that the compiler include the blanklet implementation suggestion +// when inside a `impl` statment are used two local traits. +// +// edition:2021 +use std::fmt; + +trait LocalTraitOne { } + +trait LocalTraitTwo { } + +trait GenericTrait {} + +impl LocalTraitTwo for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + +impl fmt::Display for LocalTraitOne { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl fmt::Display for LocalTraitTwo + Send { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl LocalTraitOne for fmt::Display {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + + +impl LocalTraitOne for fmt::Display + Send {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + + +impl GenericTrait for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` + +trait GenericTraitTwo {} + +impl GenericTraitTwo for GenericTrait {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr new file mode 100644 index 0000000000000..d739a8272f152 --- /dev/null +++ b/src/test/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -0,0 +1,107 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 + | +LL | impl LocalTraitTwo for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitTwo for LocalTraitOne {} +LL + impl LocalTraitTwo for dyn LocalTraitOne {} + | +help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + | +LL | impl LocalTraitTwo for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 + | +LL | impl fmt::Display for LocalTraitOne { + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl fmt::Display for LocalTraitOne { +LL + impl fmt::Display for dyn LocalTraitOne { + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 + | +LL | impl fmt::Display for LocalTraitTwo + Send { + | ^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl fmt::Display for LocalTraitTwo + Send { +LL + impl fmt::Display for dyn LocalTraitTwo + Send { + | + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 + | +LL | impl LocalTraitOne for fmt::Display {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitOne for fmt::Display {} +LL + impl LocalTraitOne for dyn fmt::Display {} + | +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + | +LL | impl LocalTraitOne for T {} + | +++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 + | +LL | impl LocalTraitOne for fmt::Display + Send {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl LocalTraitOne for fmt::Display + Send {} +LL + impl LocalTraitOne for dyn fmt::Display + Send {} + | +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + | +LL | impl LocalTraitOne for T {} + | ++++++++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 + | +LL | impl GenericTrait for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl GenericTrait for LocalTraitOne {} +LL + impl GenericTrait for dyn LocalTraitOne {} + | +help: alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` + | +LL | impl GenericTrait for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 + | +LL | impl GenericTraitTwo for GenericTrait {} + | ^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL - impl GenericTraitTwo for GenericTrait {} +LL + impl GenericTraitTwo for dyn GenericTrait {} + | +help: alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` + | +LL | impl> GenericTraitTwo for U {} + | ++++++++++++++++++++ ~ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/suggest-blanket-impl-local-trait b/suggest-blanket-impl-local-trait new file mode 100755 index 0000000000000..0a357e006c357 Binary files /dev/null and b/suggest-blanket-impl-local-trait differ