summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_macros/src/diagnostics/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_macros/src/diagnostics/utils.rs')
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs67
1 files changed, 37 insertions, 30 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 6f52a3de1..27b8f676f 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -80,7 +80,7 @@ fn report_error_if_not_applied_to_ty(
path: &[&str],
ty_name: &str,
) -> Result<(), DiagnosticDeriveError> {
- if !type_matches_path(info.ty, path) {
+ if !type_matches_path(info.ty.inner_type(), path) {
report_type_error(attr, ty_name)?;
}
@@ -105,8 +105,8 @@ pub(crate) fn report_error_if_not_applied_to_span(
attr: &Attribute,
info: &FieldInfo<'_>,
) -> Result<(), DiagnosticDeriveError> {
- if !type_matches_path(info.ty, &["rustc_span", "Span"])
- && !type_matches_path(info.ty, &["rustc_errors", "MultiSpan"])
+ if !type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"])
+ && !type_matches_path(info.ty.inner_type(), &["rustc_errors", "MultiSpan"])
{
report_type_error(attr, "`Span` or `MultiSpan`")?;
}
@@ -115,44 +115,50 @@ pub(crate) fn report_error_if_not_applied_to_span(
}
/// Inner type of a field and type of wrapper.
+#[derive(Copy, Clone)]
pub(crate) enum FieldInnerTy<'ty> {
/// Field is wrapped in a `Option<$inner>`.
Option(&'ty Type),
/// Field is wrapped in a `Vec<$inner>`.
Vec(&'ty Type),
/// Field isn't wrapped in an outer type.
- None,
+ Plain(&'ty Type),
}
impl<'ty> FieldInnerTy<'ty> {
/// Returns inner type for a field, if there is one.
///
- /// - If `ty` is an `Option`, returns `FieldInnerTy::Option { inner: (inner type) }`.
- /// - If `ty` is a `Vec`, returns `FieldInnerTy::Vec { inner: (inner type) }`.
- /// - Otherwise returns `None`.
+ /// - If `ty` is an `Option<Inner>`, returns `FieldInnerTy::Option(Inner)`.
+ /// - If `ty` is a `Vec<Inner>`, returns `FieldInnerTy::Vec(Inner)`.
+ /// - Otherwise returns `FieldInnerTy::Plain(ty)`.
pub(crate) fn from_type(ty: &'ty Type) -> Self {
- let variant: &dyn Fn(&'ty Type) -> FieldInnerTy<'ty> =
- if type_matches_path(ty, &["std", "option", "Option"]) {
- &FieldInnerTy::Option
- } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
- &FieldInnerTy::Vec
- } else {
- return FieldInnerTy::None;
+ fn single_generic_type(ty: &Type) -> &Type {
+ let Type::Path(ty_path) = ty else {
+ panic!("expected path type");
};
- if let Type::Path(ty_path) = ty {
let path = &ty_path.path;
let ty = path.segments.iter().last().unwrap();
- if let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments {
- if bracketed.args.len() == 1 {
- if let syn::GenericArgument::Type(ty) = &bracketed.args[0] {
- return variant(ty);
- }
- }
- }
+ let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments else {
+ panic!("expected bracketed generic arguments");
+ };
+
+ assert_eq!(bracketed.args.len(), 1);
+
+ let syn::GenericArgument::Type(ty) = &bracketed.args[0] else {
+ panic!("expected generic parameter to be a type generic");
+ };
+
+ ty
}
- unreachable!();
+ if type_matches_path(ty, &["std", "option", "Option"]) {
+ FieldInnerTy::Option(single_generic_type(ty))
+ } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
+ FieldInnerTy::Vec(single_generic_type(ty))
+ } else {
+ FieldInnerTy::Plain(ty)
+ }
}
/// Returns `true` if `FieldInnerTy::with` will result in iteration for this inner type (i.e.
@@ -160,15 +166,16 @@ impl<'ty> FieldInnerTy<'ty> {
pub(crate) fn will_iterate(&self) -> bool {
match self {
FieldInnerTy::Vec(..) => true,
- FieldInnerTy::Option(..) | FieldInnerTy::None => false,
+ FieldInnerTy::Option(..) | FieldInnerTy::Plain(_) => false,
}
}
- /// Returns `Option` containing inner type if there is one.
- pub(crate) fn inner_type(&self) -> Option<&'ty Type> {
+ /// Returns the inner type.
+ pub(crate) fn inner_type(&self) -> &'ty Type {
match self {
- FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) => Some(inner),
- FieldInnerTy::None => None,
+ FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) | FieldInnerTy::Plain(inner) => {
+ inner
+ }
}
}
@@ -185,7 +192,7 @@ impl<'ty> FieldInnerTy<'ty> {
#inner
}
},
- FieldInnerTy::None => quote! { #inner },
+ FieldInnerTy::Plain(..) => quote! { #inner },
}
}
}
@@ -194,7 +201,7 @@ impl<'ty> FieldInnerTy<'ty> {
/// `generate_*` methods from walking the attributes themselves.
pub(crate) struct FieldInfo<'a> {
pub(crate) binding: &'a BindingInfo<'a>,
- pub(crate) ty: &'a Type,
+ pub(crate) ty: FieldInnerTy<'a>,
pub(crate) span: &'a proc_macro2::Span,
}