diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 7cce8a2a46269..370c0ceeda909 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -4,7 +4,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -68,7 +67,6 @@ pub(crate) fn expand_deriving_clone( additional_bounds: bounds.clone(), supports_unions: true, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const, safety: Safety::Unsafe(DUMMY_SP), // `TrivialClone` is not part of an API guarantee, so it shouldn't @@ -91,12 +89,12 @@ pub(crate) fn expand_deriving_clone( generics: cx.empty_generics(span), explicit_self: true, nonself_args: SmallVec::new(), - ret_ty: Self_, + has_other_selflike_arg: false, + ret_ty: cx.ty_self(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: substructure, }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs index 69041a60027d3..c693cbb66fee9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -20,7 +20,6 @@ pub(crate) fn expand_deriving_const_param_ty( additional_bounds: smallvec![path_std!(cx, span, cmp::Eq)], supports_unions: false, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/copy.rs b/compiler/rustc_builtin_macros/src/deriving/copy.rs index 5badeb7e1877e..4ce8598e96711 100644 --- a/compiler/rustc_builtin_macros/src/deriving/copy.rs +++ b/compiler/rustc_builtin_macros/src/deriving/copy.rs @@ -20,7 +20,6 @@ pub(crate) fn expand_deriving_copy( additional_bounds: SmallVec::new(), supports_unions: true, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 66e9b3ed82bcc..2f3d2058773d8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -4,7 +4,6 @@ use rustc_session::config::FmtDebug; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -16,7 +15,12 @@ pub(crate) fn expand_deriving_debug( is_const: bool, ) { // &mut ::std::fmt::Formatter - let fmtr = Ref(Box::new(Path(path_std!(cx, span, fmt::Formatter))), ast::Mutability::Mut); + let fmtr = cx.ty_ref( + span, + cx.ty_path(path_std!(cx, span, fmt::Formatter)), + None, + ast::Mutability::Mut, + ); let trait_def = TraitDef { span, @@ -30,7 +34,8 @@ pub(crate) fn expand_deriving_debug( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(fmtr, sym::character('f'))], - ret_ty: Path(path_std!(cx, span, fmt::Result)), + has_other_selflike_arg: false, + ret_ty: cx.ty_path(path_std!(cx, span, fmt::Result)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, @@ -41,7 +46,6 @@ pub(crate) fn expand_deriving_debug( item.kind.ident().unwrap() )), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, @@ -50,7 +54,7 @@ pub(crate) fn expand_deriving_debug( } fn formatter_ident(cx: &ExtCtxt<'_>, span: Span) -> Box { - cx.expr_ident(span, Ident::new(sym::character('f'), span)) + cx.expr_ident_sym(span, sym::character('f')) } fn show_substructure( @@ -195,9 +199,9 @@ fn show_substructure( args.push(fmt); args.push(name); if is_struct { - args.push(cx.expr_ident(span, Ident::new(sym::names, span))); + args.push(cx.expr_ident_sym(span, sym::names)); } - args.push(cx.expr_ident(span, Ident::new(sym::values, span))); + args.push(cx.expr_ident_sym(span, sym::values)); let expr = cx.expr_call_global(span, fn_path_debug_internal, args); let mut stmts = ThinVec::with_capacity(2); diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 866ffc74da436..28526bdef6b9d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -7,8 +7,8 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use smallvec::SmallVec; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; +use crate::deriving::new_path; use crate::diagnostics; pub(crate) fn expand_deriving_default( @@ -22,7 +22,7 @@ pub(crate) fn expand_deriving_default( let trait_def = TraitDef { span, - path: new_path(cx, span, &[kw::Default, sym::Default], &[]), + path: new_path(cx, span, &[kw::Default, sym::Default], vec![]), skip_path_as_bound: has_a_default_variant(item), needs_copy_as_bound_if_packed: false, additional_bounds: SmallVec::new(), @@ -32,7 +32,8 @@ pub(crate) fn expand_deriving_default( generics: cx.empty_generics(span), explicit_self: false, nonself_args: SmallVec::new(), - ret_ty: Self_, + has_other_selflike_arg: false, + ret_ty: cx.ty_self(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { @@ -49,7 +50,6 @@ pub(crate) fn expand_deriving_default( } }), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs index 1083b37cbf248..da38045994c7f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -4,7 +4,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -29,7 +28,8 @@ pub(crate) fn expand_deriving_eq( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![], - ret_ty: Unit, + has_other_selflike_arg: false, + ret_ty: cx.ty_unit(span), attributes: thin_vec![ // This method will never be called, so doing codegen etc. for it is unnecessary. // We prevent this by adding `#[inline]`, which improves compile-time. @@ -40,7 +40,6 @@ pub(crate) fn expand_deriving_eq( fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(cs_total_eq_assert), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 64cc917302935..df95ccd99f3e6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -5,9 +5,8 @@ use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::pathvec; +use crate::deriving::{new_path, pathvec}; use crate::diagnostics; /// Generate an implementation of the `From` trait, provided that `item` @@ -47,12 +46,12 @@ pub(crate) fn expand_deriving_from( _ => cx.dcx().bug("Invalid derive(From) ADT input"), }; - let from_type = Ty::AstTy(match field { + let from_type = match field { Ok(ref field) => field.ty.clone(), Err(guar) => cx.ty(span, ast::TyKind::Err(guar)), - }); + }; - let path = new_path(cx, span, pathvec!(convert::From), &[from_type.clone()]); + let path = new_path(cx, span, pathvec!(convert::From), vec![from_type.clone()]); // Generate code like this: // @@ -76,7 +75,8 @@ pub(crate) fn expand_deriving_from( generics: cx.empty_generics(span), explicit_self: false, nonself_args: smallvec![(from_type, sym::value)], - ret_ty: Ty::Self_, + has_other_selflike_arg: false, + ret_ty: cx.ty_self(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, span, substructure| { @@ -97,14 +97,14 @@ pub(crate) fn expand_deriving_from( thin_vec![cx.field_imm( span, field.ident.unwrap(), - cx.expr_ident(span, Ident::new(sym::value, span)) + cx.expr_ident_sym(span, sym::value) )], ), // Self(value) VariantData::Tuple(_, _) => cx.expr_call_ident( span, self_kw, - thin_vec![cx.expr_ident(span, Ident::new(sym::value, span))], + thin_vec![cx.expr_ident_sym(span, sym::value)], ), variant => { cx.dcx().bug(format!("Invalid derive(From) ADT variant: {variant:?}")); @@ -115,7 +115,6 @@ pub(crate) fn expand_deriving_from( BlockOrExpr::new_expr(expr) }), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index b6bd482945546..71329da76c481 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -174,9 +174,8 @@ //! ) //! ``` -use std::iter::once; use std::ops::Not; -use std::{iter, vec}; +use std::vec; pub(crate) use Substructure::*; pub(crate) use rustc_ast as ast; @@ -192,12 +191,9 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, respan, sym}; pub(crate) use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; -use ty::{Ref, Self_, Ty}; use crate::{deriving, diagnostics}; -pub(crate) mod ty; - pub(crate) struct TraitDef<'a> { /// The span for the current #[derive(Foo)] header. pub span: Span, @@ -220,8 +216,6 @@ pub(crate) struct TraitDef<'a> { pub methods: SmallVec<[MethodDef<'a>; 1]>, - pub associated_types: SmallVec<[(Ident, Ty); 1]>, - pub is_const: bool, /// The safety of the `impl`. @@ -241,10 +235,13 @@ pub(crate) struct MethodDef<'a> { pub explicit_self: bool, /// Arguments other than the self argument. - pub nonself_args: SmallVec<[(Ty, Symbol); 1]>, + pub nonself_args: SmallVec<[(Box, Symbol); 1]>, + + /// Whether this method has another arg of type `&self`. + pub has_other_selflike_arg: bool, /// Returns type - pub ret_ty: Ty, + pub ret_ty: Box, pub attributes: ast::AttrVec, @@ -294,15 +291,14 @@ pub(crate) enum Substructure<'a> { /// variants has any fields). AllFieldlessEnum(&'a ast::EnumDef), - /// Matching variants of the enum: variant index, ast::Variant, + /// Matching variants of the enum: ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. EnumMatching(&'a ast::Variant, Vec), - /// The discriminant of an enum. The first field is a `FieldInfo` for the discriminants, as - /// if they were fields. The second field is the expression to combine the + /// The discriminant of an enum. The field is the expression to combine the /// discriminant expression with; it will be `None` if no match is necessary. - EnumDiscr(FieldInfo, Option>), + EnumDiscr(Option>), /// A static method where `Self` is a struct. StaticStruct(&'a ast::VariantData), @@ -462,14 +458,30 @@ impl<'a> TraitDef<'a> { push: &mut dyn FnMut(Box), from_scratch: bool, ) { + let span = self.span; let is_packed = matches!( AttributeParser::parse_limited_sym(cx.sess, &item.attrs, &[sym::repr]), Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) ); let mut newitem = match &item.kind { - ast::ItemKind::Struct(ident, generics, struct_def) => { - self.expand_struct_def(cx, struct_def, *ident, generics, from_scratch, is_packed) + ast::ItemKind::Union(..) if !self.supports_unions => { + cx.dcx().emit_err(diagnostics::DeriveUnion { span }); + return; + } + ast::ItemKind::Struct(ident, generics, struct_def) + | ast::ItemKind::Union(ident, generics, struct_def) => { + let fields = struct_def.fields().iter(); + let methods = self.methods.iter().filter_map(|method_def| { + let body = if from_scratch || method_def.is_static() { + method_def.call_substructure_method(cx, span, StaticStruct(struct_def)) + } else { + method_def.expand_struct_method_body(cx, span, struct_def, is_packed) + }; + + method_def.create_method(cx, span, body) + }); + self.create_derived_impl(cx, *ident, generics, fields, methods, is_packed) } ast::ItemKind::Enum(ident, generics, enum_def) => { // We can skip generating the impl here, because `repr(packed)` @@ -479,22 +491,17 @@ impl<'a> TraitDef<'a> { if is_packed { return; } - self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) - } - ast::ItemKind::Union(ident, generics, struct_def) => { - if self.supports_unions { - self.expand_struct_def( - cx, - struct_def, - *ident, - generics, - from_scratch, - is_packed, - ) - } else { - cx.dcx().emit_err(diagnostics::DeriveUnion { span: self.span }); - return; - } + let fields = enum_def.variants.iter().flat_map(|variant| variant.data.fields()); + let methods = self.methods.iter().filter_map(|method_def| { + let body = if from_scratch || method_def.is_static() { + method_def.call_substructure_method(cx, span, StaticEnum(enum_def)) + } else { + method_def.expand_enum_method_body(cx, span, enum_def) + }; + + method_def.create_method(cx, span, body) + }); + self.create_derived_impl(cx, *ident, generics, fields, methods, is_packed) } _ => unreachable!(), }; @@ -558,36 +565,13 @@ impl<'a> TraitDef<'a> { cx: &ExtCtxt<'_>, type_ident: Ident, generics: &Generics, - field_tys: impl Iterator, + fields: impl Iterator, methods: impl Iterator>, is_packed: bool, ) -> Box { - // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem` - let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { - Box::new(ast::AssocItem { - id: ast::DUMMY_NODE_ID, - span: self.span, - vis: ast::Visibility { - span: self.span.shrink_to_lo(), - kind: ast::VisibilityKind::Inherited, - }, - attrs: ast::AttrVec::new(), - kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias { - defaultness: ast::Defaultness::Implicit, - ident, - generics: Generics::default(), - after_where_clause: ast::WhereClause::default(), - bounds: ThinVec::new(), - ty: Some(type_def.to_ty(cx, self.span)), - })), - tokens: None, - }) - }); - let mut where_clause = ast::WhereClause::default(); where_clause.span = generics.where_clause.span; let ctxt = self.span.ctxt(); - let span = generics.span.with_ctxt(ctxt); // Create the generic parameters let params: ThinVec<_> = generics @@ -667,8 +651,8 @@ impl<'a> TraitDef<'a> { .collect(); if !ty_param_names.is_empty() { - for field_ty in field_tys { - let field_ty_params = find_type_parameters(field_ty, &ty_param_names, cx); + for field in fields { + let field_ty_params = find_type_parameters(&field.ty, &ty_param_names, cx); for field_ty_param in field_ty_params { // if we have already handled this type, skip it @@ -716,7 +700,7 @@ impl<'a> TraitDef<'a> { } } - let trait_generics = Generics { params, where_clause, span }; + let trait_generics = Generics { params, where_clause, span: generics.span.with_ctxt(ctxt) }; // Create the reference to the trait. let trait_ref = cx.trait_ref(self.path.clone()); @@ -741,8 +725,6 @@ impl<'a> TraitDef<'a> { let path = cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); - let rustc_const_unstable = - cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),]; @@ -750,6 +732,9 @@ impl<'a> TraitDef<'a> { // Other crates don't need stability attributes, so adding them is not useful, but libcore needs them // on all const trait impls. if self.is_const && cx.ecfg.features.staged_api() { + let rustc_const_unstable = + cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); + // #[rustc_const_unstable(feature = "derive_const", issue = "118304")] attrs.push( cx.attr_nested( @@ -798,72 +783,20 @@ impl<'a> TraitDef<'a> { })), constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, self_ty: self_type, - items: methods.chain(associated_types).collect(), + items: methods.collect(), }), ) } - - fn expand_struct_def( - &self, - cx: &ExtCtxt<'_>, - struct_def: &'a VariantData, - type_ident: Ident, - generics: &Generics, - from_scratch: bool, - is_packed: bool, - ) -> Box { - let field_tys = struct_def.fields().iter().map(|field| &*field.ty); - - let methods = self.methods.iter().filter_map(|method_def| { - let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self, StaticStruct(struct_def)) - } else { - method_def.expand_struct_method_body(cx, self, struct_def, is_packed) - }; - - method_def.create_method(cx, self, body) - }); - - self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) - } - - fn expand_enum_def( - &self, - cx: &ExtCtxt<'_>, - enum_def: &'a EnumDef, - type_ident: Ident, - generics: &Generics, - from_scratch: bool, - ) -> Box { - let field_tys = enum_def - .variants - .iter() - .flat_map(|variant| variant.data.fields()) - .map(|field| &*field.ty); - - let methods = self.methods.iter().filter_map(|method_def| { - let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self, StaticEnum(enum_def)) - } else { - method_def.expand_enum_method_body(cx, self, enum_def, type_ident) - }; - - method_def.create_method(cx, self, body) - }); - - let is_packed = false; // enums are never packed - self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) - } } impl<'a> MethodDef<'a> { fn call_substructure_method( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'_>, + span: Span, substructure: Substructure<'_>, ) -> BlockOrExpr { - (self.combine_substructure)(cx, trait_.span, substructure) + (self.combine_substructure)(cx, span, substructure) } fn is_static(&self) -> bool { @@ -872,30 +805,27 @@ impl<'a> MethodDef<'a> { /// Expressions for `&self` and also any other /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). - fn get_selflike_args(&self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>) -> ThinVec> { + fn get_selflike_args(&self, cx: &ExtCtxt<'_>, span: Span) -> ThinVec> { assert!(self.explicit_self); - let span = trait_.span; - - once(cx.expr_self(span)) - .chain(self.nonself_args.iter().filter_map(|(ty, name)| match ty { - Ref(Self_, _) => Some(cx.expr_ident(span, Ident::new(*name, span))), - _ => None, - })) - .collect() + let self_expr = cx.expr_self(span); + if self.has_other_selflike_arg { + thin_vec![self_expr, cx.expr_ident_sym(span, self.nonself_args[0].1)] + } else { + thin_vec![self_expr] + } } fn create_method( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'_>, + span: Span, body: BlockOrExpr, ) -> Option> { // `assert_fields_are_eq` has an empty default implementation if body.0.is_empty() && body.1.is_none() && self.name == sym::assert_fields_are_eq { return None; } - let span = trait_.span; // Create the generics that aren't for `Self`. let fn_generics = self.generics.clone(); @@ -910,16 +840,16 @@ impl<'a> MethodDef<'a> { let args = self_arg .into_iter() .chain(self.nonself_args.iter().map(|(ty, name)| { - let ast_ty = ty.to_ty(cx, span); + let ast_ty = ty.clone(); let ident = Ident::new(*name, span); cx.param(span, ident, ast_ty) })) .collect(); - let ret_type = if let Ty::Unit = &self.ret_ty { + let ret_type = if self.ret_ty.kind.is_unit() { ast::FnRetTy::Default(span) } else { - ast::FnRetTy::Ty(self.ret_ty.to_ty(cx, span)) + ast::FnRetTy::Ty(self.ret_ty.clone()) }; let method_ident = Ident::new(self.name, span); @@ -989,15 +919,15 @@ impl<'a> MethodDef<'a> { fn expand_struct_method_body<'b>( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'b>, + span: Span, struct_def: &'b VariantData, is_packed: bool, ) -> BlockOrExpr { - let selflike_args = self.get_selflike_args(cx, trait_); + let selflike_args = self.get_selflike_args(cx, span); let selflike_fields = - trait_.create_struct_field_access_fields(cx, &selflike_args, struct_def, is_packed); - self.call_substructure_method(cx, trait_, Struct(struct_def, selflike_fields)) + create_struct_field_access_fields(span, cx, &selflike_args, struct_def, is_packed); + self.call_substructure_method(cx, span, Struct(struct_def, selflike_fields)) } /// ``` @@ -1038,11 +968,9 @@ impl<'a> MethodDef<'a> { fn expand_enum_method_body<'b>( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'b>, + span: Span, enum_def: &'b EnumDef, - type_ident: Ident, ) -> BlockOrExpr { - let span = trait_.span; let variants = &enum_def.variants; // Traits that unify fieldless variants always use the discriminant(s). @@ -1059,48 +987,12 @@ impl<'a> MethodDef<'a> { return BlockOrExpr(ThinVec::new(), Some(expr)); } - let selflike_args = self.get_selflike_args(cx, trait_); - - let prefixes = iter::once("__self".to_string()) - .chain((1..selflike_args.len()).map(|arg_count| format!("__arg{arg_count}"))) - .collect::>(); - - // Build a series of let statements mapping each selflike_arg - // to its discriminant value. - // - // e.g. for `PartialEq::eq` builds two statements: - // ``` - // let __self_discr = ::core::intrinsics::discriminant_value(self); - // let __arg1_discr = ::core::intrinsics::discriminant_value(other); - // ``` - let get_discr_pieces = || { - let discr_idents = prefixes - .iter() - .map(|name| Ident::from_str_and_span(&format!("{name}_discr"), span)); - - let mut discr_exprs = - discr_idents.clone().map(|ident| cx.expr_addr_of(span, cx.expr_ident(span, ident))); + let selflike_args = self.get_selflike_args(cx, span); - let self_expr = discr_exprs.next().unwrap(); - let other_selflike_expr = discr_exprs.next(); - debug_assert!(discr_exprs.next().is_none()); - - let discr_field = - FieldInfo { span, name: None, self_expr, other_selflike_expr, maybe_scalar: true }; - - let discr_let_stmts: ThinVec<_> = iter::zip(discr_idents, &selflike_args) - .map(|(ident, selflike_arg)| { - let variant_value = deriving::call_intrinsic( - cx, - span, - sym::discriminant_value, - thin_vec![selflike_arg.clone()], - ); - cx.stmt_let(span, false, ident, variant_value) - }) - .collect(); - - (discr_field, discr_let_stmts) + let prefixes: &[&str] = match selflike_args.len() { + 1 => &["__self"], + 2 => &["__self", "__arg1"], + _ => unreachable!(), }; // There are some special cases involving fieldless enums where no @@ -1113,29 +1005,17 @@ impl<'a> MethodDef<'a> { // If the type is fieldless and the trait uses the discriminant and // there are multiple variants, we need just an operation on // the discriminant(s). - let (discr_field, mut discr_let_stmts) = get_discr_pieces(); - let mut discr_check = - self.call_substructure_method(cx, trait_, EnumDiscr(discr_field, None)); - discr_let_stmts.append(&mut discr_check.0); - return BlockOrExpr(discr_let_stmts, discr_check.1); + return self.call_substructure_method(cx, span, EnumDiscr(None)); } FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => { - return self.call_substructure_method( - cx, - trait_, - AllFieldlessEnum(enum_def), - ); + return self.call_substructure_method(cx, span, AllFieldlessEnum(enum_def)); } FieldlessVariantsStrategy::Default => (), } } else if let [variant] = variants.as_slice() { // If there is a single variant, we don't need an operation on // the discriminant(s). Just use the most degenerate result. - return self.call_substructure_method( - cx, - trait_, - EnumMatching(variant, Vec::new()), - ); + return self.call_substructure_method(cx, span, EnumMatching(variant, Vec::new())); } } @@ -1151,12 +1031,13 @@ impl<'a> MethodDef<'a> { // A single arm has form (&VariantK, &VariantK, ...) => BodyK // (see "Final wrinkle" note below for why.) - let fields = trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes); + let fields = create_struct_pattern_fields(span, cx, &variant.data, &prefixes); - let sp = variant.span.with_ctxt(trait_.span.ctxt()); - let variant_path = cx.path(sp, vec![type_ident, variant.ident]); + let sp = variant.span.with_ctxt(span.ctxt()); + let variant_path = + cx.path(sp, vec![Ident::new(kw::SelfUpper, span), variant.ident]); let mut subpats = - trait_.create_struct_patterns(cx, variant_path, &variant.data, &prefixes); + create_struct_patterns(span, cx, variant_path, &variant.data, &prefixes); // `(VariantK, VariantK, ...)` or just `VariantK`. let single_pat = if subpats.len() == 1 { @@ -1175,7 +1056,7 @@ impl<'a> MethodDef<'a> { // Build up code associated with such a case. let substructure = EnumMatching(variant, fields); let arm_expr = - self.call_substructure_method(cx, trait_, substructure).into_expr(cx, span); + self.call_substructure_method(cx, span, substructure).into_expr(cx, span); cx.arm(span, single_pat, arm_expr) }) @@ -1185,17 +1066,15 @@ impl<'a> MethodDef<'a> { let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); let default = match first_fieldless { Some(v) if unify_fieldless_variants => { - // We need a default case that handles all the fieldless - // variants. The index and actual variant aren't meaningful in - // this case, so just use dummy values. + // We need a default case that handles all the fieldless variants. Some( - self.call_substructure_method(cx, trait_, EnumMatching(v, Vec::new())) + self.call_substructure_method(cx, span, EnumMatching(v, Vec::new())) .into_expr(cx, span), ) } _ if variants.len() > 1 && selflike_args.len() > 1 => { // Because we know that all the arguments will match if we reach - // the match expression we add the unreachable intrinsics as the + // the match expression we add the unreachable intrinsic as the // result of the default which should help llvm in optimizing it. Some(deriving::call_unreachable(cx, span)) } @@ -1217,7 +1096,7 @@ impl<'a> MethodDef<'a> { let match_arg = if selflike_args.len() == 1 { selflike_args.pop().unwrap() } else { - cx.expr(span, ast::ExprKind::Tup(selflike_args)) + cx.expr_tuple(span, selflike_args) }; cx.expr_match(span, match_arg, match_arms) }; @@ -1226,16 +1105,8 @@ impl<'a> MethodDef<'a> { // to add a discriminant check operation before the match. Otherwise, the match // is enough. if unify_fieldless_variants && variants.len() > 1 { - let (discr_field, mut discr_let_stmts) = get_discr_pieces(); - // Combine a discriminant check with the match. - let mut discr_check_plus_match = self.call_substructure_method( - cx, - trait_, - EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), - ); - discr_let_stmts.append(&mut discr_check_plus_match.0); - BlockOrExpr(discr_let_stmts, discr_check_plus_match.1) + self.call_substructure_method(cx, span, EnumDiscr(Some(get_match_expr(selflike_args)))) } else { BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args))) } @@ -1243,179 +1114,128 @@ impl<'a> MethodDef<'a> { } // general helper methods. -impl<'a> TraitDef<'a> { - fn create_struct_patterns( - &self, - cx: &ExtCtxt<'_>, - struct_path: ast::Path, - struct_def: &'a VariantData, - prefixes: &[String], - ) -> ThinVec { +fn create_struct_patterns( + span: Span, + cx: &ExtCtxt<'_>, + struct_path: ast::Path, + struct_def: &VariantData, + prefixes: &[&str], +) -> ThinVec { + prefixes + .iter() + .map(|prefix| { + let pieces_iter = struct_def.fields().iter().enumerate().map(|(i, struct_field)| { + let ident = mk_pattern_ident(span, prefix, i); + let path = ident.with_span_pos(struct_field.span); + (struct_field.ident, cx.pat_ident(path.span, path)) + }); + + let struct_path = struct_path.clone(); + match *struct_def { + VariantData::Struct { .. } => { + let field_pats = pieces_iter + .map(|(ident, pat)| ast::PatField { + ident: ident.expect("a braced struct with unnamed fields in `derive`"), + is_shorthand: false, + attrs: ast::AttrVec::new(), + id: ast::DUMMY_NODE_ID, + span: pat.span.with_ctxt(span.ctxt()), + pat: Box::new(pat), + is_placeholder: false, + }) + .collect(); + cx.pat_struct(span, struct_path, field_pats) + } + VariantData::Tuple(..) => { + let subpats = pieces_iter.map(|(_, subpat)| subpat).collect(); + cx.pat_tuple_struct(span, struct_path, subpats) + } + VariantData::Unit(..) => cx.pat_path(span, struct_path), + } + }) + .collect() +} + +fn create_fields(span: Span, struct_def: &VariantData, mk_exprs: F) -> Vec +where + F: Fn(usize, &ast::FieldDef, Span) -> Vec>, +{ + struct_def + .fields() + .iter() + .enumerate() + .map(|(i, struct_field)| { + // For this field, get an expr for each selflike_arg. E.g. for + // `PartialEq::eq`, one for each of `&self` and `other`. + let span = struct_field.span.with_ctxt(span.ctxt()); + let mut exprs: Vec<_> = mk_exprs(i, struct_field, span); + let self_expr = exprs.remove(0); + debug_assert!(exprs.len() <= 1); + FieldInfo { + span, + name: struct_field.ident, + self_expr, + other_selflike_expr: exprs.pop(), + maybe_scalar: struct_field.ty.peel_refs().kind.maybe_scalar(), + } + }) + .collect() +} + +fn mk_pattern_ident(span: Span, prefix: &str, i: usize) -> Ident { + Ident::from_str_and_span(&format!("{prefix}_{i}"), span) +} + +fn create_struct_pattern_fields( + span: Span, + cx: &ExtCtxt<'_>, + struct_def: &VariantData, + prefixes: &[&str], +) -> Vec { + create_fields(span, struct_def, |i, _struct_field, sp| { prefixes .iter() .map(|prefix| { - let pieces_iter = - struct_def.fields().iter().enumerate().map(|(i, struct_field)| { - let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let ident = self.mk_pattern_ident(prefix, i); - let path = ident.with_span_pos(sp); - (struct_field.ident, cx.pat_ident(path.span, path)) - }); - - let struct_path = struct_path.clone(); - match *struct_def { - VariantData::Struct { .. } => { - let field_pats = pieces_iter - .map(|(ident, pat)| ast::PatField { - ident: ident - .expect("a braced struct with unnamed fields in `derive`"), - is_shorthand: false, - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - span: pat.span.with_ctxt(self.span.ctxt()), - pat: Box::new(pat), - is_placeholder: false, - }) - .collect(); - cx.pat_struct(self.span, struct_path, field_pats) - } - VariantData::Tuple(..) => { - let subpats = pieces_iter.map(|(_, subpat)| subpat).collect(); - cx.pat_tuple_struct(self.span, struct_path, subpats) - } - VariantData::Unit(..) => cx.pat_path(self.span, struct_path), - } + let ident = mk_pattern_ident(span, prefix, i); + cx.expr_path(cx.path_ident(sp, ident)) }) .collect() - } + }) +} - fn create_fields(&self, struct_def: &'a VariantData, mk_exprs: F) -> Vec - where - F: Fn(usize, &ast::FieldDef, Span) -> Vec>, - { - struct_def - .fields() +fn create_struct_field_access_fields( + span: Span, + cx: &ExtCtxt<'_>, + selflike_args: &[Box], + struct_def: &VariantData, + is_packed: bool, +) -> Vec { + create_fields(span, struct_def, |i, struct_field, sp| { + selflike_args .iter() - .enumerate() - .map(|(i, struct_field)| { - // For this field, get an expr for each selflike_arg. E.g. for - // `PartialEq::eq`, one for each of `&self` and `other`. - let span = struct_field.span.with_ctxt(self.span.ctxt()); - let mut exprs: Vec<_> = mk_exprs(i, struct_field, span); - let self_expr = exprs.remove(0); - debug_assert!(exprs.len() <= 1); - FieldInfo { - span, - name: struct_field.ident, - self_expr, - other_selflike_expr: exprs.pop(), - maybe_scalar: struct_field.ty.peel_refs().kind.maybe_scalar(), + .map(|selflike_arg| { + // Note: we must use `struct_field.span` rather than `sp` in the + // `unwrap_or_else` case otherwise the hygiene is wrong and we get + // "field `0` of struct `Point` is private" errors on tuple + // structs. + let mut field_expr = cx.expr( + sp, + ast::ExprKind::Field( + selflike_arg.clone(), + struct_field.ident.unwrap_or_else(|| { + Ident::from_str_and_span(&i.to_string(), struct_field.span) + }), + ), + ); + if is_packed { + // Fields in packed structs are wrapped in a block, e.g. `&{self.0}`, + // causing a copy instead of a (potentially misaligned) reference. + field_expr = cx.expr_block( + cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]), + ); } + cx.expr_addr_of(sp, field_expr) }) .collect() - } - - fn mk_pattern_ident(&self, prefix: &str, i: usize) -> Ident { - Ident::from_str_and_span(&format!("{prefix}_{i}"), self.span) - } - - fn create_struct_pattern_fields( - &self, - cx: &ExtCtxt<'_>, - struct_def: &'a VariantData, - prefixes: &[String], - ) -> Vec { - self.create_fields(struct_def, |i, _struct_field, sp| { - prefixes - .iter() - .map(|prefix| { - let ident = self.mk_pattern_ident(prefix, i); - cx.expr_path(cx.path_ident(sp, ident)) - }) - .collect() - }) - } - - fn create_struct_field_access_fields( - &self, - cx: &ExtCtxt<'_>, - selflike_args: &[Box], - struct_def: &'a VariantData, - is_packed: bool, - ) -> Vec { - self.create_fields(struct_def, |i, struct_field, sp| { - selflike_args - .iter() - .map(|selflike_arg| { - // Note: we must use `struct_field.span` rather than `sp` in the - // `unwrap_or_else` case otherwise the hygiene is wrong and we get - // "field `0` of struct `Point` is private" errors on tuple - // structs. - let mut field_expr = cx.expr( - sp, - ast::ExprKind::Field( - selflike_arg.clone(), - struct_field.ident.unwrap_or_else(|| { - Ident::from_str_and_span(&i.to_string(), struct_field.span) - }), - ), - ); - if is_packed { - // Fields in packed structs are wrapped in a block, e.g. `&{self.0}`, - // causing a copy instead of a (potentially misaligned) reference. - field_expr = cx.expr_block( - cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]), - ); - } - cx.expr_addr_of(sp, field_expr) - }) - .collect() - }) - } -} - -/// Folds over fields, combining the expressions for each field in a sequence. -/// Statics may not be folded over. -pub(crate) fn cs_foldr( - cx: &ExtCtxt<'_>, - trait_span: Span, - substructure: Substructure<'_>, - // The basic case: a field expression for one or more selflike args. E.g. - // for `PartialEq::eq` this is something like `self.x == other.x`. - single: impl Fn(FieldInfo) -> Box, - // The combination of two field expressions. E.g. for `PartialEq::eq` this - // is something like ` && `. - combine: impl Fn(Span, Box, Box) -> Box, - // The fallback case for a struct or enum variant with no fields. - fieldless: impl Fn() -> Box, -) -> Box { - match substructure { - EnumMatching(.., all_fields) | Struct(_, all_fields) => { - let mut fields = all_fields.into_iter(); - let base_field = fields.next_back(); - - let Some(base_field) = base_field else { - return fieldless(); - }; - - let base_expr = single(base_field); - - let op = |old, field: FieldInfo| { - let span = field.span; - let new = single(field); - combine(span, old, new) - }; - - fields.rfold(base_expr, op) - } - EnumDiscr(discr_field, match_expr) => { - let discr_check_expr = single(discr_field); - if let Some(match_expr) = match_expr { - combine(trait_span, match_expr, discr_check_expr) - } else { - discr_check_expr - } - } - _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive`"), - } + }) } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs deleted file mode 100644 index 8f2de7a46fa18..0000000000000 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! 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. - -use std::iter::once; - -pub(crate) use Ty::*; -use rustc_ast::{self as ast, GenericArg}; -use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, Symbol, kw}; -use thin_vec::ThinVec; - -pub(crate) fn new_path(cx: &ExtCtxt<'_>, span: Span, path: &[Symbol], params: &[Ty]) -> ast::Path { - let idents = path.iter().map(|s| Ident::new(*s, span)); - let tys = params.iter().map(|t| t.to_ty(cx, span)); - let params = tys.map(GenericArg::Type).collect(); - - let idents = once(Ident::new(kw::DollarCrate, span)).chain(idents).collect(); - cx.path_all(span, false, idents, params) -} - -/// A type. Supports pointers, Self, literals, unit or an arbitrary AST path. -#[derive(Clone)] -pub(crate) enum Ty { - Self_, - /// A reference. - Ref(Box, ast::Mutability), - /// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type - /// parameter, and things like `i32` - Path(ast::Path), - /// For () return types. - Unit, - /// An arbitrary type. - AstTy(Box), -} - -pub(crate) fn self_ref() -> Ty { - Ref(Box::new(Self_), ast::Mutability::Not) -} - -impl Ty { - pub(crate) fn to_ty(&self, cx: &ExtCtxt<'_>, span: Span) -> Box { - match self { - Ref(ty, mutbl) => { - let raw_ty = ty.to_ty(cx, span); - cx.ty_ref(span, raw_ty, None, *mutbl) - } - Path(p) => cx.ty_path(p.clone()), - Self_ => cx.ty_path(cx.path_ident(span, Ident::new(kw::SelfUpper, span))), - Unit => cx.ty(span, ast::TyKind::Tup(ThinVec::new())), - AstTy(ty) => ty.clone(), - } - } -} diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 55c1d338c5d2d..3d3023b39955d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -1,11 +1,10 @@ use rustc_ast::{Mutability, Safety}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::path_std; +use crate::deriving::{call_discriminant_value, path_std}; pub(crate) fn expand_deriving_hash( cx: &ExtCtxt<'_>, @@ -18,7 +17,7 @@ pub(crate) fn expand_deriving_hash( let typaram = Ident::new(sym::__H, span); - let arg = cx.path_ident(span, typaram); + let arg = cx.ty_path(cx.path_ident(span, typaram)); let param = { let path = path_std!(cx, span, hash::Hasher); @@ -42,13 +41,13 @@ pub(crate) fn expand_deriving_hash( name: sym::hash, generics, explicit_self: true, - nonself_args: smallvec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], - ret_ty: Unit, + nonself_args: smallvec![(cx.ty_ref(span, arg, None, Mutability::Mut), sym::state)], + has_other_selflike_arg: false, + ret_ty: cx.ty_unit(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(hash_substructure), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, @@ -57,15 +56,12 @@ pub(crate) fn expand_deriving_hash( hash_trait_def.expand(cx, item, push); } -fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr { +fn hash_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { let call_hash = |span, expr| { let strs = cx.std_path(&[sym::hash, sym::Hash, sym::hash]); let hash_path = cx.expr_path(cx.path_global(span, strs)); - let expr = cx.expr_call( - span, - hash_path, - thin_vec![expr, cx.expr_ident(span, Ident::new(sym::state, span))], - ); + let expr = + cx.expr_call(span, hash_path, thin_vec![expr, cx.expr_ident_sym(span, sym::state)]); cx.stmt_expr(expr) }; @@ -75,12 +71,14 @@ fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_ fields.into_iter().map(|field| call_hash(field.span, field.self_expr)).collect(); (stmts, None) } - EnumDiscr(discr_field, match_expr) => { - assert!(discr_field.other_selflike_expr.is_none()); - let stmts = thin_vec![call_hash(discr_field.span, discr_field.self_expr)]; + EnumDiscr(match_expr) => { + let stmts = thin_vec![call_hash( + span, + cx.expr_addr_of(span, call_discriminant_value(cx, span, kw::SelfLower)) + )]; (stmts, match_expr) } - _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive(Hash)`"), + _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(Hash)`"), }; BlockOrExpr::new_mixed(stmts, match_expr) diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 66d4a61b97fdc..c4af6ac16bdc6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -1,9 +1,11 @@ //! The compiler code necessary to implement the `#[derive]` extensions. +use std::iter::once; + use rustc_ast as ast; use rustc_ast::{GenericArg, MetaItem}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Ident, Span, Symbol, kw, sym}; use thin_vec::{ThinVec, thin_vec}; macro pathvec($($rest:ident)::+) {{ @@ -11,7 +13,7 @@ macro pathvec($($rest:ident)::+) {{ }} macro path_std($cx: expr, $span: expr, $($x:tt)*) { - generic::ty::new_path($cx, $span, pathvec!( $($x)* ), &[] ) + new_path($cx, $span, pathvec!( $($x)* ), vec![] ) } pub(crate) mod clone; @@ -87,6 +89,11 @@ fn call_intrinsic( cx.expr_call_global(span, path, args) } +/// Constructs an expression that calls the `discriminant_value` intrinsic. +fn call_discriminant_value(cx: &ExtCtxt<'_>, span: Span, arg: Symbol) -> Box { + call_intrinsic(cx, span, sym::discriminant_value, thin_vec![cx.expr_ident_sym(span, arg)]) +} + /// Constructs an expression that calls the `unreachable` intrinsic. fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> Box { let call = call_intrinsic(cx, span, sym::unreachable, ThinVec::new()); @@ -110,3 +117,11 @@ fn assert_ty_bounds( let assert_path = cx.path_all(span, true, cx.std_path(assert_path), vec![GenericArg::Type(ty)]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } + +fn new_path(cx: &ExtCtxt<'_>, span: Span, path: &[Symbol], params: Vec>) -> ast::Path { + let idents = path.iter().map(|s| Ident::new(*s, span)); + let params = params.into_iter().map(GenericArg::Type).collect(); + + let idents = once(Ident::new(kw::DollarCrate, span)).chain(idents).collect(); + cx.path_all(span, false, idents, params) +} diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index 426fa41a3b6d4..c20bfc81bd409 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -1,10 +1,10 @@ use rustc_ast::Safety; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Span, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; +use crate::deriving::partial_ord::{OrdlikeDerive, cmp_body, discr_data_order}; use crate::deriving::path_std; pub(crate) fn expand_deriving_ord( @@ -14,6 +14,8 @@ pub(crate) fn expand_deriving_ord( push: &mut dyn FnMut(Box), is_const: bool, ) { + let discr_then_data = discr_data_order(item); + let trait_def = TraitDef { span, path: path_std!(cx, span, cmp::Ord), @@ -25,13 +27,18 @@ pub(crate) fn expand_deriving_ord( name: sym::cmp, generics: cx.empty_generics(span), explicit_self: true, - nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: Path(path_std!(cx, span, cmp::Ordering)), + nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)], + has_other_selflike_arg: true, + ret_ty: cx.ty_path(path_std!(cx, span, cmp::Ordering)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, - combine_substructure: combine_substructure(cs_cmp), + combine_substructure: combine_substructure(|cx, span, substr| cs_cmp( + cx, + span, + substr, + discr_then_data + )), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, @@ -40,11 +47,12 @@ pub(crate) fn expand_deriving_ord( trait_def.expand(cx, item, push) } -pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { - let test_id = Ident::new(sym::cmp, span); - let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); - +pub(crate) fn cs_cmp( + cx: &ExtCtxt<'_>, + span: Span, + substr: Substructure<'_>, + discr_then_data: bool, +) -> BlockOrExpr { // Builds: // // match ::core::cmp::Ord::cmp(&self.x, &other.x) { @@ -52,22 +60,6 @@ pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> // ::core::cmp::Ord::cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_foldr( - cx, - span, - substr, - |field| { - let other_expr = - field.other_selflike_expr.expect("not exactly 2 arguments in `derive(Ord)`"); - let args = thin_vec![field.self_expr, other_expr]; - cx.expr_call_global(field.span, cmp_path.clone(), args) - }, - |span, expr1, expr2| { - let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); - let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); - cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) - }, - || cx.expr_path(equal_path.clone()), - ); + let expr = cmp_body(cx, span, substr, discr_then_data, OrdlikeDerive::Ord); BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 5c8a6225fa91b..377a32dcca4f0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -1,11 +1,10 @@ use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, Mutability, Safety}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::path_std; +use crate::deriving::{call_discriminant_value, path_std}; /// Expands a `#[derive(PartialEq)]` attribute into an implementation for the /// target item. @@ -29,7 +28,6 @@ pub(crate) fn expand_deriving_partial_eq( // a second check here would lead to redundant error messages. supports_unions: true, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const: false, safety: Safety::Default, document: true, @@ -42,8 +40,9 @@ pub(crate) fn expand_deriving_partial_eq( name: sym::eq, generics: cx.empty_generics(span), explicit_self: true, - nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: Path(cx.path_ident(span, Ident::new(sym::bool, span))), + nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)], + has_other_selflike_arg: true, + ret_ty: cx.ty_path(cx.path_ident(span, Ident::new(sym::bool, span))), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(get_substructure_equality_expr), @@ -57,7 +56,6 @@ pub(crate) fn expand_deriving_partial_eq( additional_bounds: SmallVec::new(), supports_unions: false, methods, - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, @@ -123,8 +121,18 @@ fn get_substructure_equality_expr( ) -> BlockOrExpr { BlockOrExpr::new_expr(match substructure { EnumMatching(.., fields) | Struct(.., fields) => { - let combine = move |acc, field| { - let rhs = get_field_equality_expr(cx, field); + let combine = move |acc, field: &FieldInfo| { + let rhs = field + .other_selflike_expr + .as_ref() + .expect("not exactly 2 arguments in `derive(PartialEq)`"); + + let rhs = cx.expr_binary( + field.span, + BinOpKind::Eq, + wrap_block_expr(cx, peel_refs(&field.self_expr)), + wrap_block_expr(cx, peel_refs(rhs)), + ); match acc { // Combine the previous comparison with the current field // using logical AND. @@ -144,43 +152,21 @@ fn get_substructure_equality_expr( // If there are no fields, treat as always equal. .unwrap_or_else(|| cx.expr_bool(span, true)) } - EnumDiscr(disc, match_expr) => { - let lhs = get_field_equality_expr(cx, &disc); + EnumDiscr(match_expr) => { + let self_expr = call_discriminant_value(cx, span, kw::SelfLower); + let other_selflike_expr = call_discriminant_value(cx, span, sym::other); + let lhs = cx.expr_binary(span, BinOpKind::Eq, self_expr, other_selflike_expr); let Some(match_expr) = match_expr else { return BlockOrExpr::new_expr(lhs); }; // Compare the discriminant first (cheaper), then the rest of the // fields. - cx.expr_binary(disc.span, BinOpKind::And, lhs, match_expr.clone()) + cx.expr_binary(span, BinOpKind::And, lhs, match_expr) } _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(PartialEq)`"), }) } -/// Generates an equality comparison expression for a single struct or enum -/// field. -/// -/// This function produces an AST expression that compares the `self` and -/// `other` values for a field using `==`. It removes any leading references -/// from both sides for readability. If the field is a block expression, it is -/// wrapped in parentheses to ensure valid syntax. -/// -/// # Panics -/// -/// Panics if there are not exactly two arguments to compare (should be `self` -/// and `other`). -fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> Box { - let rhs = - field.other_selflike_expr.as_ref().expect("not exactly 2 arguments in `derive(PartialEq)`"); - - cx.expr_binary( - field.span, - BinOpKind::Eq, - wrap_block_expr(cx, peel_refs(&field.self_expr)), - wrap_block_expr(cx, peel_refs(rhs)), - ) -} - /// Removes all leading immutable references from an expression. /// /// This is used to strip away any number of leading `&` from an expression diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index e176152c507c9..8c3e2ee58f8e2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -1,11 +1,10 @@ -use rustc_ast::{ExprKind, ItemKind, PatKind, Safety, ast}; +use rustc_ast::{Expr, ItemKind, Safety, ast}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::{path_std, pathvec}; +use crate::deriving::{call_discriminant_value, new_path, path_std, pathvec}; pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, @@ -14,36 +13,18 @@ pub(crate) fn expand_deriving_partial_ord( push: &mut dyn FnMut(Box), is_const: bool, ) { - let ordering_ty = Path(path_std!(cx, span, cmp::Ordering)); - let ret_ty = Path(new_path(cx, span, pathvec!(option::Option), &[ordering_ty])); + let ordering_ty = cx.ty_path(path_std!(cx, span, cmp::Ordering)); + let ret_ty = cx.ty_path(new_path(cx, span, pathvec!(option::Option), vec![ordering_ty])); // Order in which to perform matching - let discr_then_data = if let ItemKind::Enum(_, _, def) = &item.kind { - let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); - match dataful.iter().filter(|&&b| b).count() { - // No data, placing the discriminant check first makes codegen simpler - 0 => true, - 1..=2 => false, - _ => (0..dataful.len() - 1).any(|i| { - if dataful[i] - && let Some(idx) = dataful[i + 1..].iter().position(|v| *v) - { - idx >= 2 - } else { - false - } - }), - } - } else { - true - }; + let discr_then_data = discr_data_order(item); let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_ord = cx.resolver.has_derive_ord(container_id); let default_substructure = combine_substructure(|cx, span, substr| cs_partial_cmp(cx, span, substr, discr_then_data)); let simple_substructure = combine_substructure(|cx, span, _| { - cs_partial_cmp_simple(cx, span, cx.expr_ident(span, Ident::new(sym::other, span))) + cs_partial_cmp_simple(cx, span, cx.expr_ident_sym(span, sym::other)) }); let is_simple = match &item.kind { // For unit structs/zero-variant enums, the default generated code is better. @@ -72,7 +53,8 @@ pub(crate) fn expand_deriving_partial_ord( name: sym::partial_cmp, generics: cx.empty_generics(span), explicit_self: true, - nonself_args: smallvec![(self_ref(), sym::other)], + nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)], + has_other_selflike_arg: true, ret_ty, attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, @@ -87,7 +69,6 @@ pub(crate) fn expand_deriving_partial_ord( additional_bounds: smallvec![], supports_unions: false, methods: smallvec![partial_cmp_def], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, @@ -95,6 +76,28 @@ pub(crate) fn expand_deriving_partial_ord( trait_def.expand_ext(cx, item, push, is_simple) } +pub(crate) fn discr_data_order(item: &ast::Item) -> bool { + if let ItemKind::Enum(_, _, def) = &item.kind { + let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); + match dataful.iter().filter(|&&b| b).count() { + // No data, placing the discriminant check first makes codegen simpler + 0 => true, + 1..=2 => false, + _ => (0..dataful.len() - 1).any(|i| { + if dataful[i] + && let Some(idx) = dataful[i + 1..].iter().position(|v| *v) + { + idx >= 2 + } else { + false + } + }), + } + } else { + true + } +} + // Special case for the type deriving both `PartialOrd` and `Ord`. Builds: // ``` // Some(::core::cmp::Ord::cmp(self, other)) @@ -112,10 +115,6 @@ fn cs_partial_cmp( substr: Substructure<'_>, discr_then_data: bool, ) -> BlockOrExpr { - let test_id = Ident::new(sym::cmp, span); - let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]); - // Builds: // // match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { @@ -123,63 +122,121 @@ fn cs_partial_cmp( // ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_foldr( - cx, - span, - substr, - |field| { - let other_expr = - field.other_selflike_expr.expect("not exactly 2 arguments in `derive(PartialOrd)`"); - let args = thin_vec![field.self_expr, other_expr]; - cx.expr_call_global(field.span, partial_cmp_path.clone(), args) - }, - |span, mut expr1, expr2| { - // When the item is an enum, this expands to - // ``` - // match (expr2) { - // Some(Ordering::Equal) => expr1, - // cmp => cmp - // } - // ``` - // where `expr2` is `partial_cmp(self_discr, other_discr)`, and `expr1` is a `match` - // against the enum variants. This means that we begin by comparing the enum discriminants, - // before either inspecting their contents (if they match), or returning - // the `cmp::Ordering` of comparing the enum discriminants. - // ``` - // match partial_cmp(self_discr, other_discr) { - // Some(Ordering::Equal) => match (self, other) { - // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), - // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0), - // _ => Some(Ordering::Equal) - // } - // cmp => cmp - // } - // ``` - // If we have any certain enum layouts, flipping this results in better codegen - // ``` - // match (self, other) { - // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), - // _ => partial_cmp(self_discr, other_discr) - // } - // ``` - // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 + let expr = cmp_body(cx, span, substr, discr_then_data, OrdlikeDerive::PartialOrd); + BlockOrExpr::new_expr(expr) +} + +#[derive(PartialEq)] +pub(crate) enum OrdlikeDerive { + PartialOrd, + Ord, +} + +pub(crate) fn cmp_body( + cx: &ExtCtxt<'_>, + span: Span, + substructure: Substructure<'_>, + discr_then_data: bool, + derive: OrdlikeDerive, +) -> Box { + let is_partial_ord = derive == OrdlikeDerive::PartialOrd; + let method_path = if is_partial_ord { + cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]) + } else { + cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]) + }; + let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); + + // The combination of two field expressions. E.g. for `Ord::cmp` this + // is something like ` && `. + let combine = |span, mut expr1: Box, expr2| { + // For `PartialOrd` (`Ord` works the same but without the `Some` wrapping), + // when the item is an enum, this expands to + // ``` + // match (expr2) { + // Some(Ordering::Equal) => expr1, + // cmp => cmp + // } + // ``` + // where `expr2` is `partial_cmp(self_discr, other_discr)`, and `expr1` is a `match` + // against the enum variants. This means that we begin by comparing the enum discriminants, + // before either inspecting their contents (if they match), or returning + // the `cmp::Ordering` of comparing the enum discriminants. + // ``` + // match partial_cmp(self_discr, other_discr) { + // Some(Ordering::Equal) => match (self, other) { + // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), + // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0), + // _ => Some(Ordering::Equal) + // } + // cmp => cmp + // } + // ``` + // If we have any certain enum layouts, flipping this results in better codegen + // ``` + // match (self, other) { + // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), + // _ => partial_cmp(self_discr, other_discr) + // } + // ``` + // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 - if !discr_then_data - && let ExprKind::Match(_, arms, _) = &mut expr1.kind - && let Some(last) = arms.last_mut() - && let PatKind::Wild = last.pat.kind - { - last.body = Some(expr2); - expr1 + if !discr_then_data + && let ast::ExprKind::Match(_, arms, _) = &mut expr1.kind + && let Some(last) = arms.last_mut() + && let ast::PatKind::Wild = last.pat.kind + { + last.body = Some(expr2); + expr1 + } else { + let eq_pat = cx.pat_path(span, equal_path.clone()); + let eq_arm = cx.arm( + span, + if is_partial_ord { cx.pat_some(span, eq_pat) } else { eq_pat }, + expr1, + ); + let cmp_ident = Ident::new(sym::cmp, span); + let neq_arm = + cx.arm(span, cx.pat_ident(span, cmp_ident), cx.expr_ident(span, cmp_ident)); + cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) + } + }; + + match substructure { + EnumMatching(.., all_fields) | Struct(_, all_fields) => { + let op = |old, field: FieldInfo| { + // The basic case: a field expression for one or more selflike args. E.g. + // for `Ord::cmp` this is something like `Ord::cmp(&self.x, &other.x)`. + let other_expr = + field.other_selflike_expr.expect("not exactly 2 arguments in `derive`"); + let args = thin_vec![field.self_expr, other_expr]; + let new = cx.expr_call_global(field.span, method_path.clone(), args); + match old { + Some(old) => Some(combine(field.span, old, new)), + None => Some(new), + } + }; + + all_fields.into_iter().rfold(None, op).unwrap_or_else(|| { + // The fallback case for a struct or enum variant with no fields. + let mut expr = cx.expr_path(equal_path); + if is_partial_ord { + expr = cx.expr_some(span, expr) + }; + expr + }) + } + EnumDiscr(match_expr) => { + let self_expr = cx.expr_addr_of(span, call_discriminant_value(cx, span, kw::SelfLower)); + let other_expr = cx.expr_addr_of(span, call_discriminant_value(cx, span, sym::other)); + let args = thin_vec![self_expr, other_expr]; + let discr_check_expr = cx.expr_call_global(span, method_path, args); + if let Some(match_expr) = match_expr { + combine(span, match_expr, discr_check_expr) } else { - let eq_arm = - cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1); - let neq_arm = - cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); - cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) + discr_check_expr } - }, - || cx.expr_some(span, cx.expr_path(equal_path.clone())), - ); - BlockOrExpr::new_expr(expr) + } + _ => cx.dcx().span_bug(span, "unexpected substructure in `derive`"), + } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 0e9d9ec5e8b7e..9a93d82a4fe4c 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -125,6 +125,17 @@ impl<'a> ExtCtxt<'a> { self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) } + pub fn ty_unit(&self, span: Span) -> Box { + self.ty(span, ast::TyKind::Tup(ThinVec::new())) + } + + pub fn ty_self(&self, span: Span) -> Box { + self.ty_path(self.path_ident(span, Ident::new(kw::SelfUpper, span))) + } + pub fn ty_self_ref(&self, span: Span) -> Box { + self.ty_ref(span, self.ty_self(span), None, ast::Mutability::Not) + } + pub fn typaram( &self, span: Span, @@ -310,6 +321,9 @@ impl<'a> ExtCtxt<'a> { pub fn expr_self(&self, span: Span) -> Box { self.expr_ident(span, Ident::new(kw::SelfLower, span)) } + pub fn expr_ident_sym(&self, span: Span, sym: Symbol) -> Box { + self.expr_ident(span, Ident::new(sym, span)) + } pub fn expr_macro_call(&self, span: Span, call: Box) -> Box { self.expr(span, ast::ExprKind::MacCall(call)) diff --git a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir index b1bbceae330c7..f7faefcc1bf7b 100644 --- a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir @@ -7,11 +7,7 @@ fn direct(_1: Option) -> bool { let mut _2: isize; scope 2 { scope 3 (inlined ::eq) { - let _3: i8; - scope 4 { - scope 5 { - } - } + let mut _3: i8; } } } @@ -30,7 +26,7 @@ fn direct(_1: Option) -> bool { bb2: { StorageLive(_3); _3 = discriminant(((_1 as Some).0: std::cmp::Ordering)); - _0 = Eq(copy _3, const 0_i8); + _0 = Eq(move _3, const 0_i8); StorageDead(_3); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir index 86ef69b9a4cd5..2f0233e353c2f 100644 --- a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir @@ -9,11 +9,7 @@ fn with_let(_1: Option) -> bool { let mut _2: isize; scope 3 { scope 4 (inlined ::eq) { - let _3: i8; - scope 5 { - scope 6 { - } - } + let mut _3: i8; } } } @@ -33,7 +29,7 @@ fn with_let(_1: Option) -> bool { bb2: { StorageLive(_3); _3 = discriminant(((_1 as Some).0: std::cmp::Ordering)); - _0 = Eq(copy _3, const 0_i8); + _0 = Eq(move _3, const 0_i8); StorageDead(_3); goto -> bb3; } diff --git a/tests/ui/associated-types/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs index 35c371235e640..227599204cc1f 100644 --- a/tests/ui/associated-types/issue-38821.rs +++ b/tests/ui/associated-types/issue-38821.rs @@ -32,8 +32,6 @@ pub trait Column: Expression {} //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied pub enum ColumnInsertValue where //~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied @@ -44,6 +42,8 @@ pub enum ColumnInsertValue where //~^ ERROR the trait bound `::SqlType: IntoNullable` is not satisfied { Expression(Col, Expr), + //~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied + //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied Default(Col), } diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 050054ad704bc..ad59184366ae1 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:1 + --> $DIR/issue-38821.rs:35:1 | LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -17,7 +17,7 @@ LL | Expr: Expression::Nullable>, ::SqlType: IntoNullable` is not satisfied - --> $DIR/issue-38821.rs:43:22 + --> $DIR/issue-38821.rs:41:22 | LL | Expr: Expression::Nullable>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -82,7 +82,7 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -98,7 +98,7 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Debug` - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -132,7 +132,7 @@ LL | Expr: Expression::Nullable>, ::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ---- in this derive macro expansion @@ -148,7 +148,7 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Copy` - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ---- in this derive macro expansion @@ -211,7 +211,7 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -227,7 +227,7 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Clone` - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -303,10 +303,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:44:5 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | Expression(Col, Expr), + | ^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -315,13 +318,15 @@ LL | impl IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:44:5 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | Expression(Col, Expr), + | ^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -330,7 +335,6 @@ LL | impl IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 18 previous errors diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index ddd1158132c7d..05412aca82360 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -1018,7 +1018,7 @@ impl ::core::clone::Clone for Enum1 { #[inline] fn clone(&self) -> Self { match self { - Enum1::Single { x: __self_0 } => + Self::Single { x: __self_0 } => Self::Single { x: ::core::clone::Clone::clone(__self_0) }, } } @@ -1028,7 +1028,7 @@ impl ::core::fmt::Debug for Enum1 { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - Enum1::Single { x: __self_0 } => + Self::Single { x: __self_0 } => ::core::fmt::Formatter::debug_struct_field1_finish(f, "Single", "x", &__self_0), } @@ -1039,7 +1039,7 @@ impl ::core::hash::Hash for Enum1 { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { match self { - Enum1::Single { x: __self_0 } => + Self::Single { x: __self_0 } => ::core::hash::Hash::hash(__self_0, state), } } @@ -1051,7 +1051,7 @@ impl ::core::cmp::PartialEq for Enum1 { #[inline] fn eq(&self, other: &Self) -> bool { match (self, other) { - (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + (Self::Single { x: __self_0 }, Self::Single { x: __arg1_0 }) => __self_0 == __arg1_0, } } @@ -1078,7 +1078,7 @@ impl ::core::cmp::Ord for Enum1 { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match (self, other) { - (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + (Self::Single { x: __self_0 }, Self::Single { x: __arg1_0 }) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), } } @@ -1176,8 +1176,8 @@ impl ::core::default::Default for Fieldless { impl ::core::hash::Hash for Fieldless { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state) + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state) } } #[automatically_derived] @@ -1186,9 +1186,8 @@ impl ::core::marker::StructuralPartialEq for Fieldless { } impl ::core::cmp::PartialEq for Fieldless { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) } } #[automatically_derived] @@ -1205,9 +1204,8 @@ impl ::core::cmp::PartialOrd for Fieldless { impl ::core::cmp::Ord for Fieldless { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)) } } @@ -1243,12 +1241,12 @@ impl ::core::fmt::Debug for Mixed { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), - Mixed::Q => ::core::fmt::Formatter::write_str(f, "Q"), - Mixed::R(__self_0) => + Self::P => ::core::fmt::Formatter::write_str(f, "P"), + Self::Q => ::core::fmt::Formatter::write_str(f, "Q"), + Self::R(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "R", &__self_0), - Mixed::S { d1: __self_0, d2: __self_1 } => + Self::S { d1: __self_0, d2: __self_1 } => ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", "d1", __self_0, "d2", &__self_1), } @@ -1263,11 +1261,11 @@ impl ::core::default::Default for Mixed { impl ::core::hash::Hash for Mixed { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state); + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state); match self { - Mixed::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), - Mixed::S { d1: __self_0, d2: __self_1 } => { + Self::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::S { d1: __self_0, d2: __self_1 } => { ::core::hash::Hash::hash(__self_0, state); ::core::hash::Hash::hash(__self_1, state) } @@ -1281,13 +1279,12 @@ impl ::core::marker::StructuralPartialEq for Mixed { } impl ::core::cmp::PartialEq for Mixed { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { - (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + (Self::R(__self_0), Self::R(__arg1_0)) => __self_0 == __arg1_0, - (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + (Self::S { d1: __self_0, d2: __self_1 }, Self::S { d1: __arg1_0, d2: __arg1_1 }) => __self_0 == __arg1_0 && __self_1 == __arg1_1, _ => true, @@ -1317,23 +1314,19 @@ impl ::core::cmp::PartialOrd for Mixed { impl ::core::cmp::Ord for Mixed { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { - ::core::cmp::Ordering::Equal => - match (self, other) { - (Mixed::R(__self_0), Mixed::R(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { - d1: __arg1_0, d2: __arg1_1 }) => - match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { - ::core::cmp::Ordering::Equal => - ::core::cmp::Ord::cmp(__self_1, __arg1_1), - cmp => cmp, - }, - _ => ::core::cmp::Ordering::Equal, + match (self, other) { + (Self::R(__self_0), Self::R(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Self::S { d1: __self_0, d2: __self_1 }, Self::S { + d1: __arg1_0, d2: __arg1_1 }) => + match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(__self_1, __arg1_1), + cmp => cmp, }, - cmp => cmp, + _ => + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1356,16 +1349,15 @@ impl ::core::marker::StructuralPartialEq for ReorderEnum { } impl ::core::cmp::PartialEq for ReorderEnum { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { - (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) => + (Self::A(__self_0), Self::A(__arg1_0)) => __self_0 == __arg1_0, - (ReorderEnum::C(__self_0), ReorderEnum::C(__arg1_0)) => + (Self::C(__self_0), Self::C(__arg1_0)) => __self_0 == __arg1_0, - (ReorderEnum::G(__self_0, __self_1, __self_2), - ReorderEnum::G(__arg1_0, __arg1_1, __arg1_2)) => + (Self::G(__self_0, __self_1, __self_2), + Self::G(__arg1_0, __arg1_1, __arg1_2)) => __self_1 == __arg1_1 && __self_0 == __arg1_0 && __self_2 == __arg1_2, _ => true, @@ -1377,18 +1369,16 @@ impl ::core::cmp::PartialOrd for ReorderEnum { #[inline] fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::PartialOrd::partial_cmp(&__self_discr, - &__arg1_discr) { + match ::core::cmp::PartialOrd::partial_cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => match (self, other) { - (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) => + (Self::A(__self_0), Self::A(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (ReorderEnum::C(__self_0), ReorderEnum::C(__arg1_0)) => + (Self::C(__self_0), Self::C(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (ReorderEnum::G(__self_0, __self_1, __self_2), - ReorderEnum::G(__arg1_0, __arg1_1, __arg1_2)) => + (Self::G(__self_0, __self_1, __self_2), + Self::G(__arg1_0, __arg1_1, __arg1_2)) => match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) @@ -1417,11 +1407,11 @@ impl ::core::clone::Clone for Fielded { #[inline] fn clone(&self) -> Self { match self { - Fielded::X(__self_0) => + Self::X(__self_0) => Self::X(::core::clone::Clone::clone(__self_0)), - Fielded::Y(__self_0) => + Self::Y(__self_0) => Self::Y(::core::clone::Clone::clone(__self_0)), - Fielded::Z(__self_0) => + Self::Z(__self_0) => Self::Z(::core::clone::Clone::clone(__self_0)), } } @@ -1431,13 +1421,13 @@ impl ::core::fmt::Debug for Fielded { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - Fielded::X(__self_0) => + Self::X(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "X", &__self_0), - Fielded::Y(__self_0) => + Self::Y(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Y", &__self_0), - Fielded::Z(__self_0) => + Self::Z(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Z", &__self_0), } @@ -1447,12 +1437,12 @@ impl ::core::fmt::Debug for Fielded { impl ::core::hash::Hash for Fielded { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state); + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state); match self { - Fielded::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), - Fielded::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), - Fielded::Z(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::Z(__self_0) => ::core::hash::Hash::hash(__self_0, state), } } } @@ -1462,15 +1452,14 @@ impl ::core::marker::StructuralPartialEq for Fielded { } impl ::core::cmp::PartialEq for Fielded { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { - (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + (Self::X(__self_0), Self::X(__arg1_0)) => __self_0 == __arg1_0, - (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + (Self::Y(__self_0), Self::Y(__arg1_0)) => __self_0 == __arg1_0, - (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + (Self::Z(__self_0), Self::Z(__arg1_0)) => __self_0 == __arg1_0, _ => unsafe { ::core::intrinsics::unreachable() } } @@ -1499,20 +1488,16 @@ impl ::core::cmp::PartialOrd for Fielded { impl ::core::cmp::Ord for Fielded { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { - ::core::cmp::Ordering::Equal => - match (self, other) { - (Fielded::X(__self_0), Fielded::X(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - _ => unsafe { ::core::intrinsics::unreachable() } - }, - cmp => cmp, + match (self, other) { + (Self::X(__self_0), Self::X(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Self::Y(__self_0), Self::Y(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Self::Z(__self_0), Self::Z(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + _ => + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1525,9 +1510,9 @@ impl ::core::clone::Clone #[inline] fn clone(&self) -> Self { match self { - EnumGeneric::One(__self_0) => + Self::One(__self_0) => Self::One(::core::clone::Clone::clone(__self_0)), - EnumGeneric::Two(__self_0) => + Self::Two(__self_0) => Self::Two(::core::clone::Clone::clone(__self_0)), } } @@ -1542,10 +1527,10 @@ impl ::core::fmt::Debug for #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - EnumGeneric::One(__self_0) => + Self::One(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "One", &__self_0), - EnumGeneric::Two(__self_0) => + Self::Two(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Two", &__self_0), } @@ -1556,13 +1541,11 @@ impl ::core::hash::Hash for EnumGeneric { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state); + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state); match self { - EnumGeneric::One(__self_0) => - ::core::hash::Hash::hash(__self_0, state), - EnumGeneric::Two(__self_0) => - ::core::hash::Hash::hash(__self_0, state), + Self::One(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::Two(__self_0) => ::core::hash::Hash::hash(__self_0, state), } } } @@ -1575,13 +1558,12 @@ impl ::core::cmp::PartialEq for EnumGeneric { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { - (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => + (Self::One(__self_0), Self::One(__arg1_0)) => __self_0 == __arg1_0, - (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => + (Self::Two(__self_0), Self::Two(__arg1_0)) => __self_0 == __arg1_0, _ => unsafe { ::core::intrinsics::unreachable() } } @@ -1604,16 +1586,14 @@ impl #[inline] fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); match (self, other) { - (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => + (Self::One(__self_0), Self::One(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => + (Self::Two(__self_0), Self::Two(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), _ => - ::core::cmp::PartialOrd::partial_cmp(&__self_discr, - &__arg1_discr), + ::core::cmp::PartialOrd::partial_cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1622,18 +1602,14 @@ impl ::core::cmp::Ord for EnumGeneric { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { - ::core::cmp::Ordering::Equal => - match (self, other) { - (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => - ::core::cmp::Ord::cmp(__self_0, __arg1_0), - _ => unsafe { ::core::intrinsics::unreachable() } - }, - cmp => cmp, + match (self, other) { + (Self::One(__self_0), Self::One(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Self::Two(__self_0), Self::Two(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + _ => + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1652,8 +1628,8 @@ impl ::core::cmp::PartialEq for NonCopyEnum { #[inline] fn eq(&self, other: &Self) -> bool { match (self, other) { - (NonCopyEnum::NonCopyField(__self_0), - NonCopyEnum::NonCopyField(__arg1_0)) => __self_0 == __arg1_0, + (Self::NonCopyField(__self_0), Self::NonCopyField(__arg1_0)) => + __self_0 == __arg1_0, } } } diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index 95567e20db3bf..efc3785878c39 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -3,7 +3,7 @@ macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- macro-stats #[derive(Clone)] 8 67 8.4 1_909 238.6 -macro-stats #[derive(Hash)] 2 17 8.5 565 282.5 +macro-stats #[derive(Hash)] 2 17 8.5 536 268.0 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 505 505.0 macro-stats #[derive(Default)] 2 16 8.0 409 204.5