| 
1 | 1 | use rustc_ast as ast;  | 
2 | 2 | use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};  | 
3 | 3 | use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};  | 
4 |  | -use rustc_ast::{PatKind, RangeEnd};  | 
 | 4 | +use rustc_ast::{PatKind, RangeEnd, VariantData};  | 
5 | 5 | use rustc_errors::struct_span_err;  | 
6 | 6 | use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};  | 
7 | 7 | use rustc_feature::{Features, GateIssue};  | 
8 |  | -use rustc_session::parse::feature_err_issue;  | 
 | 8 | +use rustc_session::parse::{feature_err, feature_err_issue};  | 
9 | 9 | use rustc_session::Session;  | 
10 | 10 | use rustc_span::source_map::Spanned;  | 
11 | 11 | use rustc_span::symbol::sym;  | 
@@ -218,6 +218,46 @@ impl<'a> PostExpansionVisitor<'a> {  | 
218 | 218 |         }  | 
219 | 219 |     }  | 
220 | 220 | 
 
  | 
 | 221 | +    fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {  | 
 | 222 | +        let has_fields = variants.iter().any(|variant| match variant.data {  | 
 | 223 | +            VariantData::Tuple(..) | VariantData::Struct(..) => true,  | 
 | 224 | +            VariantData::Unit(..) => false,  | 
 | 225 | +        });  | 
 | 226 | + | 
 | 227 | +        let discriminant_spans = variants  | 
 | 228 | +            .iter()  | 
 | 229 | +            .filter(|variant| match variant.data {  | 
 | 230 | +                VariantData::Tuple(..) | VariantData::Struct(..) => false,  | 
 | 231 | +                VariantData::Unit(..) => true,  | 
 | 232 | +            })  | 
 | 233 | +            .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))  | 
 | 234 | +            .collect::<Vec<_>>();  | 
 | 235 | + | 
 | 236 | +        if !discriminant_spans.is_empty() && has_fields {  | 
 | 237 | +            let mut err = feature_err(  | 
 | 238 | +                &self.sess.parse_sess,  | 
 | 239 | +                sym::arbitrary_enum_discriminant,  | 
 | 240 | +                discriminant_spans.clone(),  | 
 | 241 | +                "custom discriminant values are not allowed in enums with tuple or struct variants",  | 
 | 242 | +            );  | 
 | 243 | +            for sp in discriminant_spans {  | 
 | 244 | +                err.span_label(sp, "disallowed custom discriminant");  | 
 | 245 | +            }  | 
 | 246 | +            for variant in variants.iter() {  | 
 | 247 | +                match &variant.data {  | 
 | 248 | +                    VariantData::Struct(..) => {  | 
 | 249 | +                        err.span_label(variant.span, "struct variant defined here");  | 
 | 250 | +                    }  | 
 | 251 | +                    VariantData::Tuple(..) => {  | 
 | 252 | +                        err.span_label(variant.span, "tuple variant defined here");  | 
 | 253 | +                    }  | 
 | 254 | +                    VariantData::Unit(..) => {}  | 
 | 255 | +                }  | 
 | 256 | +            }  | 
 | 257 | +            err.emit();  | 
 | 258 | +        }  | 
 | 259 | +    }  | 
 | 260 | + | 
221 | 261 |     fn check_gat(&self, generics: &ast::Generics, span: Span) {  | 
222 | 262 |         if !generics.params.is_empty() {  | 
223 | 263 |             gate_feature_post!(  | 
@@ -362,6 +402,26 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {  | 
362 | 402 |                 }  | 
363 | 403 |             }  | 
364 | 404 | 
 
  | 
 | 405 | +            ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {  | 
 | 406 | +                for variant in variants {  | 
 | 407 | +                    match (&variant.data, &variant.disr_expr) {  | 
 | 408 | +                        (ast::VariantData::Unit(..), _) => {}  | 
 | 409 | +                        (_, Some(disr_expr)) => gate_feature_post!(  | 
 | 410 | +                            &self,  | 
 | 411 | +                            arbitrary_enum_discriminant,  | 
 | 412 | +                            disr_expr.value.span,  | 
 | 413 | +                            "discriminants on non-unit variants are experimental"  | 
 | 414 | +                        ),  | 
 | 415 | +                        _ => {}  | 
 | 416 | +                    }  | 
 | 417 | +                }  | 
 | 418 | + | 
 | 419 | +                let has_feature = self.features.arbitrary_enum_discriminant;  | 
 | 420 | +                if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {  | 
 | 421 | +                    self.maybe_report_invalid_custom_discriminants(&variants);  | 
 | 422 | +                }  | 
 | 423 | +            }  | 
 | 424 | + | 
365 | 425 |             ast::ItemKind::Impl(box ast::ImplKind {  | 
366 | 426 |                 polarity, defaultness, ref of_trait, ..  | 
367 | 427 |             }) => {  | 
 | 
0 commit comments