about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs14
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs8
-rw-r--r--compiler/rustc_infer/src/traits/util.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs7
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs23
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs5
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs406
16 files changed, 278 insertions, 247 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 75f384405bb..885537a212f 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -11,7 +11,7 @@ use rustc_hir::def::Res;
 use rustc_hir::definitions::DefPathData;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{sym, Ident};
 use rustc_span::DUMMY_SP;
 
 impl<'hir> LoweringContext<'_, 'hir> {
@@ -1204,11 +1204,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
 
         let fields = self.arena.alloc_from_iter(
-            e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))).map(|(s, e)| {
-                let expr = self.lower_expr(&e);
-                let ident = Ident::new(Symbol::intern(s), self.lower_span(e.span));
-                self.expr_field(ident, expr, e.span)
-            }),
+            e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
+                |(s, e)| {
+                    let expr = self.lower_expr(&e);
+                    let ident = Ident::new(s, self.lower_span(e.span));
+                    self.expr_field(ident, expr, e.span)
+                },
+            ),
         );
 
         hir::ExprKind::Struct(
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 1f745f977d4..87b0a887d1c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -312,6 +312,7 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
     }
 }
 
+#[track_caller]
 fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: &str) {
     // We sometimes see MIR failures (notably predicate failures) due to
     // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f03d8eea40b..76f4df6ec2d 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -293,10 +293,6 @@ impl GenericArg<'_> {
         }
     }
 
-    pub fn is_const(&self) -> bool {
-        matches!(self, GenericArg::Const(_))
-    }
-
     pub fn is_synthetic(&self) -> bool {
         matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty())
     }
@@ -318,6 +314,13 @@ impl GenericArg<'_> {
             GenericArg::Infer(_) => ast::ParamKindOrd::Infer,
         }
     }
+
+    pub fn is_ty_or_const(&self) -> bool {
+        match self {
+            GenericArg::Lifetime(_) => false,
+            GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true,
+        }
+    }
 }
 
 #[derive(Debug, HashStable_Generic)]
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 8bb0e8b960c..c1cca834f2b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::symbol::kw;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use std::borrow::Cow;
 
 struct FindHirNodeVisitor<'a, 'tcx> {
@@ -1003,9 +1003,9 @@ impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
             | ty::Opaque(..)
             | ty::Projection(_)
             | ty::Never => t.super_fold_with(self),
-            ty::Array(ty, c) => self
-                .tcx()
-                .mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))),
+            ty::Array(ty, c) => {
+                self.tcx().mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, sym::N)))
+            }
             // We don't want to hide type params that haven't been resolved yet.
             // This would be the type that will be written out with the type param
             // name in the output.
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 8f5d6c85097..65443fd88d7 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -152,7 +152,7 @@ impl<'tcx> Elaborator<'tcx> {
                         obligation.cause.clone(),
                     )
                 });
-                debug!("super_predicates: data={:?}", data);
+                debug!(?data, ?obligations, "super_predicates");
 
                 // Only keep those bounds that we haven't already seen.
                 // This is necessary to prevent infinite recursion in some
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 1c3a01e2cfa..0bd96f8f865 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -31,6 +31,13 @@ impl GenericParamDefKind {
             GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const,
         }
     }
+
+    pub fn is_ty_or_const(&self) -> bool {
+        match self {
+            GenericParamDefKind::Lifetime => false,
+            GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => true,
+        }
+    }
 }
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 94127a144df..7b5905fddc9 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -188,6 +188,11 @@ pub trait Printer<'tcx>: Sized {
             own_params.start = 1;
         }
 
+        // If we're in verbose mode, then print default-equal args too
+        if self.tcx().sess.verbose() {
+            return &substs[own_params];
+        }
+
         // Don't print args that are the defaults of their respective parameters.
         own_params.end -= generics
             .params
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 350386f8d93..b2ae6e6fae6 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1784,10 +1784,11 @@ impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
         self = print_prefix(self)?;
 
         // Don't print `'_` if there's no unerased regions.
-        let print_regions = args.iter().any(|arg| match arg.unpack() {
-            GenericArgKind::Lifetime(r) => *r != ty::ReErased,
-            _ => false,
-        });
+        let print_regions = self.tcx.sess.verbose()
+            || args.iter().any(|arg| match arg.unpack() {
+                GenericArgKind::Lifetime(r) => *r != ty::ReErased,
+                _ => false,
+            });
         let args = args.iter().cloned().filter(|arg| match arg.unpack() {
             GenericArgKind::Lifetime(_) => print_regions,
             _ => true,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5134d916320..f99d5cfad0a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -208,6 +208,7 @@ symbols! {
         LinkedList,
         LintPass,
         Mutex,
+        N,
         None,
         Ok,
         Option,
@@ -327,6 +328,7 @@ symbols! {
         array,
         arrays,
         as_ptr,
+        as_ref,
         as_str,
         asm,
         asm_const,
@@ -593,6 +595,7 @@ symbols! {
         enable,
         enclosing_scope,
         encode,
+        end,
         env,
         eq,
         ermsb_target_feature,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 035bc9b00c9..577b96f3a40 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1225,6 +1225,10 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     );
 }
 
+#[tracing::instrument(
+    level = "debug",
+    skip(selcx, candidate_set, ctor, env_predicates, potentially_unnormalized_candidates)
+)]
 fn assemble_candidates_from_predicates<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
@@ -1233,8 +1237,6 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
     potentially_unnormalized_candidates: bool,
 ) {
-    debug!(?obligation, "assemble_candidates_from_predicates");
-
     let infcx = selcx.infcx();
     for predicate in env_predicates {
         debug!(?predicate);
@@ -1270,13 +1272,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     }
 }
 
+#[tracing::instrument(level = "debug", skip(selcx, obligation, candidate_set))]
 fn assemble_candidates_from_impls<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
 ) {
-    debug!("assemble_candidates_from_impls");
-
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
     let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 017f47d4357..b573c4b4390 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -173,6 +173,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
 
+        let sized_predicate = self.tcx().lang_items().sized_trait()
+            == Some(stack.obligation.predicate.skip_binder().def_id());
+
         // If there are STILL multiple candidates, we can further
         // reduce the list by dropping duplicates -- including
         // resolving specializations.
@@ -181,6 +184,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             while i < candidates.len() {
                 let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
                     self.candidate_should_be_dropped_in_favor_of(
+                        sized_predicate,
                         &candidates[i],
                         &candidates[j],
                         needs_infer,
@@ -338,13 +342,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(candidates)
     }
 
+    #[tracing::instrument(level = "debug", skip(self, candidates))]
     fn assemble_candidates_from_projected_tys(
         &mut self,
         obligation: &TraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        debug!(?obligation, "assemble_candidates_from_projected_tys");
-
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
@@ -369,12 +372,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// supplied to find out whether it is listed among them.
     ///
     /// Never affects the inference environment.
+    #[tracing::instrument(level = "debug", skip(self, stack, candidates))]
     fn assemble_candidates_from_caller_bounds<'o>(
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) -> Result<(), SelectionError<'tcx>> {
-        debug!(?stack.obligation, "assemble_candidates_from_caller_bounds");
+        debug!(?stack.obligation);
 
         let all_bounds = stack
             .obligation
@@ -876,6 +880,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
     }
 
+    #[tracing::instrument(level = "debug", skip(self, obligation, candidates))]
     fn assemble_candidates_for_trait_alias(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -883,7 +888,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) {
         // Okay to skip binder here because the tests we do below do not involve bound regions.
         let self_ty = obligation.self_ty().skip_binder();
-        debug!(?self_ty, "assemble_candidates_for_trait_alias");
+        debug!(?self_ty);
 
         let def_id = obligation.predicate.def_id();
 
@@ -894,6 +899,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     /// Assembles the trait which are built-in to the language itself:
     /// `Copy`, `Clone` and `Sized`.
+    #[tracing::instrument(level = "debug", skip(self, candidates))]
     fn assemble_builtin_bound_candidates(
         &mut self,
         conditions: BuiltinImplConditions<'tcx>,
@@ -901,14 +907,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) {
         match conditions {
             BuiltinImplConditions::Where(nested) => {
-                debug!(?nested, "builtin_bound");
                 candidates
                     .vec
                     .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
             }
             BuiltinImplConditions::None => {}
             BuiltinImplConditions::Ambiguous => {
-                debug!("assemble_builtin_bound_candidates: ambiguous builtin");
                 candidates.ambiguous = true;
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index bb3b3203a7c..32518ffb071 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -201,6 +201,7 @@ struct EvaluatedCandidate<'tcx> {
 }
 
 /// When does the builtin impl for `T: Trait` apply?
+#[derive(Debug)]
 enum BuiltinImplConditions<'tcx> {
     /// The impl is conditional on `T1, T2, ...: Trait`.
     Where(ty::Binder<'tcx, Vec<Ty<'tcx>>>),
@@ -344,7 +345,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
             Err(e) => Err(e),
             Ok(candidate) => {
-                debug!(?candidate);
+                debug!(?candidate, "confirmed");
                 Ok(Some(candidate))
             }
         }
@@ -1523,6 +1524,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// See the comment for "SelectionCandidate" for more details.
     fn candidate_should_be_dropped_in_favor_of(
         &mut self,
+        sized_predicate: bool,
         victim: &EvaluatedCandidate<'tcx>,
         other: &EvaluatedCandidate<'tcx>,
         needs_infer: bool,
@@ -1594,6 +1596,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // Drop otherwise equivalent non-const fn pointer candidates
             (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
 
+            // If obligation is a sized predicate or the where-clause bound is
+            // global, prefer the projection or object candidate. See issue
+            // #50825 and #89352.
+            (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
+                sized_predicate || is_global(cand)
+            }
+            (ParamCandidate(ref cand), ObjectCandidate(_) | ProjectionCandidate(_)) => {
+                !(sized_predicate || is_global(cand))
+            }
+
             // Global bounds from the where clause should be ignored
             // here (see issue #50825). Otherwise, we have a where
             // clause so don't go around looking for impls.
@@ -1609,15 +1621,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | BuiltinUnsizeCandidate
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { .. }
-                | TraitAliasCandidate(..)
-                | ObjectCandidate(_)
-                | ProjectionCandidate(_),
+                | TraitAliasCandidate(..),
             ) => !is_global(cand),
-            (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
-                // Prefer these to a global where-clause bound
-                // (see issue #50825).
-                is_global(cand)
-            }
             (
                 ImplCandidate(_)
                 | ClosureCandidate
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 17cf3667611..34f93a517ce 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -288,7 +288,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// Given the type/lifetime/const arguments provided to some path (along with
     /// an implicit `Self`, if this is a trait reference), returns the complete
     /// set of substitutions. This may involve applying defaulted type parameters.
-    /// Also returns back constraints on associated types.
+    /// Constraints on associated typess are created from `create_assoc_bindings_for_generic_args`.
     ///
     /// Example:
     ///
@@ -302,7 +302,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     ///    which will have been resolved to a `def_id`
     /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
     ///    parameters are returned in the `SubstsRef`, the associated type bindings like
-    ///    `Output = u32` are returned in the `Vec<ConvertedBinding...>` result.
+    ///    `Output = u32` are returned from `create_assoc_bindings_for_generic_args`.
     ///
     /// Note that the type listing given here is *exactly* what the user provided.
     ///
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index ac3e09318e5..5057be70c48 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -359,6 +359,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let (obligation, substs) =
             self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types);
 
+        debug!(?obligation);
+
         // Now we want to know if this can be matched
         if !self.predicate_may_hold(&obligation) {
             debug!("--> Cannot match obligation");
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 7cda27041a2..de83e45329b 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::print::with_crate_prefix;
 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_span::lev_distance;
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol};
+use rustc_span::{source_map, FileName, MultiSpan, Span};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
     FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
@@ -1524,8 +1524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
                             // implement the `AsRef` trait.
                             let skip = skippable.contains(&did)
-                                || (("Pin::new" == *pre)
-                                    && (Symbol::intern("as_ref") == item_name.name));
+                                || (("Pin::new" == *pre) && (sym::as_ref == item_name.name));
                             // Make sure the method is defined for the *actual* receiver: we don't
                             // want to treat `Box<Self>` as a receiver if it only works because of
                             // an autoderef to `&self`
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index ae8d262fcf1..5ff2a747541 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -18,6 +18,7 @@ use super::{bad_placeholder, is_suggestable_infer_ty};
 /// Computes the relevant generic parameter for a potential generic const argument.
 ///
 /// This should be called using the query `tcx.opt_const_param_of`.
+#[instrument(level = "debug", skip(tcx))]
 pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
     // FIXME(generic_arg_infer): allow for returning DefIds of inference of
     // GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag
@@ -25,231 +26,228 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
     use hir::*;
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
-    if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
-        let parent_node_id = tcx.hir().get_parent_node(hir_id);
-        let parent_node = tcx.hir().get(parent_node_id);
+    match tcx.hir().get(hir_id) {
+        Node::AnonConst(_) => (),
+        _ => return None,
+    };
 
-        match parent_node {
-            // 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 typchecking 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 @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
-                // Find the Item containing the associated type so we can create an ItemCtxt.
-                // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
-                // ty which is a fully resolved projection.
-                // For the code example above, this would mean converting Self::Assoc<3>
-                // into a ty::Projection(<Self as Foo>::Assoc<3>)
-                let item_hir_id = tcx
-                    .hir()
-                    .parent_iter(hir_id)
-                    .filter(|(_, node)| matches!(node, Node::Item(_)))
-                    .map(|(id, _)| id)
-                    .next()
-                    .unwrap();
-                let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
-                let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
-                let ty = item_ctxt.ast_ty_to_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 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::Projection(projection) = ty.kind() {
-                    let generics = tcx.generics_of(projection.item_def_id);
-
-                    let arg_index = segment
-                        .args
-                        .and_then(|args| {
-                            args.args
-                                .iter()
-                                .filter(|arg| arg.is_const())
-                                .position(|arg| arg.id() == hir_id)
-                        })
-                        .unwrap_or_else(|| {
-                            bug!("no arg matching AnonConst in segment");
-                        });
+    let parent_node_id = tcx.hir().get_parent_node(hir_id);
+    let parent_node = tcx.hir().get(parent_node_id);
 
-                    return generics
-                        .params
-                        .iter()
-                        .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
-                        .nth(arg_index)
-                        .map(|param| param.def_id);
-                }
-
-                // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
-                tcx.sess.delay_span_bug(
-                    tcx.def_span(def_id),
-                    "unexpected non-GAT usage of an anon const",
-                );
-                return None;
-            }
-            Node::Expr(&Expr {
-                kind:
-                    ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
-                ..
-            }) => {
-                let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(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 type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
-                let idx = segment
+    let (generics, arg_idx) = match parent_node {
+        // 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 typchecking 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 @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
+            // Find the Item containing the associated type so we can create an ItemCtxt.
+            // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
+            // ty which is a fully resolved projection.
+            // For the code example above, this would mean converting Self::Assoc<3>
+            // into a ty::Projection(<Self as Foo>::Assoc<3>)
+            let item_hir_id = tcx
+                .hir()
+                .parent_iter(hir_id)
+                .filter(|(_, node)| matches!(node, Node::Item(_)))
+                .map(|(id, _)| id)
+                .next()
+                .unwrap();
+            let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
+            let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
+            let ty = item_ctxt.ast_ty_to_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 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::Projection(projection) = ty.kind() {
+                let generics = tcx.generics_of(projection.item_def_id);
+
+                let arg_index = segment
                     .args
                     .and_then(|args| {
                         args.args
                             .iter()
-                            .filter(|arg| arg.is_const())
+                            .filter(|arg| arg.is_ty_or_const())
                             .position(|arg| arg.id() == hir_id)
                     })
                     .unwrap_or_else(|| {
                         bug!("no arg matching AnonConst in segment");
                     });
 
-                tcx.generics_of(type_dependent_def)
-                    .params
-                    .iter()
-                    .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
-                    .nth(idx)
-                    .map(|param| param.def_id)
+                (generics, arg_index)
+            } else {
+                // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
+                tcx.sess.delay_span_bug(
+                    tcx.def_span(def_id),
+                    "unexpected non-GAT usage of an anon const",
+                );
+                return None;
             }
+        }
+        Node::Expr(&Expr {
+            kind:
+                ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
+            ..
+        }) => {
+            let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(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 type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
+            let idx = segment
+                .args
+                .and_then(|args| {
+                    args.args
+                        .iter()
+                        .filter(|arg| arg.is_ty_or_const())
+                        .position(|arg| arg.id() == hir_id)
+                })
+                .unwrap_or_else(|| {
+                    bug!("no arg matching AnonConst in segment");
+                });
 
-            Node::Ty(&Ty { kind: TyKind::Path(_), .. })
-            | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
-            | Node::TraitRef(..)
-            | Node::Pat(_) => {
-                let path = match parent_node {
-                    Node::Ty(&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().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
-                        let _tables = tcx.typeck(body_owner);
-                        &*path
-                    }
-                    Node::Pat(pat) => {
-                        if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
-                            path
-                        } else {
-                            tcx.sess.delay_span_bug(
-                                tcx.def_span(def_id),
-                                &format!(
-                                    "unable to find const parent for {} in pat {:?}",
-                                    hir_id, pat
-                                ),
-                            );
-                            return None;
-                        }
-                    }
-                    _ => {
-                        tcx.sess.delay_span_bug(
-                            tcx.def_span(def_id),
-                            &format!("unexpected const parent path {:?}", parent_node),
-                        );
-                        return None;
-                    }
-                };
-
-                // 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 filtered = path
-                    .segments
-                    .iter()
-                    .filter_map(|seg| seg.args.map(|args| (args.args, seg)))
-                    .find_map(|(args, seg)| {
-                        args.iter()
-                            .filter(|arg| arg.is_const())
-                            .position(|arg| arg.id() == hir_id)
-                            .map(|index| (index, seg))
-                    });
-                let (arg_index, segment) = match filtered {
-                    None => {
-                        tcx.sess.delay_span_bug(
-                            tcx.def_span(def_id),
-                            "no arg matching AnonConst in path",
-                        );
-                        return None;
-                    }
-                    Some(inner) => inner,
-                };
-
-                // Try to use the segment resolution if it is valid, otherwise we
-                // default to the path resolution.
-                let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
-                use def::CtorOf;
-                let generics = match res {
-                    Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx.generics_of(
-                        tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap(),
-                    ),
-                    Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
-                        tcx.generics_of(tcx.parent(def_id).unwrap())
-                    }
-                    // Other `DefKind`s don't have generics and would ICE when calling
-                    // `generics_of`.
-                    Res::Def(
-                        DefKind::Struct
-                        | DefKind::Union
-                        | DefKind::Enum
-                        | DefKind::Trait
-                        | DefKind::OpaqueTy
-                        | DefKind::TyAlias
-                        | DefKind::ForeignTy
-                        | DefKind::TraitAlias
-                        | DefKind::AssocTy
-                        | DefKind::Fn
-                        | DefKind::AssocFn
-                        | DefKind::AssocConst
-                        | DefKind::Impl,
-                        def_id,
-                    ) => tcx.generics_of(def_id),
-                    Res::Err => {
-                        tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
-                        return None;
-                    }
-                    _ => {
-                        // If the user tries to specify generics on a type that does not take them,
-                        // e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
-                        // no arguments have been passed. An error should already have been emitted.
+            (tcx.generics_of(type_dependent_def), idx)
+        }
+
+        Node::Ty(&Ty { kind: TyKind::Path(_), .. })
+        | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
+        | Node::TraitRef(..)
+        | Node::Pat(_) => {
+            let path = match parent_node {
+                Node::Ty(&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().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
+                    let _tables = tcx.typeck(body_owner);
+                    &*path
+                }
+                Node::Pat(pat) => {
+                    if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
+                        path
+                    } else {
                         tcx.sess.delay_span_bug(
                             tcx.def_span(def_id),
-                            &format!("unexpected anon const res {:?} in path: {:?}", res, path),
+                            &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
                         );
                         return None;
                     }
-                };
-
-                generics
-                    .params
-                    .iter()
-                    .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. }))
-                    .nth(arg_index)
-                    .map(|param| param.def_id)
+                }
+                _ => {
+                    tcx.sess.delay_span_bug(
+                        tcx.def_span(def_id),
+                        &format!("unexpected const parent path {:?}", parent_node),
+                    );
+                    return None;
+                }
+            };
+
+            // 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 filtered = path
+                .segments
+                .iter()
+                .filter_map(|seg| seg.args.map(|args| (args.args, seg)))
+                .find_map(|(args, seg)| {
+                    args.iter()
+                        .filter(|arg| arg.is_ty_or_const())
+                        .position(|arg| arg.id() == hir_id)
+                        .map(|index| (index, seg))
+                });
+            let (arg_index, segment) = match filtered {
+                None => {
+                    tcx.sess
+                        .delay_span_bug(tcx.def_span(def_id), "no arg matching AnonConst in path");
+                    return None;
+                }
+                Some(inner) => inner,
+            };
+
+            // Try to use the segment resolution if it is valid, otherwise we
+            // default to the path resolution.
+            let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
+            use def::CtorOf;
+            let generics = match res {
+                Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx
+                    .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()),
+                Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
+                    tcx.generics_of(tcx.parent(def_id).unwrap())
+                }
+                // Other `DefKind`s don't have generics and would ICE when calling
+                // `generics_of`.
+                Res::Def(
+                    DefKind::Struct
+                    | DefKind::Union
+                    | DefKind::Enum
+                    | DefKind::Trait
+                    | DefKind::OpaqueTy
+                    | DefKind::TyAlias
+                    | DefKind::ForeignTy
+                    | DefKind::TraitAlias
+                    | DefKind::AssocTy
+                    | DefKind::Fn
+                    | DefKind::AssocFn
+                    | DefKind::AssocConst
+                    | DefKind::Impl,
+                    def_id,
+                ) => tcx.generics_of(def_id),
+                Res::Err => {
+                    tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
+                    return None;
+                }
+                _ => {
+                    // If the user tries to specify generics on a type that does not take them,
+                    // e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
+                    // no arguments have been passed. An error should already have been emitted.
+                    tcx.sess.delay_span_bug(
+                        tcx.def_span(def_id),
+                        &format!("unexpected anon const res {:?} in path: {:?}", res, path),
+                    );
+                    return None;
+                }
+            };
+
+            (generics, arg_index)
+        }
+        _ => return None,
+    };
+
+    debug!(?parent_node);
+    debug!(?generics, ?arg_idx);
+    generics
+        .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,
-        }
-    } else {
-        None
-    }
+        })
 }
 
 fn get_path_containing_arg_in_pat<'hir>(