Skip to content

Commit 6729479

Browse files
committed
Allow access to struct variants of an enum through a type alias of the enum
1 parent 140ab5a commit 6729479

File tree

5 files changed

+24
-59
lines changed

5 files changed

+24
-59
lines changed

src/librustc_resolve/diagnostics.rs

-23
Original file line numberDiff line numberDiff line change
@@ -714,29 +714,6 @@ match Something::NotFoo {
714714
```
715715
"##,
716716

717-
E0422: r##"
718-
You are trying to use an identifier that is either undefined or not a
719-
struct. For instance:
720-
```
721-
fn main () {
722-
let x = Foo { x: 1, y: 2 };
723-
}
724-
```
725-
726-
In this case, `Foo` is undefined, so it inherently isn't anything, and
727-
definitely not a struct.
728-
729-
```
730-
fn main () {
731-
let foo = 1;
732-
let x = foo { x: 1, y: 2 };
733-
}
734-
```
735-
736-
In this case, `foo` is defined, but is not a struct, so Rust can't use
737-
it as one.
738-
"##,
739-
740717
E0423: r##"
741718
A `struct` variant name was used like a function name. Example of
742719
erroneous code:

src/librustc_resolve/lib.rs

+8-29
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,6 @@ pub enum ResolutionError<'a> {
170170
NotAnAssociatedConst(&'a str),
171171
/// error E0421: unresolved associated const
172172
UnresolvedAssociatedConst(&'a str),
173-
/// error E0422: does not name a struct
174-
DoesNotNameAStruct(&'a str),
175173
/// error E0423: is a struct variant name, but this expression uses it like a function name
176174
StructVariantUsedAsFunction(&'a str),
177175
/// error E0424: `self` is not available in a static method
@@ -412,13 +410,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
412410
"unresolved associated const `{}`",
413411
name)
414412
}
415-
ResolutionError::DoesNotNameAStruct(name) => {
416-
struct_span_err!(resolver.session,
417-
span,
418-
E0422,
419-
"`{}` does not name a structure",
420-
name)
421-
}
422413
ResolutionError::StructVariantUsedAsFunction(path_name) => {
423414
struct_span_err!(resolver.session,
424415
span,
@@ -2862,18 +2853,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28622853
}
28632854

28642855
PatStruct(ref path, _, _) => {
2865-
match self.resolve_path(pat_id, path, 0, TypeNS, false) {
2866-
Some(definition) => {
2856+
match self.resolve_possibly_assoc_item(pat_id, None, path, TypeNS, false) {
2857+
ResolveAttempt(Some(definition)) => {
28672858
self.record_def(pattern.id, definition);
28682859
}
2869-
result => {
2870-
debug!("(resolving pattern) didn't find struct def: {:?}", result);
2871-
resolve_error(
2872-
self,
2873-
path.span,
2874-
ResolutionError::DoesNotNameAStruct(
2875-
&*path_names_to_string(path, 0))
2876-
);
2860+
_ => {
2861+
self.resolve_path(pat_id, path, 0, TypeNS, false);
28772862
self.record_def(pattern.id, err_path_resolution());
28782863
}
28792864
}
@@ -3665,16 +3650,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
36653650
// Resolve the path to the structure it goes to. We don't
36663651
// check to ensure that the path is actually a structure; that
36673652
// is checked later during typeck.
3668-
match self.resolve_path(expr.id, path, 0, TypeNS, false) {
3669-
Some(definition) => self.record_def(expr.id, definition),
3670-
None => {
3671-
debug!("(resolving expression) didn't find struct def",);
3672-
3673-
resolve_error(self,
3674-
path.span,
3675-
ResolutionError::DoesNotNameAStruct(
3676-
&*path_names_to_string(path, 0))
3677-
);
3653+
match self.resolve_possibly_assoc_item(expr.id, None, path, TypeNS, false) {
3654+
ResolveAttempt(Some(definition)) => self.record_def(expr.id, definition),
3655+
_ => {
3656+
self.resolve_path(expr.id, path, 0, TypeNS, false);
36783657
self.record_def(expr.id, err_path_resolution());
36793658
}
36803659
}

src/librustc_typeck/check/_match.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,12 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
562562
let fcx = pcx.fcx;
563563
let tcx = pcx.fcx.ccx.tcx;
564564

565-
let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
565+
let path_res = *tcx.def_map.borrow().get(&pat.id).unwrap();
566+
let def = match resolve_ty_and_def_ufcs(fcx, path_res, None, path, pat.span, pat.id) {
567+
Some((_, _, def)) => def,
568+
None => Def::Err,
569+
};
570+
566571
let variant = match fcx.def_struct_variant(def, path.span) {
567572
Some((_, variant)) => variant,
568573
None => {

src/librustc_typeck/check/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -3166,11 +3166,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
31663166
let tcx = fcx.tcx();
31673167

31683168
// Find the relevant variant
3169-
let def = lookup_full_def(tcx, path.span, expr.id);
3170-
if def == Def::Err {
3171-
check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
3172-
return;
3173-
}
3169+
let path_res = *tcx.def_map.borrow().get(&expr.id).unwrap();
3170+
let def = match resolve_ty_and_def_ufcs(fcx, path_res, None, path, expr.span, expr.id) {
3171+
Some((_, _, def)) => def,
3172+
None => Def::Err,
3173+
};
31743174
let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
31753175
Some((adt, variant)) => (adt, variant),
31763176
None => {

src/test/run-pass/enum-alias-access-variant.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
enum Foo {
1414
Unit,
1515
Bar(i32),
16+
Baz { i: i32 },
1617
}
1718

1819
type Alias = Foo;
@@ -24,9 +25,12 @@ impl Default for Foo {
2425
}
2526

2627
fn main() {
27-
let t = Alias::Bar(0);
28+
let _t = Alias::Bar(0);
29+
let t = Alias::Baz { i: 0 };
30+
2831
match t {
2932
Alias::Unit => {}
3033
Alias::Bar(_i) => {}
34+
Alias::Baz { i: _i } => {}
3135
}
3236
}

0 commit comments

Comments
 (0)