about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <rust@boxyuwu.dev>2024-11-30 19:31:06 +0000
committerBoxy <rust@boxyuwu.dev>2024-12-03 23:39:51 +0000
commitec036cda3fee341d938336b64bc38cd11df7231d (patch)
tree2397765ef5e6e6afa1fcfbebc1eb3cd8cf7764a2
parentc44b3d50fea96a3e0417e8264c16ea21a0a3fca2 (diff)
downloadrust-ec036cda3fee341d938336b64bc38cd11df7231d.tar.gz
rust-ec036cda3fee341d938336b64bc38cd11df7231d.zip
Don't try and handle unfed `type_of` on anon consts
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs243
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs2
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr10
-rw-r--r--tests/ui/traits/bound/unknown-assoc-with-const-arg.rs2
-rw-r--r--tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr22
6 files changed, 14 insertions, 270 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 8d5824130d8..a4636da3f62 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -309,10 +309,10 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
                     self.tcx.ensure().type_of(param.def_id);
                     if let Some(default) = default {
                         // need to store default and type of default
+                        self.tcx.ensure().const_param_default(param.def_id);
                         if let hir::ConstArgKind::Anon(ac) = default.kind {
                             self.tcx.ensure().type_of(ac.def_id);
                         }
-                        self.tcx.ensure().const_param_default(param.def_id);
                     }
                 }
             }
@@ -1817,7 +1817,6 @@ fn const_param_default<'tcx>(
         ),
     };
     let icx = ItemCtxt::new(tcx, def_id);
-    // FIXME(const_generics): investigate which places do and don't need const ty feeding
-    let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
+    let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id()));
     ty::EarlyBinder::bind(ct)
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 7cf99bebd36..72d5b3ac4f5 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -12,7 +12,6 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span};
-use tracing::debug;
 
 use super::{ItemCtxt, bad_placeholder};
 use crate::errors::TypeofReservedKeywordUsed;
@@ -138,252 +137,26 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
     use hir::*;
     use rustc_middle::ty::Ty;
 
-    let parent_node_id = tcx.parent_hir_id(arg_hir_id);
-    let parent_node = tcx.hir_node(parent_node_id);
-
-    let (generics, arg_idx) = match parent_node {
-        // Easy case: arrays repeat expressions.
+    match tcx.parent_hir_node(arg_hir_id) {
+        // Array length const arguments do not have `type_of` fed as there is never a corresponding
+        // generic parameter definition.
         Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
         | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
             if constant.hir_id == arg_hir_id =>
         {
             return tcx.types.usize;
         }
-        Node::GenericParam(&GenericParam {
-            def_id: param_def_id,
-            kind: GenericParamKind::Const { default: Some(ct), .. },
-            ..
-        }) if ct.hir_id == arg_hir_id => {
-            return tcx
-                .type_of(param_def_id)
-                .no_bound_vars()
-                .expect("const parameter types cannot be generic");
-        }
-
-        // This match arm is for when the def_id appears in a GAT whose
-        // path can't be resolved without typechecking e.g.
-        //
-        // trait Foo {
-        //   type Assoc<const N: usize>;
-        //   fn foo() -> Self::Assoc<3>;
-        // }
-        //
-        // In the above code we would call this query with the def_id of 3 and
-        // the parent_node we match on would be the hir node for Self::Assoc<3>
-        //
-        // `Self::Assoc<3>` cant be resolved without typechecking here as we
-        // didnt write <Self as Foo>::Assoc<3>. If we did then another match
-        // arm would handle this.
-        //
-        // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
-        Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(ty, segment)), .. }) => {
-            // Find the Item containing the associated type so we can create an ItemCtxt.
-            // Using the ItemCtxt lower the HIR for the unresolved assoc type into a
-            // ty which is a fully resolved projection.
-            // For the code example above, this would mean lowering `Self::Assoc<3>`
-            // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
-            let item_def_id = tcx.hir().get_parent_item(ty.hir_id).def_id;
-            let ty = ItemCtxt::new(tcx, item_def_id).lower_ty(hir_ty);
-
-            // Iterate through the generics of the projection to find the one that corresponds to
-            // the def_id that this query was called with. We filter to only type and const args here
-            // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
-            // but it can't hurt to be safe ^^
-            if let ty::Alias(ty::Projection | ty::Inherent, projection) = ty.kind() {
-                let generics = tcx.generics_of(projection.def_id);
-
-                let arg_index = segment
-                    .args
-                    .and_then(|args| {
-                        args.args
-                            .iter()
-                            .filter(|arg| arg.is_ty_or_const())
-                            .position(|arg| arg.hir_id() == arg_hir_id)
-                    })
-                    .unwrap_or_else(|| {
-                        bug!("no arg matching AnonConst in segment");
-                    });
-
-                (generics, arg_index)
-            } else {
-                // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
-                return Ty::new_error_with_message(
-                    tcx,
-                    span,
-                    "unexpected non-GAT usage of an anon const",
-                );
-            }
-        }
-        Node::Expr(&Expr {
-            kind:
-                ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
-            ..
-        }) => {
-            let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
-            let tables = tcx.typeck(body_owner);
-            // This may fail in case the method/path does not actually exist.
-            // As there is no relevant param for `def_id`, we simply return
-            // `None` here.
-            let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
-                return Ty::new_error_with_message(
-                    tcx,
-                    span,
-                    format!("unable to find type-dependent def for {parent_node_id:?}"),
-                );
-            };
-            let idx = segment
-                .args
-                .and_then(|args| {
-                    args.args
-                        .iter()
-                        .filter(|arg| arg.is_ty_or_const())
-                        .position(|arg| arg.hir_id() == arg_hir_id)
-                })
-                .unwrap_or_else(|| {
-                    bug!("no arg matching ConstArg in segment");
-                });
-
-            (tcx.generics_of(type_dependent_def), idx)
-        }
-
-        Node::Ty(&hir::Ty { kind: TyKind::Path(_), .. })
-        | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
-        | Node::TraitRef(..)
-        | Node::Pat(_) => {
-            let path = match parent_node {
-                Node::Ty(&hir::Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
-                | Node::TraitRef(&TraitRef { path, .. }) => &*path,
-                Node::Expr(&Expr {
-                    kind:
-                        ExprKind::Path(QPath::Resolved(_, path))
-                        | ExprKind::Struct(&QPath::Resolved(_, path), ..),
-                    ..
-                }) => {
-                    let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
-                    let _tables = tcx.typeck(body_owner);
-                    &*path
-                }
-                Node::Pat(pat) => {
-                    if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) {
-                        path
-                    } else {
-                        return Ty::new_error_with_message(
-                            tcx,
-                            span,
-                            format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"),
-                        );
-                    }
-                }
-                _ => {
-                    return Ty::new_error_with_message(
-                        tcx,
-                        span,
-                        format!("unexpected const parent path {parent_node:?}"),
-                    );
-                }
-            };
-
-            // We've encountered an `AnonConst` in some path, so we need to
-            // figure out which generic parameter it corresponds to and return
-            // the relevant type.
-            let Some((arg_index, segment)) = path.segments.iter().find_map(|seg| {
-                let args = seg.args?;
-                args.args
-                    .iter()
-                    .filter(|arg| arg.is_ty_or_const())
-                    .position(|arg| arg.hir_id() == arg_hir_id)
-                    .map(|index| (index, seg))
-                    .or_else(|| {
-                        args.constraints
-                            .iter()
-                            .copied()
-                            .filter_map(AssocItemConstraint::ct)
-                            .position(|ct| ct.hir_id == arg_hir_id)
-                            .map(|idx| (idx, seg))
-                    })
-            }) else {
-                return Ty::new_error_with_message(tcx, span, "no arg matching AnonConst in path");
-            };
-
-            let generics = match tcx.res_generics_def_id(segment.res) {
-                Some(def_id) => tcx.generics_of(def_id),
-                None => {
-                    return Ty::new_error_with_message(
-                        tcx,
-                        span,
-                        format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
-                    );
-                }
-            };
-
-            (generics, arg_index)
-        }
 
-        _ => {
-            return Ty::new_error_with_message(
-                tcx,
-                span,
-                format!("unexpected const arg parent in type_of(): {parent_node:?}"),
-            );
-        }
-    };
-
-    debug!(?parent_node);
-    debug!(?generics, ?arg_idx);
-    if let Some(param_def_id) = generics
-        .own_params
-        .iter()
-        .filter(|param| param.kind.is_ty_or_const())
-        .nth(match generics.has_self && generics.parent.is_none() {
-            true => arg_idx + 1,
-            false => arg_idx,
-        })
-        .and_then(|param| match param.kind {
-            ty::GenericParamDefKind::Const { .. } => {
-                debug!(?param);
-                Some(param.def_id)
-            }
-            _ => None,
-        })
-    {
-        tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
-    } else {
-        return Ty::new_error_with_message(
+        // This is not a `bug!` as const arguments in path segments that did not resolve to anything
+        // will result in `type_of` never being fed.
+        _ => Ty::new_error_with_message(
             tcx,
             span,
-            format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
-        );
+            "`type_of` called on const argument's anon const before the const argument was lowered",
+        ),
     }
 }
 
-fn get_path_containing_arg_in_pat<'hir>(
-    pat: &'hir hir::Pat<'hir>,
-    arg_id: HirId,
-) -> Option<&'hir hir::Path<'hir>> {
-    use hir::*;
-
-    let is_arg_in_path = |p: &hir::Path<'_>| {
-        p.segments
-            .iter()
-            .filter_map(|seg| seg.args)
-            .flat_map(|args| args.args)
-            .any(|arg| arg.hir_id() == arg_id)
-    };
-    let mut arg_path = None;
-    pat.walk(|pat| match pat.kind {
-        PatKind::Struct(QPath::Resolved(_, path), _, _)
-        | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
-        | PatKind::Path(QPath::Resolved(_, path))
-            if is_arg_in_path(path) =>
-        {
-            arg_path = Some(path);
-            false
-        }
-        _ => true,
-    });
-    arg_path
-}
-
 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> {
     use rustc_hir::*;
     use rustc_middle::ty::Ty;
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
index 07c13239a2c..c98ec1de17e 100644
--- a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
@@ -3,8 +3,6 @@
 trait X {
     fn test() -> Self::Assoc<{ async {} }>;
     //~^ ERROR associated type `Assoc` not found for `Self`
-    //~| ERROR associated type `Assoc` not found for `Self`
-
 }
 
 pub fn main() {}
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
index 864c6556d79..58553728753 100644
--- a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
@@ -4,14 +4,6 @@ error[E0220]: associated type `Assoc` not found for `Self`
 LL |     fn test() -> Self::Assoc<{ async {} }>;
    |                        ^^^^^ associated type `Assoc` not found
 
-error[E0220]: associated type `Assoc` not found for `Self`
-  --> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
-   |
-LL |     fn test() -> Self::Assoc<{ async {} }>;
-   |                        ^^^^^ associated type `Assoc` not found
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
index 48a98efea5e..0da68afb592 100644
--- a/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
+++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
@@ -3,7 +3,6 @@
 trait X {
     fn a<T>() -> T::unknown<{}> {}
     //~^ ERROR: associated type `unknown` not found for `T`
-    //~| ERROR: associated type `unknown` not found for `T`
 }
 
 trait Y {
@@ -14,7 +13,6 @@ trait Y {
 trait Z<T> {
     fn a() -> T::unknown<{}> {}
     //~^ ERROR: associated type `unknown` not found for `T`
-    //~| ERROR: associated type `unknown` not found for `T`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
index 9598c373e6e..49e41f75ff3 100644
--- a/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
+++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
@@ -5,34 +5,18 @@ LL |     fn a<T>() -> T::unknown<{}> {}
    |                     ^^^^^^^ associated type `unknown` not found
 
 error[E0220]: associated type `unknown` not found for `T`
-  --> $DIR/unknown-assoc-with-const-arg.rs:15:18
+  --> $DIR/unknown-assoc-with-const-arg.rs:14:18
    |
 LL |     fn a() -> T::unknown<{}> {}
    |                  ^^^^^^^ associated type `unknown` not found
 
-error[E0220]: associated type `unknown` not found for `T`
-  --> $DIR/unknown-assoc-with-const-arg.rs:4:21
-   |
-LL |     fn a<T>() -> T::unknown<{}> {}
-   |                     ^^^^^^^ associated type `unknown` not found
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0220]: associated type `unknown` not found for `T`
-  --> $DIR/unknown-assoc-with-const-arg.rs:15:18
-   |
-LL |     fn a() -> T::unknown<{}> {}
-   |                  ^^^^^^^ associated type `unknown` not found
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0433]: failed to resolve: use of undeclared type `NOT_EXIST`
-  --> $DIR/unknown-assoc-with-const-arg.rs:10:15
+  --> $DIR/unknown-assoc-with-const-arg.rs:9:15
    |
 LL |     fn a() -> NOT_EXIST::unknown<{}> {}
    |               ^^^^^^^^^ use of undeclared type `NOT_EXIST`
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0220, E0433.
 For more information about an error, try `rustc --explain E0220`.