1use rustc_hir::attrs::lang_items::{self, LangItem};
6use rustc_hir::def::DefKind;
7use rustc_hir::def_id::DefId;
8use rustc_middle::ty::{
9 self, AssocContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv, Unnormalized,
10};
11use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, sym};
12use tracing::debug;
13
14use crate::traits::specialization_graph;
15
16#[derive(#[automatically_derived]
impl ::core::clone::Clone for CallDesugaringKind {
#[inline]
fn clone(&self) -> CallDesugaringKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CallDesugaringKind { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for CallDesugaringKind {
#[inline]
fn eq(&self, other: &CallDesugaringKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for CallDesugaringKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for CallDesugaringKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
CallDesugaringKind::ForLoopIntoIter => "ForLoopIntoIter",
CallDesugaringKind::ForLoopIntoAsyncIter =>
"ForLoopIntoAsyncIter",
CallDesugaringKind::ForLoopNext => "ForLoopNext",
CallDesugaringKind::QuestionBranch => "QuestionBranch",
CallDesugaringKind::QuestionFromResidual =>
"QuestionFromResidual",
CallDesugaringKind::TryBlockFromOutput =>
"TryBlockFromOutput",
CallDesugaringKind::Await => "Await",
})
}
}Debug)]
17pub enum CallDesugaringKind {
18 ForLoopIntoIter,
20 ForLoopIntoAsyncIter,
22 ForLoopNext,
24 QuestionBranch,
26 QuestionFromResidual,
28 TryBlockFromOutput,
30 Await,
32}
33
34impl CallDesugaringKind {
35 pub fn name(&self) -> &'static str {
36 match self {
37 CallDesugaringKind::ForLoopIntoIter => "`for` loop",
38 CallDesugaringKind::ForLoopIntoAsyncIter => "`for await` loop",
39 CallDesugaringKind::ForLoopNext => "`for` loop",
40 CallDesugaringKind::QuestionBranch => "question mark operator",
41 CallDesugaringKind::QuestionFromResidual => "question mark operator",
42 CallDesugaringKind::TryBlockFromOutput => "try block",
43 CallDesugaringKind::Await => "`await`",
44 }
45 }
46
47 pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId {
48 match self {
49 Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(),
50 Self::ForLoopIntoAsyncIter => tcx.get_diagnostic_item(sym::IntoAsyncIterator).unwrap(),
51 Self::ForLoopNext => tcx.require_lang_item(LangItem::Iterator, DUMMY_SP),
52 Self::QuestionBranch | Self::TryBlockFromOutput => {
53 tcx.require_lang_item(LangItem::Try, DUMMY_SP)
54 }
55 Self::QuestionFromResidual => tcx.get_diagnostic_item(sym::FromResidual).unwrap(),
56 Self::Await => tcx.get_diagnostic_item(sym::IntoFuture).unwrap(),
57 }
58 }
59}
60
61#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for CallKind<'tcx> {
#[inline]
fn clone(&self) -> CallKind<'tcx> {
let _: ::core::clone::AssertParamIsClone<Option<Ident>>;
let _:
::core::clone::AssertParamIsClone<Option<(CallDesugaringKind,
Ty<'tcx>)>>;
let _: ::core::clone::AssertParamIsClone<DefId>;
let _: ::core::clone::AssertParamIsClone<GenericArgsRef<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Option<Ident>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Option<Span>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for CallKind<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for CallKind<'tcx> {
#[inline]
fn eq(&self, other: &CallKind<'tcx>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(CallKind::Normal {
self_arg: __self_0,
desugaring: __self_1,
method_did: __self_2,
method_args: __self_3 }, CallKind::Normal {
self_arg: __arg1_0,
desugaring: __arg1_1,
method_did: __arg1_2,
method_args: __arg1_3 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2 && __self_3 == __arg1_3,
(CallKind::FnCall { fn_trait_id: __self_0, self_ty: __self_1
}, CallKind::FnCall {
fn_trait_id: __arg1_0, self_ty: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(CallKind::Operator {
self_arg: __self_0, trait_id: __self_1, self_ty: __self_2 },
CallKind::Operator {
self_arg: __arg1_0, trait_id: __arg1_1, self_ty: __arg1_2 })
=>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(CallKind::DerefCoercion {
deref_target_span: __self_0,
deref_target_ty: __self_1,
self_ty: __self_2 }, CallKind::DerefCoercion {
deref_target_span: __arg1_0,
deref_target_ty: __arg1_1,
self_ty: __arg1_2 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for CallKind<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<Ident>>;
let _:
::core::cmp::AssertParamIsEq<Option<(CallDesugaringKind,
Ty<'tcx>)>>;
let _: ::core::cmp::AssertParamIsEq<DefId>;
let _: ::core::cmp::AssertParamIsEq<GenericArgsRef<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Option<Ident>>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Option<Span>>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for CallKind<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
CallKind::Normal {
self_arg: __self_0,
desugaring: __self_1,
method_did: __self_2,
method_args: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"Normal", "self_arg", __self_0, "desugaring", __self_1,
"method_did", __self_2, "method_args", &__self_3),
CallKind::FnCall { fn_trait_id: __self_0, self_ty: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"FnCall", "fn_trait_id", __self_0, "self_ty", &__self_1),
CallKind::Operator {
self_arg: __self_0, trait_id: __self_1, self_ty: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"Operator", "self_arg", __self_0, "trait_id", __self_1,
"self_ty", &__self_2),
CallKind::DerefCoercion {
deref_target_span: __self_0,
deref_target_ty: __self_1,
self_ty: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"DerefCoercion", "deref_target_span", __self_0,
"deref_target_ty", __self_1, "self_ty", &__self_2),
}
}
}Debug)]
62pub enum CallKind<'tcx> {
63 Normal {
65 self_arg: Option<Ident>,
66 desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
67 method_did: DefId,
68 method_args: GenericArgsRef<'tcx>,
69 },
70 FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
72 Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
74 DerefCoercion {
75 deref_target_span: Option<Span>,
78 deref_target_ty: Ty<'tcx>,
80 self_ty: Ty<'tcx>,
81 },
82}
83
84pub fn call_kind<'tcx>(
85 tcx: TyCtxt<'tcx>,
86 typing_env: TypingEnv<'tcx>,
87 method_did: DefId,
88 method_args: GenericArgsRef<'tcx>,
89 fn_call_span: Span,
90 from_hir_call: bool,
91 self_arg: Option<Ident>,
92) -> CallKind<'tcx> {
93 let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
94 let container_id = assoc.container_id(tcx);
95 match assoc.container {
96 AssocContainer::InherentImpl => None,
97 AssocContainer::TraitImpl(_) => Some(tcx.impl_trait_id(container_id)),
98 AssocContainer::Trait => Some(container_id),
99 }
100 });
101
102 let fn_call = parent.filter(|&p| tcx.fn_trait_kind_from_def_id(p).is_some());
103
104 let operator = if !from_hir_call && let Some(p) = parent {
105 lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
106 } else {
107 None
108 };
109
110 if let Some(trait_id) = fn_call {
114 return CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_args.type_at(0) };
115 } else if let Some(trait_id) = operator {
116 return CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) };
117 } else if !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did) {
118 let deref_target_def_id =
119 tcx.get_diagnostic_item(sym::deref_target).expect("deref method but no deref target");
120 let deref_target_ty = tcx.normalize_erasing_regions(
121 typing_env,
122 Unnormalized::new(Ty::new_projection(
123 tcx,
124 ty::IsRigid::No,
125 deref_target_def_id,
126 method_args,
127 )),
128 );
129 let deref_target_span = if let Ok(Some(instance)) =
130 Instance::try_resolve(tcx, typing_env, method_did, method_args)
131 && let instance_parent_def_id = tcx.parent(instance.def_id())
132 && #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(instance_parent_def_id)
{
DefKind::Impl { .. } => true,
_ => false,
}matches!(tcx.def_kind(instance_parent_def_id), DefKind::Impl { .. })
133 && let Ok(instance) =
134 specialization_graph::assoc_def(tcx, instance_parent_def_id, deref_target_def_id)
135 && instance.is_final()
136 {
137 Some(tcx.def_span(instance.item.def_id))
138 } else {
139 None
140 };
141 return CallKind::DerefCoercion {
142 deref_target_ty,
143 deref_target_span,
144 self_ty: method_args.type_at(0),
145 };
146 }
147
148 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs:149",
"rustc_trait_selection::error_reporting::traits::call_kind",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs"),
::tracing_core::__macro_support::Option::Some(149u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::call_kind"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("method_did")
}> =
::tracing::__macro_support::FieldName::new("method_did");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("fn_call_span")
}> =
::tracing::__macro_support::FieldName::new("fn_call_span");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&method_did)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_call_span)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?method_did, ?fn_call_span);
150 let desugaring = if tcx.is_lang_item(method_did, LangItem::IntoIterIntoIter)
151 && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
152 {
153 Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0)))
154 } else if tcx.is_lang_item(method_did, LangItem::IntoAsyncIterIntoIter)
155 && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
156 {
157 Some((CallDesugaringKind::ForLoopIntoAsyncIter, method_args.type_at(0)))
158 } else if tcx.is_lang_item(method_did, LangItem::IteratorNext)
159 && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
160 {
161 Some((CallDesugaringKind::ForLoopNext, method_args.type_at(0)))
162 } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
163 if tcx.is_lang_item(method_did, LangItem::TryTraitBranch) {
164 Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0)))
165 } else if tcx.is_lang_item(method_did, LangItem::TryTraitFromResidual) {
166 Some((CallDesugaringKind::QuestionFromResidual, method_args.type_at(0)))
167 } else {
168 None
169 }
170 } else if tcx.is_lang_item(method_did, LangItem::TryTraitFromOutput)
171 && fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock)
172 {
173 Some((CallDesugaringKind::TryBlockFromOutput, method_args.type_at(0)))
174 } else if fn_call_span.is_desugaring(DesugaringKind::Await) {
175 Some((CallDesugaringKind::Await, method_args.type_at(0)))
176 } else {
177 None
178 };
179 CallKind::Normal { self_arg, desugaring, method_did, method_args }
180}