about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAli MJ Al-Nasrawy <alimjalnasrawy@gmail.com>2022-10-29 16:19:57 +0300
committerAli MJ Al-Nasrawy <alimjalnasrawy@gmail.com>2023-01-07 13:38:38 +0300
commit34329d6f6c73a6f0080e169007d099a40db3aea1 (patch)
treef07cb5c8012a1329a2e6e860b606a599f59d7068
parentd227506683e846cbeb872e089d660187a7a6041f (diff)
downloadrust-34329d6f6c73a6f0080e169007d099a40db3aea1.tar.gz
rust-34329d6f6c73a6f0080e169007d099a40db3aea1.zip
introduce AstConv::probe_adt
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs17
4 files changed, 38 insertions, 19 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index bcb695cc8e3..df6600626a3 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -106,9 +106,12 @@ pub trait AstConv<'tcx> {
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx>;
 
-    fn normalize_ty_2(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        ty
-    }
+    /// Returns `AdtDef` if `ty` is an ADT.
+    /// Note that `ty` might be a projection type that needs normalization.
+    /// This used to get the enum variants in scope of the type.
+    /// For example, `Self::A` could refer to an associated type
+    /// or to an enum variant depending on the result of this function.
+    fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>;
 
     /// Invoked when we encounter an error from some prior pass
     /// (e.g., resolve) that is translated into a ty-error. This is
@@ -1805,7 +1808,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // Check if we have an enum variant.
         let mut variant_resolution = None;
-        if let ty::Adt(adt_def, adt_substs) = self.normalize_ty_2(span, qself_ty).kind() {
+        if let Some(adt_def) = self.probe_adt(span, qself_ty) {
             if adt_def.is_enum() {
                 let variant_def = adt_def
                     .variants()
@@ -1907,6 +1910,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else {
                     continue;
                 };
+                let ty::Adt(_, adt_substs) = qself_ty.kind() else {
+                    // FIXME(inherent_associated_types)
+                    bug!("unimplemented: non-adt self of inherent assoc ty");
+                };
                 let item_substs = self.create_substs_for_associated_item(
                     span,
                     assoc_ty_did,
@@ -2262,6 +2269,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Option<Ty<'tcx>>,
         kind: DefKind,
         def_id: DefId,
+        span: Span,
     ) -> Vec<PathSeg> {
         // We need to extract the type parameters supplied by the user in
         // the path `path`. Due to the current setup, this is a bit of a
@@ -2329,8 +2337,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             // Case 2. Reference to a variant constructor.
             DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => {
-                let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
-                let (generics_def_id, index) = if let Some(adt_def) = adt_def {
+                let (generics_def_id, index) = if let Some(self_ty) = self_ty {
+                    let adt_def = self.probe_adt(span, self_ty).unwrap();
                     debug_assert!(adt_def.is_enum());
                     (adt_def.did(), last)
                 } else if last >= 1 && segments[last - 1].args.is_some() {
@@ -2426,7 +2434,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 assert_eq!(opt_self_ty, None);
 
                 let path_segs =
-                    self.def_ids_for_value_path_segments(path.segments, None, kind, def_id);
+                    self.def_ids_for_value_path_segments(path.segments, None, kind, def_id, span);
                 let generic_segs: FxHashSet<_> =
                     path_segs.iter().map(|PathSeg(_, index)| index).collect();
                 self.prohibit_generics(
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index fd54aec480a..b7f259668a1 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -505,6 +505,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
         }
     }
 
+    fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
+        // FIXME(#103640): Should we handle the case where `ty` is a projection?
+        ty.ty_adt_def()
+    }
+
     fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
         // There's no obvious place to track this, so just let it go.
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 3e05f67b74b..6c2dfaf4413 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1007,9 +1007,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Res::Def(kind, def_id) => <dyn AstConv<'_>>::def_ids_for_value_path_segments(
                 self,
                 segments,
-                self_ty.map(|ty| ty.normalized),
+                self_ty.map(|ty| ty.raw),
                 kind,
                 def_id,
+                span,
             ),
             _ => bug!("instantiate_value_path on {:?}", res),
         };
@@ -1122,7 +1123,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .unwrap_or(false);
 
         let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
-            let ty = self.normalize_ty_2(span, tcx.at(span).type_of(impl_def_id));
+            let ty = tcx.at(span).type_of(impl_def_id);
+            let ty = self.normalize(span, ty);
             match *ty.kind() {
                 ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
                     let variant = adt_def.non_enum_variant();
@@ -1238,10 +1240,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // If we have a default, then we it doesn't matter that we're not
                             // inferring the type arguments: we provide the default where any
                             // is missing.
-                            let default = tcx.bound_type_of(param.def_id);
-                            self.fcx
-                                .normalize_ty_2(self.span, default.subst(tcx, substs.unwrap()))
-                                .into()
+                            let default =
+                                tcx.bound_type_of(param.def_id).subst(tcx, substs.unwrap());
+                            self.fcx.normalize(self.span, default).into()
                         } else {
                             // If no type arguments were provided, we have to infer them.
                             // This case also occurs as a result of some malformed input, e.g.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index d7e53a0aa04..6347b9a69a0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -297,11 +297,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
         self.tcx().mk_projection(item_def_id, item_substs)
     }
 
-    fn normalize_ty_2(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if ty.has_escaping_bound_vars() {
-            ty // FIXME: normalization and escaping regions
-        } else {
-            self.normalize(span, ty)
+    fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
+        match ty.kind() {
+            ty::Adt(adt_def, _) => Some(*adt_def),
+            // FIXME(#104767): Should we handle bound regions here?
+            ty::Alias(ty::Projection, _) if !ty.has_escaping_bound_vars() => {
+                self.normalize(span, ty).ty_adt_def()
+            }
+            _ => None,
         }
     }
 
@@ -310,7 +313,9 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     }
 
     fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) {
-        self.write_ty(hir_id, self.normalize_ty_2(span, ty))
+        // FIXME: normalization and escaping regions
+        let ty = if !ty.has_escaping_bound_vars() { self.normalize(span, ty) } else { ty };
+        self.write_ty(hir_id, ty)
     }
 }