deriv(Hash) for single-variant enum should not hash discriminant
Fixes #39137
This commit is contained in:
parent
b40be00a0c
commit
f11e40a811
6 changed files with 20 additions and 10 deletions
|
@ -167,7 +167,7 @@ fn cs_clone(name: &str,
|
||||||
all_fields = af;
|
all_fields = af;
|
||||||
vdata = vdata_;
|
vdata = vdata_;
|
||||||
}
|
}
|
||||||
EnumMatching(_, variant, ref af) => {
|
EnumMatching(.., variant, ref af) => {
|
||||||
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
|
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
|
||||||
all_fields = af;
|
all_fields = af;
|
||||||
vdata = &variant.node.data;
|
vdata = &variant.node.data;
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
|
||||||
// based on the "shape".
|
// based on the "shape".
|
||||||
let (ident, is_struct) = match *substr.fields {
|
let (ident, is_struct) = match *substr.fields {
|
||||||
Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
|
Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
|
||||||
EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
|
EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()),
|
||||||
EnumNonMatchingCollapsed(..) |
|
EnumNonMatchingCollapsed(..) |
|
||||||
StaticStruct(..) |
|
StaticStruct(..) |
|
||||||
StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
|
StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
|
||||||
|
|
|
@ -233,7 +233,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
|
||||||
blk])
|
blk])
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumMatching(idx, variant, ref fields) => {
|
EnumMatching(idx, _, variant, ref fields) => {
|
||||||
// We're not generating an AST that the borrow checker is expecting,
|
// We're not generating an AST that the borrow checker is expecting,
|
||||||
// so we need to generate a unique local variable to take the
|
// so we need to generate a unique local variable to take the
|
||||||
// mutable loan out on, otherwise we get conflicts which don't
|
// mutable loan out on, otherwise we get conflicts which don't
|
||||||
|
|
|
@ -305,10 +305,10 @@ pub enum StaticFields {
|
||||||
/// A summary of the possible sets of fields.
|
/// A summary of the possible sets of fields.
|
||||||
pub enum SubstructureFields<'a> {
|
pub enum SubstructureFields<'a> {
|
||||||
Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
|
Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
|
||||||
/// Matching variants of the enum: variant index, ast::Variant,
|
/// Matching variants of the enum: variant index, variant count, ast::Variant,
|
||||||
/// fields: the field name is only non-`None` in the case of a struct
|
/// fields: the field name is only non-`None` in the case of a struct
|
||||||
/// variant.
|
/// variant.
|
||||||
EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
|
EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
|
||||||
|
|
||||||
/// Non-matching variants of the enum, but with all state hidden from
|
/// Non-matching variants of the enum, but with all state hidden from
|
||||||
/// the consequent code. The first component holds `Ident`s for all of
|
/// the consequent code. The first component holds `Ident`s for all of
|
||||||
|
@ -1250,7 +1250,7 @@ impl<'a> MethodDef<'a> {
|
||||||
// expressions for referencing every field of every
|
// expressions for referencing every field of every
|
||||||
// Self arg, assuming all are instances of VariantK.
|
// Self arg, assuming all are instances of VariantK.
|
||||||
// Build up code associated with such a case.
|
// Build up code associated with such a case.
|
||||||
let substructure = EnumMatching(index, variant, field_tuples);
|
let substructure = EnumMatching(index, variants.len(), variant, field_tuples);
|
||||||
let arm_expr = self.call_substructure_method(cx,
|
let arm_expr = self.call_substructure_method(cx,
|
||||||
trait_,
|
trait_,
|
||||||
type_ident,
|
type_ident,
|
||||||
|
@ -1267,12 +1267,13 @@ impl<'a> MethodDef<'a> {
|
||||||
// We need a default case that handles the fieldless variants.
|
// We need a default case that handles the fieldless variants.
|
||||||
// The index and actual variant aren't meaningful in this case,
|
// The index and actual variant aren't meaningful in this case,
|
||||||
// so just use whatever
|
// so just use whatever
|
||||||
|
let substructure = EnumMatching(0, variants.len(), v, Vec::new());
|
||||||
Some(self.call_substructure_method(cx,
|
Some(self.call_substructure_method(cx,
|
||||||
trait_,
|
trait_,
|
||||||
type_ident,
|
type_ident,
|
||||||
&self_args[..],
|
&self_args[..],
|
||||||
nonself_args,
|
nonself_args,
|
||||||
&EnumMatching(0, v, Vec::new())))
|
&substructure))
|
||||||
}
|
}
|
||||||
_ if variants.len() > 1 && self_args.len() > 1 => {
|
_ if variants.len() > 1 && self_args.len() > 1 => {
|
||||||
// Since we know that all the arguments will match if we reach
|
// Since we know that all the arguments will match if we reach
|
||||||
|
|
|
@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
|
|
||||||
let fields = match *substr.fields {
|
let fields = match *substr.fields {
|
||||||
Struct(_, ref fs) => fs,
|
Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
|
||||||
EnumMatching(.., ref fs) => {
|
EnumMatching(.., ref fs) => {
|
||||||
let variant_value = deriving::call_intrinsic(cx,
|
let variant_value = deriving::call_intrinsic(cx,
|
||||||
trait_span,
|
trait_span,
|
||||||
|
|
|
@ -45,8 +45,8 @@ impl<'a> Hasher for FakeHasher<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fake_hash(v: &mut Vec<u8>, e: E) {
|
fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) {
|
||||||
e.hash(&mut FakeHasher(v));
|
a.hash(&mut FakeHasher(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -69,4 +69,13 @@ fn main() {
|
||||||
fake_hash(&mut va, E::A);
|
fake_hash(&mut va, E::A);
|
||||||
fake_hash(&mut vb, E::B);
|
fake_hash(&mut vb, E::B);
|
||||||
assert!(va != vb);
|
assert!(va != vb);
|
||||||
|
|
||||||
|
// issue #39137: single variant enum hash should not hash discriminant
|
||||||
|
#[derive(Hash)]
|
||||||
|
enum SingleVariantEnum {
|
||||||
|
A(u8),
|
||||||
|
}
|
||||||
|
let mut v = vec![];
|
||||||
|
fake_hash(&mut v, SingleVariantEnum::A(17));
|
||||||
|
assert_eq!(vec![17], v);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue