From 140ab5ac87ae4ea00165e1e34547a3445f22b298 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 25 Jan 2016 03:43:40 +0000 Subject: [PATCH] Allow access to unit and tuple variants of an enum through a type alias of the enum --- src/librustc_typeck/check/_match.rs | 12 +++---- src/librustc_typeck/check/method/mod.rs | 9 ++++++ .../run-pass/enum-alias-access-variant.rs | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/enum-alias-access-variant.rs diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index c43349f88104d..27c0ecca73818 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -640,8 +640,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, }; // Items that were partially resolved before should have been resolved to - // associated constants (i.e. not methods). - if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) { + // variants or associated constants (i.e. not methods). + if let Def::Variant(..) = def { + } else if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) { fcx.write_error(pat.id); return; } @@ -675,10 +676,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } }; - // If we didn't have a fully resolved path to start with, we had an - // associated const, and we should quit now, since the rest of this - // function uses checks specific to structs and enums. - if path_res.depth != 0 { + // If we have an associated const, and we should quit now, since + // the rest of this function uses checks specific to structs and enums. + if let Def::AssociatedConst(..) = def { if is_tuple_struct_pat { report_bad_struct_kind(false); } else { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index fc2dd4475e3ff..5d55e236451f8 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -336,6 +336,15 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr_id: ast::NodeId) -> Result<(Def, LastPrivate), MethodError<'tcx>> { + // First check if method_name is a variant of self_ty + if let &ty::TyS { sty: ty::TyEnum(adt_def, _), .. } = self_ty { + for variant in adt_def.variants.iter() { + if variant.name == method_name { + return Ok((Def::Variant(adt_def.did, variant.did), LastMod(AllPublic))) + } + } + } + let mode = probe::Mode::Path; let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id)); let def_id = pick.item.def_id(); diff --git a/src/test/run-pass/enum-alias-access-variant.rs b/src/test/run-pass/enum-alias-access-variant.rs new file mode 100644 index 0000000000000..93f167dc4ddb2 --- /dev/null +++ b/src/test/run-pass/enum-alias-access-variant.rs @@ -0,0 +1,32 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks that unit and tuple enum variants can be accessed through a type alias of the enum + +enum Foo { + Unit, + Bar(i32), +} + +type Alias = Foo; + +impl Default for Foo { + fn default() -> Self { + Self::Unit + } +} + +fn main() { + let t = Alias::Bar(0); + match t { + Alias::Unit => {} + Alias::Bar(_i) => {} + } +}