about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-09 17:43:02 +0000
committerMichael Goulet <michael@errs.io>2025-01-13 02:20:08 +0000
commit9bf9f5db9b07cf0fa74bc5f2340ef13b6c22a96a (patch)
tree94a6863f6529f9eaed217469ccdb0da11947d7e9 /compiler/rustc_middle
parente7ad3ae331bf2716389c10e01612e201a7f98c8d (diff)
downloadrust-9bf9f5db9b07cf0fa74bc5f2340ef13b6c22a96a.tar.gz
rust-9bf9f5db9b07cf0fa74bc5f2340ef13b6c22a96a.zip
Assert that Instance::try_resolve is only used on body-like things
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs22
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs149
-rw-r--r--compiler/rustc_middle/src/util/mod.rs2
3 files changed, 20 insertions, 153 deletions
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 49b5588e261..e4ded2c30f5 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -5,7 +5,7 @@ use std::path::PathBuf;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
-use rustc_hir::def::Namespace;
+use rustc_hir::def::{CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::FiniteBitSet;
@@ -498,7 +498,8 @@ impl<'tcx> Instance<'tcx> {
 
     /// Resolves a `(def_id, args)` pair to an (optional) instance -- most commonly,
     /// this is used to find the precise code that will run for a trait method invocation,
-    /// if known.
+    /// if known. This should only be used for functions and consts. If you want to
+    /// resolve an associated type, use [`TyCtxt::try_normalize_erasing_regions`].
     ///
     /// Returns `Ok(None)` if we cannot resolve `Instance` to a specific instance.
     /// For example, in a context like this,
@@ -527,6 +528,23 @@ impl<'tcx> Instance<'tcx> {
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
     ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
+        assert_matches!(
+            tcx.def_kind(def_id),
+            DefKind::Fn
+                | DefKind::AssocFn
+                | DefKind::Const
+                | DefKind::AssocConst
+                | DefKind::AnonConst
+                | DefKind::InlineConst
+                | DefKind::Static { .. }
+                | DefKind::Ctor(_, CtorKind::Fn)
+                | DefKind::Closure
+                | DefKind::SyntheticCoroutineBody,
+            "`Instance::try_resolve` should only be used to resolve instances of \
+            functions, statics, and consts; to resolve associated types, use \
+            `try_normalize_erasing_regions`."
+        );
+
         // Rust code can easily create exponentially-long types using only a
         // polynomial recursion depth. Even with the default recursion
         // depth, you can easily get cases that take >2^60 steps to run,
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
deleted file mode 100644
index 0e395331687..00000000000
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-//! Common logic for borrowck use-after-move errors when moved into a `fn(self)`,
-//! as well as errors when attempting to call a non-const function in a const
-//! context.
-
-use rustc_hir::def_id::DefId;
-use rustc_hir::{LangItem, lang_items};
-use rustc_span::{DesugaringKind, Ident, Span, sym};
-use tracing::debug;
-
-use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum CallDesugaringKind {
-    /// for _ in x {} calls x.into_iter()
-    ForLoopIntoIter,
-    /// for _ in x {} calls iter.next()
-    ForLoopNext,
-    /// x? calls x.branch()
-    QuestionBranch,
-    /// x? calls type_of(x)::from_residual()
-    QuestionFromResidual,
-    /// try { ..; x } calls type_of(x)::from_output(x)
-    TryBlockFromOutput,
-    /// `.await` calls `IntoFuture::into_future`
-    Await,
-}
-
-impl CallDesugaringKind {
-    pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId {
-        match self {
-            Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(),
-            Self::ForLoopNext => tcx.require_lang_item(LangItem::Iterator, None),
-            Self::QuestionBranch | Self::TryBlockFromOutput => {
-                tcx.require_lang_item(LangItem::Try, None)
-            }
-            Self::QuestionFromResidual => tcx.get_diagnostic_item(sym::FromResidual).unwrap(),
-            Self::Await => tcx.get_diagnostic_item(sym::IntoFuture).unwrap(),
-        }
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum CallKind<'tcx> {
-    /// A normal method call of the form `receiver.foo(a, b, c)`
-    Normal {
-        self_arg: Option<Ident>,
-        desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
-        method_did: DefId,
-        method_args: GenericArgsRef<'tcx>,
-    },
-    /// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
-    FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
-    /// A call to an operator trait, desugared from operator syntax (e.g. `a << b`)
-    Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
-    DerefCoercion {
-        /// The `Span` of the `Target` associated type
-        /// in the `Deref` impl we are using.
-        deref_target: Span,
-        /// The type `T::Deref` we are dereferencing to
-        deref_target_ty: Ty<'tcx>,
-        self_ty: Ty<'tcx>,
-    },
-}
-
-pub fn call_kind<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    typing_env: TypingEnv<'tcx>,
-    method_did: DefId,
-    method_args: GenericArgsRef<'tcx>,
-    fn_call_span: Span,
-    from_hir_call: bool,
-    self_arg: Option<Ident>,
-) -> CallKind<'tcx> {
-    let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
-        let container_id = assoc.container_id(tcx);
-        match assoc.container {
-            AssocItemContainer::Impl => tcx.trait_id_of_impl(container_id),
-            AssocItemContainer::Trait => Some(container_id),
-        }
-    });
-
-    let fn_call = parent.and_then(|p| {
-        lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
-    });
-
-    let operator = if !from_hir_call && let Some(p) = parent {
-        lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
-    } else {
-        None
-    };
-
-    let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
-
-    // Check for a 'special' use of 'self' -
-    // an FnOnce call, an operator (e.g. `<<`), or a
-    // deref coercion.
-    let kind = if let Some(trait_id) = fn_call {
-        Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_args.type_at(0) })
-    } else if let Some(trait_id) = operator {
-        Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) })
-    } else if is_deref {
-        let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
-            Instance::try_resolve(tcx, typing_env, deref_target, method_args).transpose()
-        });
-        if let Some(Ok(instance)) = deref_target {
-            let deref_target_ty = instance.ty(tcx, typing_env);
-            Some(CallKind::DerefCoercion {
-                deref_target: tcx.def_span(instance.def_id()),
-                deref_target_ty,
-                self_ty: method_args.type_at(0),
-            })
-        } else {
-            None
-        }
-    } else {
-        None
-    };
-
-    kind.unwrap_or_else(|| {
-        // This isn't a 'special' use of `self`
-        debug!(?method_did, ?fn_call_span);
-        let desugaring = if tcx.is_lang_item(method_did, LangItem::IntoIterIntoIter)
-            && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-        {
-            Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0)))
-        } else if tcx.is_lang_item(method_did, LangItem::IteratorNext)
-            && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-        {
-            Some((CallDesugaringKind::ForLoopNext, method_args.type_at(0)))
-        } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
-            if tcx.is_lang_item(method_did, LangItem::TryTraitBranch) {
-                Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0)))
-            } else if tcx.is_lang_item(method_did, LangItem::TryTraitFromResidual) {
-                Some((CallDesugaringKind::QuestionFromResidual, method_args.type_at(0)))
-            } else {
-                None
-            }
-        } else if tcx.is_lang_item(method_did, LangItem::TryTraitFromOutput)
-            && fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock)
-        {
-            Some((CallDesugaringKind::TryBlockFromOutput, method_args.type_at(0)))
-        } else if fn_call_span.is_desugaring(DesugaringKind::Await) {
-            Some((CallDesugaringKind::Await, method_args.type_at(0)))
-        } else {
-            None
-        };
-        CallKind::Normal { self_arg, desugaring, method_did, method_args }
-    })
-}
diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs
index 8dafc422644..097a868191c 100644
--- a/compiler/rustc_middle/src/util/mod.rs
+++ b/compiler/rustc_middle/src/util/mod.rs
@@ -1,9 +1,7 @@
 pub mod bug;
-pub mod call_kind;
 pub mod common;
 pub mod find_self_call;
 
-pub use call_kind::{CallDesugaringKind, CallKind, call_kind};
 pub use find_self_call::find_self_call;
 
 #[derive(Default, Copy, Clone)]