diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 77e0b6c55a8..7bd344467d0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -16,6 +16,7 @@ pub fn expand_deriving_copy( let trait_def = TraitDef { span, path: path_std!(marker::Copy), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c7f2d95e72f..fa8685f5f4e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -72,6 +72,7 @@ pub fn expand_deriving_clone( let trait_def = TraitDef { span, path: path_std!(clone::Clone), + skip_path_as_bound: false, additional_bounds: bounds, generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 5b556c5c9b9..eab67b0d354 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -25,6 +25,7 @@ pub fn expand_deriving_eq( let trait_def = TraitDef { span, path: path_std!(cmp::Eq), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 72625869558..7f117981a9a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -19,6 +19,7 @@ pub fn expand_deriving_ord( let trait_def = TraitDef { span, path: path_std!(cmp::Ord), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, 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 42ee65b570a..236cbccaf9f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -83,6 +83,7 @@ fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOr let trait_def = TraitDef { span, path: path_std!(cmp::PartialEq), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, 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 516892aeda9..4173403a1b8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -37,6 +37,7 @@ pub fn expand_deriving_partial_ord( let trait_def = TraitDef { span, path: path_std!(cmp::PartialOrd), + skip_path_as_bound: false, additional_bounds: vec![], generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 4af7fd81653..2cf614ed947 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -20,6 +20,7 @@ pub fn expand_deriving_debug( let trait_def = TraitDef { span, path: path_std!(fmt::Debug), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 7174dbbe7ea..d669f616802 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -23,6 +23,7 @@ pub fn expand_deriving_rustc_decodable( let trait_def = TraitDef { span, path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index a94c8a996e6..17df9fb279a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -24,6 +24,7 @@ pub fn expand_deriving_default( let trait_def = TraitDef { span, path: Path::new(vec![kw::Default, sym::Default]), + skip_path_as_bound: has_a_default_variant(item), additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, @@ -262,3 +263,22 @@ fn visit_variant(&mut self, v: &'a rustc_ast::Variant) { } } } + +fn has_a_default_variant(item: &Annotatable) -> bool { + struct HasDefaultAttrOnVariant { + found: bool, + } + + impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant { + fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) { + if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) { + self.found = true; + } + // no need to subrecurse. + } + } + + let mut visitor = HasDefaultAttrOnVariant { found: false }; + item.visit_with(&mut visitor); + visitor.found +} diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index b220e54238f..f83f58b97d3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -107,6 +107,7 @@ pub fn expand_deriving_rustc_encodable( let trait_def = TraitDef { span, path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index adffebd3fd2..cd53050c61e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -172,6 +172,7 @@ use rustc_span::Span; use std::cell::RefCell; use std::iter; +use std::ops::Not; use std::vec; use thin_vec::thin_vec; use ty::{Bounds, Path, Ref, Self_, Ty}; @@ -185,6 +186,9 @@ pub struct TraitDef<'a> { /// Path of the trait, including any type parameters pub path: Path, + /// Whether to skip adding the current trait as a bound to the type parameters of the type. + pub skip_path_as_bound: bool, + /// Additional bounds required of any type parameters of the type, /// other than the current trait pub additional_bounds: Vec, @@ -594,7 +598,7 @@ fn create_derived_impl( cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) }).chain( // require the current trait - iter::once(cx.trait_bound(trait_path.clone())) + self.skip_path_as_bound.not().then(|| cx.trait_bound(trait_path.clone())) ).chain( // also add in any bounds from the declaration param.bounds.iter().cloned() diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index f1f02e7ce77..6e9d5f08b94 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -22,6 +22,7 @@ pub fn expand_deriving_hash( let hash_trait_def = TraitDef { span, path, + skip_path_as_bound: false, additional_bounds: Vec::new(), generics: Bounds::empty(), supports_unions: false,