Skip to content

Commit 7d96352

Browse files
authored
Merge pull request #2857 from dtolnay/collide
Revert the colliding aliases hard error (PRs #2562 & #2853)
2 parents b1353a9 + 111ecc5 commit 7d96352

File tree

5 files changed

+108
-222
lines changed

5 files changed

+108
-222
lines changed

serde_derive/src/internals/check.rs

+1-135
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use crate::internals::ast::{Container, Data, Field, Style, Variant};
1+
use crate::internals::ast::{Container, Data, Field, Style};
22
use crate::internals::attr::{Default, Identifier, TagType};
33
use crate::internals::{ungroup, Ctxt, Derive};
4-
use std::collections::btree_map::Entry;
5-
use std::collections::{BTreeMap, BTreeSet};
64
use syn::{Member, Type};
75

86
// Cross-cutting checks that require looking at more than a single attrs object.
@@ -18,7 +16,6 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
1816
check_adjacent_tag_conflict(cx, cont);
1917
check_transparent(cx, cont, derive);
2018
check_from_and_try_from(cx, cont);
21-
check_name_conflicts(cx, cont, derive);
2219
}
2320

2421
// If some field of a tuple struct is marked #[serde(default)] then all fields
@@ -478,134 +475,3 @@ fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) {
478475
);
479476
}
480477
}
481-
482-
// Checks that aliases does not repeated
483-
fn check_name_conflicts(cx: &Ctxt, cont: &Container, derive: Derive) {
484-
if let Derive::Deserialize = derive {
485-
match &cont.data {
486-
Data::Enum(variants) => check_variant_name_conflicts(cx, variants),
487-
Data::Struct(Style::Struct, fields) => check_field_name_conflicts(cx, fields),
488-
_ => {}
489-
}
490-
}
491-
}
492-
493-
// All renames already applied
494-
fn check_variant_name_conflicts(cx: &Ctxt, variants: &[Variant]) {
495-
let names: BTreeSet<_> = variants
496-
.iter()
497-
.filter_map(|variant| {
498-
if variant.attrs.skip_deserializing() {
499-
None
500-
} else {
501-
Some(variant.attrs.name().deserialize_name().to_owned())
502-
}
503-
})
504-
.collect();
505-
let mut alias_owners = BTreeMap::new();
506-
507-
for variant in variants {
508-
let name = variant.attrs.name().deserialize_name();
509-
510-
for alias in variant.attrs.aliases().intersection(&names) {
511-
// Aliases contains variant names, so filter them out
512-
if alias == name {
513-
continue;
514-
}
515-
516-
// TODO: report other variant location when this become possible
517-
cx.error_spanned_by(
518-
variant.original,
519-
format!(
520-
"alias `{}` conflicts with deserialization name of other variant",
521-
alias
522-
),
523-
);
524-
}
525-
526-
for alias in variant.attrs.aliases() {
527-
// Aliases contains variant names, so filter them out
528-
if alias == name {
529-
continue;
530-
}
531-
532-
match alias_owners.entry(alias) {
533-
Entry::Vacant(e) => {
534-
e.insert(variant);
535-
}
536-
Entry::Occupied(e) => {
537-
// TODO: report other variant location when this become possible
538-
cx.error_spanned_by(
539-
variant.original,
540-
format!(
541-
"alias `{}` already used by variant {}",
542-
alias,
543-
e.get().original.ident
544-
),
545-
);
546-
}
547-
}
548-
}
549-
550-
check_field_name_conflicts(cx, &variant.fields);
551-
}
552-
}
553-
554-
// All renames already applied
555-
fn check_field_name_conflicts(cx: &Ctxt, fields: &[Field]) {
556-
let names: BTreeSet<_> = fields
557-
.iter()
558-
.filter_map(|field| {
559-
if field.attrs.skip_deserializing() {
560-
None
561-
} else {
562-
Some(field.attrs.name().deserialize_name().to_owned())
563-
}
564-
})
565-
.collect();
566-
let mut alias_owners = BTreeMap::new();
567-
568-
for field in fields {
569-
let name = field.attrs.name().deserialize_name();
570-
571-
for alias in field.attrs.aliases().intersection(&names) {
572-
// Aliases contains field names, so filter them out
573-
if alias == name {
574-
continue;
575-
}
576-
577-
// TODO: report other field location when this become possible
578-
cx.error_spanned_by(
579-
field.original,
580-
format!(
581-
"alias `{}` conflicts with deserialization name of other field",
582-
alias
583-
),
584-
);
585-
}
586-
587-
for alias in field.attrs.aliases() {
588-
// Aliases contains field names, so filter them out
589-
if alias == name {
590-
continue;
591-
}
592-
593-
match alias_owners.entry(alias) {
594-
Entry::Vacant(e) => {
595-
e.insert(field);
596-
}
597-
Entry::Occupied(e) => {
598-
// TODO: report other field location when this become possible
599-
cx.error_spanned_by(
600-
field.original,
601-
format!(
602-
"alias `{}` already used by field {}",
603-
alias,
604-
e.get().original.ident.as_ref().unwrap()
605-
),
606-
);
607-
}
608-
}
609-
}
610-
}
611-
}

test_suite/tests/ui/conflict/alias-enum.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,6 @@ enum E3 {
7676
b,
7777
}
7878

79-
fn main() {}
79+
fn main() {
80+
@//fail
81+
}
+64-56
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,79 @@
1-
error: alias `b` conflicts with deserialization name of other field
2-
--> tests/ui/conflict/alias-enum.rs:8:9
1+
error: expected expression, found `@`
2+
--> tests/ui/conflict/alias-enum.rs:80:5
33
|
4-
8 | / /// Expected error on "alias b", because this is a name of other field
5-
9 | | /// Error on "alias a" is not expected because this is a name of this field
6-
10 | | /// Error on "alias c" is not expected because field `c` is skipped
7-
11 | | #[serde(alias = "a", alias = "b", alias = "c")]
8-
12 | | a: (),
9-
| |_____________^
4+
80 | @//fail
5+
| ^ expected expression
106

11-
error: alias `c` already used by field a
12-
--> tests/ui/conflict/alias-enum.rs:14:9
7+
warning: unreachable pattern
8+
--> tests/ui/conflict/alias-enum.rs:16:9
139
|
14-
14 | / /// Expected error on "alias c", because it is already used as alias of `a`
15-
15 | | #[serde(alias = "c")]
16-
16 | | b: (),
17-
| |_____________^
10+
11 | #[serde(alias = "a", alias = "b", alias = "c")]
11+
| --- matches all the relevant values
12+
...
13+
16 | b: (),
14+
| ^ no value can reach this
15+
|
16+
= note: `#[warn(unreachable_patterns)]` on by default
17+
18+
warning: unreachable pattern
19+
--> tests/ui/conflict/alias-enum.rs:15:25
20+
|
21+
11 | #[serde(alias = "a", alias = "b", alias = "c")]
22+
| --- matches all the relevant values
23+
...
24+
15 | #[serde(alias = "c")]
25+
| ^^^ no value can reach this
1826

19-
error: alias `c` conflicts with deserialization name of other field
20-
--> tests/ui/conflict/alias-enum.rs:23:9
27+
warning: unreachable pattern
28+
--> tests/ui/conflict/alias-enum.rs:28:26
2129
|
22-
23 | / /// Expected error on "alias c", because this is a name of other field after
23-
24 | | /// applying rename rules
24-
25 | | #[serde(alias = "b", alias = "c")]
25-
26 | | a: (),
26-
| |_____________^
30+
25 | #[serde(alias = "b", alias = "c")]
31+
| --- matches all the relevant values
32+
...
33+
28 | #[serde(rename = "c")]
34+
| ^^^ no value can reach this
2735

28-
error: alias `B` conflicts with deserialization name of other field
29-
--> tests/ui/conflict/alias-enum.rs:34:9
36+
warning: unreachable pattern
37+
--> tests/ui/conflict/alias-enum.rs:38:9
3038
|
31-
34 | / /// Expected error on "alias B", because this is a name of field after
32-
35 | | /// applying rename rules
33-
36 | | #[serde(alias = "B", alias = "c")]
34-
37 | | a: (),
35-
| |_____________^
39+
36 | #[serde(alias = "B", alias = "c")]
40+
| --- matches all the relevant values
41+
37 | a: (),
42+
38 | b: (),
43+
| ^ no value can reach this
3644

37-
error: alias `b` conflicts with deserialization name of other variant
38-
--> tests/ui/conflict/alias-enum.rs:44:5
45+
warning: unreachable pattern
46+
--> tests/ui/conflict/alias-enum.rs:52:5
3947
|
40-
44 | / /// Expected error on "alias b", because this is a name of other variant
41-
45 | | /// Error on "alias a" is not expected because this is a name of this variant
42-
46 | | /// Error on "alias c" is not expected because variant `c` is skipped
43-
47 | | #[serde(alias = "a", alias = "b", alias = "c")]
44-
48 | | a,
45-
| |_____^
48+
47 | #[serde(alias = "a", alias = "b", alias = "c")]
49+
| --- matches all the relevant values
50+
...
51+
52 | b,
52+
| ^ no value can reach this
4653

47-
error: alias `c` already used by variant a
48-
--> tests/ui/conflict/alias-enum.rs:50:5
54+
warning: unreachable pattern
55+
--> tests/ui/conflict/alias-enum.rs:51:21
4956
|
50-
50 | / /// Expected error on "alias c", because it is already used as alias of `a`
51-
51 | | #[serde(alias = "c")]
52-
52 | | b,
53-
| |_____^
57+
47 | #[serde(alias = "a", alias = "b", alias = "c")]
58+
| --- matches all the relevant values
59+
...
60+
51 | #[serde(alias = "c")]
61+
| ^^^ no value can reach this
5462

55-
error: alias `c` conflicts with deserialization name of other variant
56-
--> tests/ui/conflict/alias-enum.rs:60:5
63+
warning: unreachable pattern
64+
--> tests/ui/conflict/alias-enum.rs:65:22
5765
|
58-
60 | / /// Expected error on "alias c", because this is a name of other variant after
59-
61 | | /// applying rename rules
60-
62 | | #[serde(alias = "b", alias = "c")]
61-
63 | | a,
62-
| |_____^
66+
62 | #[serde(alias = "b", alias = "c")]
67+
| --- matches all the relevant values
68+
...
69+
65 | #[serde(rename = "c")]
70+
| ^^^ no value can reach this
6371

64-
error: alias `B` conflicts with deserialization name of other variant
65-
--> tests/ui/conflict/alias-enum.rs:72:5
72+
warning: unreachable pattern
73+
--> tests/ui/conflict/alias-enum.rs:76:5
6674
|
67-
72 | / /// Expected error on "alias B", because this is a name of variant after
68-
73 | | /// applying rename rules
69-
74 | | #[serde(alias = "B", alias = "c")]
70-
75 | | a,
71-
| |_____^
75+
74 | #[serde(alias = "B", alias = "c")]
76+
| --- matches all the relevant values
77+
75 | a,
78+
76 | b,
79+
| ^ no value can reach this

test_suite/tests/ui/conflict/alias.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ struct S3 {
3737
b: (),
3838
}
3939

40-
fn main() {}
40+
fn main() {
41+
@//fail
42+
}
+37-29
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
1-
error: alias `b` conflicts with deserialization name of other field
2-
--> tests/ui/conflict/alias.rs:5:5
3-
|
4-
5 | / /// Expected error on "alias b", because this is a name of other field
5-
6 | | /// Error on "alias a" is not expected because this is a name of this field
6-
7 | | /// Error on "alias c" is not expected because field `c` is skipped
7-
8 | | #[serde(alias = "a", alias = "b", alias = "c")]
8-
9 | | a: (),
9-
| |_________^
1+
error: expected expression, found `@`
2+
--> tests/ui/conflict/alias.rs:41:5
3+
|
4+
41 | @//fail
5+
| ^ expected expression
6+
7+
warning: unreachable pattern
8+
--> tests/ui/conflict/alias.rs:13:5
9+
|
10+
8 | #[serde(alias = "a", alias = "b", alias = "c")]
11+
| --- matches all the relevant values
12+
...
13+
13 | b: (),
14+
| ^ no value can reach this
15+
|
16+
= note: `#[warn(unreachable_patterns)]` on by default
1017

11-
error: alias `c` already used by field a
12-
--> tests/ui/conflict/alias.rs:11:5
18+
warning: unreachable pattern
19+
--> tests/ui/conflict/alias.rs:12:21
1320
|
14-
11 | / /// Expected error on "alias c", because it is already used as alias of `a`
15-
12 | | #[serde(alias = "c")]
16-
13 | | b: (),
17-
| |_________^
21+
8 | #[serde(alias = "a", alias = "b", alias = "c")]
22+
| --- matches all the relevant values
23+
...
24+
12 | #[serde(alias = "c")]
25+
| ^^^ no value can reach this
1826

19-
error: alias `c` conflicts with deserialization name of other field
20-
--> tests/ui/conflict/alias.rs:21:5
27+
warning: unreachable pattern
28+
--> tests/ui/conflict/alias.rs:26:22
2129
|
22-
21 | / /// Expected error on "alias c", because this is a name of other field after
23-
22 | | /// applying rename rules
24-
23 | | #[serde(alias = "b", alias = "c")]
25-
24 | | a: (),
26-
| |_________^
30+
23 | #[serde(alias = "b", alias = "c")]
31+
| --- matches all the relevant values
32+
...
33+
26 | #[serde(rename = "c")]
34+
| ^^^ no value can reach this
2735

28-
error: alias `B` conflicts with deserialization name of other field
29-
--> tests/ui/conflict/alias.rs:33:5
36+
warning: unreachable pattern
37+
--> tests/ui/conflict/alias.rs:37:5
3038
|
31-
33 | / /// Expected error on "alias B", because this is a name of field after
32-
34 | | /// applying rename rules
33-
35 | | #[serde(alias = "B", alias = "c")]
34-
36 | | a: (),
35-
| |_________^
39+
35 | #[serde(alias = "B", alias = "c")]
40+
| --- matches all the relevant values
41+
36 | a: (),
42+
37 | b: (),
43+
| ^ no value can reach this

0 commit comments

Comments
 (0)