about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
authorFrank King <frankking1729@gmail.com>2024-01-04 21:53:06 +0800
committerFrank King <frankking1729@gmail.com>2024-02-12 12:47:23 +0800
commit879a1e571305a0fb35ef6cc4297f9230fca95be5 (patch)
tree232e06c6b3eefcc81f10f825a430f04a7325c498 /compiler/rustc_hir_analysis/src
parent084ce5bdb5f7dc1c725f6770a8de281165ba3b0a (diff)
downloadrust-879a1e571305a0fb35ef6cc4297f9230fca95be5.tar.gz
rust-879a1e571305a0fb35ef6cc4297f9230fca95be5.zip
Lower anonymous structs or unions to HIR
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs82
2 files changed, 87 insertions, 8 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 1ae3ebaebbb..a643614d33d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2457,6 +2457,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             hir::TyKind::Tup(fields) => {
                 Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.ast_ty_to_ty(t)))
             }
+            hir::TyKind::AnonAdt(item_id) => {
+                let did = item_id.owner_id.def_id;
+                let adt_def = tcx.adt_def(did);
+                let generics = tcx.generics_of(did);
+
+                debug!("ast_ty_to_ty_inner(AnonAdt): generics={:?}", generics);
+                let args = ty::GenericArgs::for_item(tcx, did.to_def_id(), |param, _| {
+                    tcx.mk_param_from_def(param)
+                });
+                debug!("ast_ty_to_ty_inner(AnonAdt): args={:?}", args);
+
+                Ty::new_adt(tcx, adt_def, tcx.mk_args(args))
+            }
             hir::TyKind::BareFn(bf) => {
                 require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span);
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f458ff01c10..768b07069c8 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -789,6 +789,65 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
     }
 }
 
+/*
+/// In a type definition, we check that unnamed field names are distinct.
+fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) {
+    let mut seen_fields: FxHashMap<Ident, Option<Span>> = Default::default();
+    fn check_fields_anon_adt_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, seen_fields: &mut FxHashMap<Ident, Option<Span>>) {
+        let fields = match &item.kind {
+            hir::ItemKind::Struct(fields, _) | hir::ItemKind::Union(fields, _) => fields,
+            _ => return,
+        };
+        for field in fields.fields() {
+            if field.ident.name == kw::Underscore {
+                if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() {
+                    let item = tcx.hir().item(item_id);
+                    check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
+                } else {
+                    let field_ty = match tcx.type_of(field.def_id).instantiate_identity().ty_adt_def() {
+                        Some(adt_ty) => adt_ty,
+                        None => {
+                            tcx.sess.emit_err(err);
+                            return;
+                        }
+                    };
+                    if let Some(def_id) = field_ty.did().as_local() {
+                        let item = tcx.hir().item(hir::ItemId { owner_id: hir::OwnerId { def_id }});
+                        check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
+                    }
+                }
+                field_ty.flags()
+                let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt");
+                check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields);
+            } else {
+                let span = field.did.as_local().map(|did| {
+                    let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+                    tcx.hir().span(hir_id)
+                });
+                match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() {
+                    Some(Some(prev_span)) => {
+                        tcx.sess.emit_err(errors::FieldAlreadyDeclared {
+                            field_name: ident,
+                            span: f.span,
+                            prev_span,
+                        });
+                    }
+                    Some(None) => {
+                        tcx.sess.emit_err(errors::FieldAlreadyDeclared {
+                            field_name: f.ident,
+                            span: f.span,
+                            prev_span,
+                        });
+                    }
+                    None =>
+                        seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
+                }
+            }
+        }
+    }
+}
+ */
+
 fn convert_variant(
     tcx: TyCtxt<'_>,
     variant_did: Option<LocalDefId>,
@@ -798,11 +857,17 @@ fn convert_variant(
     adt_kind: ty::AdtKind,
     parent_did: LocalDefId,
 ) -> ty::VariantDef {
+    let mut has_unnamed_fields = false;
     let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
     let fields = def
         .fields()
         .iter()
-        .map(|f| {
+        .inspect(|f| {
+            // Skip the unnamed field here, we will check it later.
+            if f.ident.name == kw::Underscore {
+                has_unnamed_fields = true;
+                return;
+            }
             let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
             if let Some(prev_span) = dup_span {
                 tcx.dcx().emit_err(errors::FieldAlreadyDeclared {
@@ -813,12 +878,11 @@ fn convert_variant(
             } else {
                 seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
             }
-
-            ty::FieldDef {
-                did: f.def_id.to_def_id(),
-                name: f.ident.name,
-                vis: tcx.visibility(f.def_id),
-            }
+        })
+        .map(|f| ty::FieldDef {
+            did: f.def_id.to_def_id(),
+            name: f.ident.name,
+            vis: tcx.visibility(f.def_id),
         })
         .collect();
     let recovered = match def {
@@ -837,6 +901,7 @@ fn convert_variant(
         adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
             || variant_did
                 .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
+        has_unnamed_fields,
     )
 }
 
@@ -847,6 +912,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
         bug!("expected ADT to be an item");
     };
 
+    let is_anonymous = item.ident.name == kw::Empty;
     let repr = tcx.repr_options_of_def(def_id.to_def_id());
     let (kind, variants) = match &item.kind {
         ItemKind::Enum(def, _) => {
@@ -897,7 +963,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
         }
         _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
     };
-    tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
+    tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr, is_anonymous)
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {