diff options
| author | Michael Goulet <michael@errs.io> | 2025-01-09 17:43:02 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-01-13 02:20:08 +0000 |
| commit | 9bf9f5db9b07cf0fa74bc5f2340ef13b6c22a96a (patch) | |
| tree | 94a6863f6529f9eaed217469ccdb0da11947d7e9 /compiler/rustc_middle | |
| parent | e7ad3ae331bf2716389c10e01612e201a7f98c8d (diff) | |
| download | rust-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.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/util/call_kind.rs | 149 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/util/mod.rs | 2 |
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)] |
