1use core::ops::ControlFlow;
2
3use rustc_abi::{FieldIdx, VariantIdx};
4use rustc_apfloat::Float;
5use rustc_attr_ir::find_attr;
6use rustc_attr_ir::lang_items::LangItem;
7use rustc_data_structures::fx::FxHashSet;
8use rustc_errors::{Diag, msg};
9use rustc_hir as hir;
10use rustc_index::Idx;
11use rustc_infer::infer::TyCtxtInferExt;
12use rustc_infer::traits::Obligation;
13use rustc_middle::mir::interpret::ErrorHandled;
14use rustc_middle::thir::{FieldPat, Pat, PatKind};
15use rustc_middle::ty::consts::ConstExt;
16use rustc_middle::ty::{
17 self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, Unnormalized,
18};
19use rustc_span::def_id::DefId;
20use rustc_span::{DUMMY_SP, Span, span_bug};
21use rustc_trait_selection::error_reporting::traits::ambiguity::{
22 CandidateSource, compute_applicable_impls_for_diagnostics,
23};
24use rustc_trait_selection::traits::ObligationCause;
25use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
26use tracing::{debug, instrument, trace};
27
28use super::PatCtxt;
29use crate::diagnostics::{
30 ConstPatternDependsOnGenericParameter, CouldNotEvalConstPattern, InvalidPattern, NaNPattern,
31 PointerPattern, SuggestEq, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern,
32};
33
34impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
35 {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() || { false }
{
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("const_to_pat",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(42u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("c")
}> =
::tracing::__macro_support::FieldName::new("c");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("id")
}> =
::tracing::__macro_support::FieldName::new("id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("span")
}> =
::tracing::__macro_support::FieldName::new("span");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&c)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let mut convert = ConstToPat::new(self, id, span, c);
match c.kind() {
ty::ConstKind::Alias(_, alias_const) =>
convert.alias_to_pat(alias_const, ty),
ty::ConstKind::Value(value) =>
convert.valtree_to_pat(value),
_ =>
::rustc_span::macros::bug_impl(Some(span),
format_args!("Invalid `ConstKind` for `const_to_pat`: {0:?}",
c), Location::caller()),
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs:42",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(42u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
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(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "debug", skip(self), ret)]
43 pub(super) fn const_to_pat(
44 &self,
45 c: ty::Const<'tcx>,
46 ty: Ty<'tcx>,
47 id: hir::HirId,
48 span: Span,
49 ) -> Box<Pat<'tcx>> {
50 let mut convert = ConstToPat::new(self, id, span, c);
51
52 match c.kind() {
53 ty::ConstKind::Alias(_, alias_const) => convert.alias_to_pat(alias_const, ty),
54 ty::ConstKind::Value(value) => convert.valtree_to_pat(value),
55 _ => span_bug!(span, "Invalid `ConstKind` for `const_to_pat`: {:?}", c),
56 }
57 }
58}
59
60struct ConstToPat<'tcx> {
61 tcx: TyCtxt<'tcx>,
62 typing_env: ty::TypingEnv<'tcx>,
63 span: Span,
64 id: hir::HirId,
65
66 c: ty::Const<'tcx>,
67}
68
69impl<'tcx> ConstToPat<'tcx> {
70 fn new(pat_ctxt: &PatCtxt<'tcx, '_>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
71 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs:71",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(71u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("pat_ctxt.typeck_results.hir_owner")
}> =
::tracing::__macro_support::FieldName::new("pat_ctxt.typeck_results.hir_owner");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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(&pat_ctxt.typeck_results.hir_owner)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(?pat_ctxt.typeck_results.hir_owner);
72 ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c }
73 }
74
75 fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
76 ty.is_structural_eq_shallow(self.tcx)
77 }
78
79 fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
81 if let ty::ConstKind::Alias(_, alias_const) = self.c.kind() {
82 if let ty::AliasConstKind::Projection { def_id }
83 | ty::AliasConstKind::InherentSelf { def_id }
84 | ty::AliasConstKind::InherentImpl { def_id } = alias_const.kind
85 && let Some(def_id) = def_id.as_local()
86 {
87 err.span_context(self.tcx.def_span(self.tcx.local_parent(def_id)));
89 }
90 if let ty::AliasConstKind::Projection { def_id }
91 | ty::AliasConstKind::InherentSelf { def_id }
92 | ty::AliasConstKind::InherentImpl { def_id }
93 | ty::AliasConstKind::Free { def_id } = alias_const.kind
94 {
95 err.span_label(self.tcx.def_span(def_id), rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("constant defined here"))msg!("constant defined here"));
96 }
97 }
98 Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit_err()), extra: None })
99 }
100
101 fn alias_to_pat(&mut self, alias_const: ty::AliasConst<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
102 let typing_env =
110 self.tcx.erase_and_anonymize_regions(self.typing_env).with_codegen_normalized(self.tcx);
111 let alias_const = self.tcx.erase_and_anonymize_regions(alias_const);
112
113 let mk_too_generic_err = || {
114 let mut err = self
115 .tcx
116 .dcx()
117 .create_err(ConstPatternDependsOnGenericParameter { span: self.span });
118 for arg in alias_const.args {
119 if let ty::GenericArgKind::Type(ty) = arg.kind()
120 && let ty::Param(param_ty) = ty.kind()
121 {
122 let def_id = self.tcx.hir_enclosing_body_owner(self.id);
123 let generics = self.tcx.generics_of(def_id);
124 let param = generics.type_param(*param_ty, self.tcx);
125 let span = self.tcx.def_span(param.def_id);
126 err.span_label(span, "constant depends on this generic parameter");
127 if let Some(ident) = self.tcx.def_ident_span(def_id)
128 && self.tcx.sess.source_map().is_multiline(ident.between(span))
129 {
130 err.span_context(ident);
133 }
134 }
135 }
136 return self.mk_err(err, ty);
137 };
138
139 let const_value = if self.tcx.features().gca_const_items()
149 || alias_const.kind.is_direct_const(self.tcx)
150 {
151 let Ok(normalize) = self
152 .tcx
153 .try_normalize_erasing_regions(self.typing_env, Unnormalized::new_wip(self.c))
154 else {
155 let err = self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span });
156 return self.mk_err(err, ty);
157 };
158
159 let ty::ConstKind::Value(value) = normalize.kind() else {
160 let err = self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span });
161 return self.mk_err(err, ty);
162 };
163 value
164 } else {
165 let valtree =
168 match self.tcx.const_eval_resolve_for_typeck(typing_env, alias_const, self.span) {
169 Ok(Ok(c)) => c,
170 Err(ErrorHandled::Reported(_, _)) => {
171 let mut err =
173 self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span });
174 if let ty::ConstKind::Alias(_, alias_const) = self.c.kind()
177 && let ty::AliasConstKind::Projection { .. }
178 | ty::AliasConstKind::InherentSelf { .. }
179 | ty::AliasConstKind::InherentImpl { .. }
180 | ty::AliasConstKind::Free { .. } = alias_const.kind
181 {
182 err.downgrade_to_delayed_bug();
183 }
184 return self.mk_err(err, ty);
185 }
186 Err(ErrorHandled::TooGeneric(_)) => {
187 return mk_too_generic_err();
188 }
189 Ok(Err(bad_ty)) => {
190 let e = match bad_ty.kind() {
192 ty::Adt(def, ..) => {
193 if !def.is_union() {
::core::panicking::panic("assertion failed: def.is_union()")
};assert!(def.is_union());
194 self.tcx.dcx().create_err(UnionPattern { span: self.span })
195 }
196 ty::FnPtr(..) | ty::RawPtr(..) => {
197 self.tcx.dcx().create_err(PointerPattern { span: self.span })
198 }
199 _ => self.tcx.dcx().create_err(InvalidPattern {
200 span: self.span,
201 non_sm_ty: bad_ty,
202 prefix: bad_ty.prefix_string(self.tcx).to_string(),
203 }),
204 };
205 return self.mk_err(e, ty);
206 }
207 };
208
209 ty::Value { ty, valtree }
211 };
212 if const_value.ty.has_param() {
213 return mk_too_generic_err();
214 }
215 let mut thir_pat = self.valtree_to_pat(const_value);
216
217 if !thir_pat.references_error() {
218 if !type_has_partial_eq_impl(self.tcx, typing_env, ty).has_impl {
220 let mut err = self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty });
221 extend_type_not_partial_eq(self.tcx, typing_env, ty, &mut err);
222 return self.mk_err(err, ty);
223 }
224 }
225
226 thir_pat.extra.get_or_insert_default().expanded_const = Some(alias_const.kind);
229 thir_pat
230 }
231
232 fn lower_field_values_to_fieldpats(
233 &self,
234 values: impl Iterator<Item = ty::Value<'tcx>>,
235 ) -> Vec<FieldPat<'tcx>> {
236 values
237 .enumerate()
238 .map(|(index, value)| FieldPat {
239 field: FieldIdx::new(index),
240 pattern: *self.valtree_to_pat(value),
241 })
242 .collect()
243 }
244
245 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("valtree_to_pat",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(246u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Box<Pat<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let span = self.span;
let tcx = self.tcx;
let ty::Value { ty, valtree } = value;
let kind =
match ty.kind() {
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs:258",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(258u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("adt_def")
}> =
::tracing::__macro_support::FieldName::new("adt_def");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value.ty")
}> =
::tracing::__macro_support::FieldName::new("value.ty");
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(&format_args!("ADT type in pattern is not `type_marked_structural`")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&adt_def)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value.ty)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let PartialEqImplStatus {
is_derived,
possibly_inapplicable_structural_partial_eq,
non_blanket_impl,
possibly_inapplicable_derived_partial_eq,
has_impl, .. } =
type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
if possibly_inapplicable_derived_partial_eq && !has_impl {
let mut err =
self.tcx.dcx().create_err(TypeNotPartialEq {
span: self.span,
ty,
});
extend_type_not_partial_eq(self.tcx, self.typing_env, ty,
&mut err);
return self.mk_err(err, ty);
}
let (manual_partialeq_impl_span,
manual_partialeq_impl_note) =
match (possibly_inapplicable_structural_partial_eq,
non_blanket_impl) {
(true, _) => (None, false),
(_, Some(def_id)) if def_id.is_local() && !is_derived => {
(Some(tcx.def_span(def_id)), false)
}
_ => (None, true),
};
let manual_partialeq_impl =
manual_partialeq_impl_note ||
manual_partialeq_impl_span.is_some();
let is_local = adt_def.did().is_local();
let ty_def_span = tcx.def_span(adt_def.did());
let suggestion =
if let Ok(name) =
tcx.sess.source_map().span_to_snippet(self.span) &&
(is_local || manual_partialeq_impl) {
let mut hir_id = self.id;
while let hir::Node::Pat(pat) = tcx.parent_hir_node(hir_id)
{
hir_id = pat.hir_id;
}
match tcx.parent_hir_node(hir_id) {
hir::Node::Arm(hir::Arm { pat, guard: None, .. }) => {
Some(SuggestEq::AddIf {
if_span: pat.span.shrink_to_hi(),
pat_span: self.span,
name,
ty,
manual_partialeq_impl,
})
}
hir::Node::Arm(hir::Arm { guard: Some(guard), .. }) => {
Some(SuggestEq::AddToIf {
span: guard.span.shrink_to_hi(),
pat_span: self.span,
name,
ty,
manual_partialeq_impl,
})
}
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Let(let_expr), span, .. }) => {
if let_expr.pat.span == self.span {
Some(SuggestEq::ReplaceWithEq {
removal: span.until(self.span),
eq: self.span.between(let_expr.init.span),
ty,
manual_partialeq_impl,
})
} else if tcx.sess.edition().at_least_rust_2024() {
Some(SuggestEq::AddToLetChain {
span: span.shrink_to_hi(),
pat_span: self.span,
name,
ty,
manual_partialeq_impl,
})
} else { None }
}
hir::Node::LetStmt(let_stmt) if
let Some(init) = let_stmt.init &&
let Some(els) = let_stmt.els && init.span.ctxt().is_root()
&& els.span.ctxt().is_root() => {
Some(SuggestEq::ReplaceLetElseWithIf {
if_span: let_stmt.span.until(let_stmt.pat.span),
eq: let_stmt.pat.span.between(init.span),
else_span: init.span.between(els.span),
ty,
manual_partialeq_impl,
})
}
_ => None,
}
} else { None };
let err =
TypeNotStructural {
span,
ty,
ty_def_span,
manual_partialeq_impl_span,
manual_partialeq_impl_note,
is_local,
suggestion,
};
return self.mk_err(tcx.dcx().create_err(err), ty);
}
ty::Adt(adt_def, args) if adt_def.is_enum() => {
let (&variant_index, fields) =
valtree.to_branch().split_first().unwrap();
let variant_index =
VariantIdx::from_u32(variant_index.to_leaf().to_u32());
PatKind::Variant {
adt_def: *adt_def,
args,
variant_index,
subpatterns: self.lower_field_values_to_fieldpats(fields.iter().map(|ct|
ct.to_value())),
}
}
ty::Adt(def, _) => {
if !!def.is_union() {
::core::panicking::panic("assertion failed: !def.is_union()")
};
PatKind::Leaf {
subpatterns: self.lower_field_values_to_fieldpats(valtree.to_branch().iter().map(|ct|
ct.to_value())),
}
}
ty::Tuple(_) =>
PatKind::Leaf {
subpatterns: self.lower_field_values_to_fieldpats(valtree.to_branch().iter().map(|ct|
ct.to_value())),
},
ty::Slice(_) =>
PatKind::Slice {
prefix: valtree.to_branch().iter().map(|val|
*self.valtree_to_pat(val.to_value())).collect(),
slice: None,
suffix: Box::new([]),
},
ty::Array(_, _) =>
PatKind::Array {
prefix: valtree.to_branch().iter().map(|val|
*self.valtree_to_pat(val.to_value())).collect(),
slice: None,
suffix: Box::new([]),
},
ty::Str => { PatKind::Constant { value } }
ty::Ref(_, pointee_ty, ..) => {
if pointee_ty.is_str() || pointee_ty.is_slice() ||
pointee_ty.is_sized(tcx, self.typing_env) {
PatKind::Deref {
pin: hir::Pinnedness::Not,
subpattern: self.valtree_to_pat(ty::Value {
ty: *pointee_ty,
valtree,
}),
}
} else {
return self.mk_err(tcx.dcx().create_err(UnsizedPattern {
span,
non_sm_ty: *pointee_ty,
}), ty);
}
}
ty::Float(flt) => {
let v = valtree.to_leaf();
let is_nan =
match flt {
ty::FloatTy::F16 => v.to_f16().is_nan(),
ty::FloatTy::F32 => v.to_f32().is_nan(),
ty::FloatTy::F64 => v.to_f64().is_nan(),
ty::FloatTy::F128 => v.to_f128().is_nan(),
};
if is_nan {
return self.mk_err(tcx.dcx().create_err(NaNPattern {
span,
}), ty);
} else { PatKind::Constant { value } }
}
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_)
| ty::RawPtr(..) => {
PatKind::Constant { value }
}
ty::FnPtr(..) => {
{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Valtree construction would never succeed for FnPtr, so this is unreachable.")));
}
}
_ => {
let err =
InvalidPattern {
span,
non_sm_ty: ty,
prefix: ty.prefix_string(tcx).to_string(),
};
return self.mk_err(tcx.dcx().create_err(err), ty);
}
};
Box::new(Pat { span, ty, kind, extra: None })
}
}
}#[instrument(skip(self), level = "debug")]
247 fn valtree_to_pat(&self, value: ty::Value<'tcx>) -> Box<Pat<'tcx>> {
248 let span = self.span;
249 let tcx = self.tcx;
250 let ty::Value { ty, valtree } = value;
251
252 let kind = match ty.kind() {
253 ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
257 debug!(?adt_def, ?value.ty, "ADT type in pattern is not `type_marked_structural`");
259 let PartialEqImplStatus {
260 is_derived,
261 possibly_inapplicable_structural_partial_eq,
262 non_blanket_impl,
263 possibly_inapplicable_derived_partial_eq,
264 has_impl,
265 ..
266 } = type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
267
268 if possibly_inapplicable_derived_partial_eq && !has_impl {
275 let mut err =
276 self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty });
277 extend_type_not_partial_eq(self.tcx, self.typing_env, ty, &mut err);
278 return self.mk_err(err, ty);
279 }
280
281 let (manual_partialeq_impl_span, manual_partialeq_impl_note) =
282 match (possibly_inapplicable_structural_partial_eq, non_blanket_impl) {
283 (true, _) => (None, false),
284 (_, Some(def_id)) if def_id.is_local() && !is_derived => {
285 (Some(tcx.def_span(def_id)), false)
286 }
287 _ => (None, true),
288 };
289 let manual_partialeq_impl =
290 manual_partialeq_impl_note || manual_partialeq_impl_span.is_some();
291 let is_local = adt_def.did().is_local();
292 let ty_def_span = tcx.def_span(adt_def.did());
293 let suggestion = if let Ok(name) = tcx.sess.source_map().span_to_snippet(self.span)
294 && (is_local || manual_partialeq_impl)
295 {
296 let mut hir_id = self.id;
297 while let hir::Node::Pat(pat) = tcx.parent_hir_node(hir_id) {
298 hir_id = pat.hir_id;
299 }
300 match tcx.parent_hir_node(hir_id) {
301 hir::Node::Arm(hir::Arm { pat, guard: None, .. }) => {
302 Some(SuggestEq::AddIf {
304 if_span: pat.span.shrink_to_hi(),
305 pat_span: self.span,
306 name,
307 ty,
308 manual_partialeq_impl,
309 })
310 }
311 hir::Node::Arm(hir::Arm { guard: Some(guard), .. }) => {
312 Some(SuggestEq::AddToIf {
314 span: guard.span.shrink_to_hi(),
315 pat_span: self.span,
316 name,
317 ty,
318 manual_partialeq_impl,
319 })
320 }
321 hir::Node::Expr(hir::Expr {
322 kind: hir::ExprKind::Let(let_expr),
323 span,
324 ..
325 }) => {
326 if let_expr.pat.span == self.span {
327 Some(SuggestEq::ReplaceWithEq {
329 removal: span.until(self.span),
330 eq: self.span.between(let_expr.init.span),
331 ty,
332 manual_partialeq_impl,
333 })
334 } else if tcx.sess.edition().at_least_rust_2024() {
335 Some(SuggestEq::AddToLetChain {
338 span: span.shrink_to_hi(),
339 pat_span: self.span,
340 name,
341 ty,
342 manual_partialeq_impl,
343 })
344 } else {
345 None
346 }
347 }
348 hir::Node::LetStmt(let_stmt)
349 if let Some(init) = let_stmt.init
350 && let Some(els) = let_stmt.els
351 && init.span.ctxt().is_root()
352 && els.span.ctxt().is_root() =>
353 {
354 Some(SuggestEq::ReplaceLetElseWithIf {
356 if_span: let_stmt.span.until(let_stmt.pat.span),
357 eq: let_stmt.pat.span.between(init.span),
358 else_span: init.span.between(els.span),
359 ty,
360 manual_partialeq_impl,
361 })
362 }
363 _ => None,
364 }
365 } else {
366 None
367 };
368 let err = TypeNotStructural {
369 span,
370 ty,
371 ty_def_span,
372 manual_partialeq_impl_span,
373 manual_partialeq_impl_note,
374 is_local,
375 suggestion,
376 };
377 return self.mk_err(tcx.dcx().create_err(err), ty);
378 }
379 ty::Adt(adt_def, args) if adt_def.is_enum() => {
380 let (&variant_index, fields) = valtree.to_branch().split_first().unwrap();
381 let variant_index = VariantIdx::from_u32(variant_index.to_leaf().to_u32());
382 PatKind::Variant {
383 adt_def: *adt_def,
384 args,
385 variant_index,
386 subpatterns: self
387 .lower_field_values_to_fieldpats(fields.iter().map(|ct| ct.to_value())),
388 }
389 }
390 ty::Adt(def, _) => {
391 assert!(!def.is_union()); PatKind::Leaf {
393 subpatterns: self.lower_field_values_to_fieldpats(
394 valtree.to_branch().iter().map(|ct| ct.to_value()),
395 ),
396 }
397 }
398 ty::Tuple(_) => PatKind::Leaf {
399 subpatterns: self.lower_field_values_to_fieldpats(
400 valtree.to_branch().iter().map(|ct| ct.to_value()),
401 ),
402 },
403 ty::Slice(_) => PatKind::Slice {
404 prefix: valtree
405 .to_branch()
406 .iter()
407 .map(|val| *self.valtree_to_pat(val.to_value()))
408 .collect(),
409 slice: None,
410 suffix: Box::new([]),
411 },
412 ty::Array(_, _) => PatKind::Array {
413 prefix: valtree
414 .to_branch()
415 .iter()
416 .map(|val| *self.valtree_to_pat(val.to_value()))
417 .collect(),
418 slice: None,
419 suffix: Box::new([]),
420 },
421 ty::Str => {
422 PatKind::Constant { value }
430 }
431 ty::Ref(_, pointee_ty, ..) => {
432 if pointee_ty.is_str()
433 || pointee_ty.is_slice()
434 || pointee_ty.is_sized(tcx, self.typing_env)
435 {
436 PatKind::Deref {
437 pin: hir::Pinnedness::Not,
439 subpattern: self.valtree_to_pat(ty::Value { ty: *pointee_ty, valtree }),
443 }
444 } else {
445 return self.mk_err(
446 tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }),
447 ty,
448 );
449 }
450 }
451 ty::Float(flt) => {
452 let v = valtree.to_leaf();
453 let is_nan = match flt {
454 ty::FloatTy::F16 => v.to_f16().is_nan(),
455 ty::FloatTy::F32 => v.to_f32().is_nan(),
456 ty::FloatTy::F64 => v.to_f64().is_nan(),
457 ty::FloatTy::F128 => v.to_f128().is_nan(),
458 };
459 if is_nan {
460 return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty);
463 } else {
464 PatKind::Constant { value }
465 }
466 }
467 ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
468 PatKind::Constant { value }
471 }
472 ty::FnPtr(..) => {
473 unreachable!(
474 "Valtree construction would never succeed for FnPtr, so this is unreachable."
475 )
476 }
477 _ => {
478 let err = InvalidPattern {
479 span,
480 non_sm_ty: ty,
481 prefix: ty.prefix_string(tcx).to_string(),
482 };
483 return self.mk_err(tcx.dcx().create_err(err), ty);
484 }
485 };
486
487 Box::new(Pat { span, ty, kind, extra: None })
488 }
489}
490
491fn extend_type_not_partial_eq<'tcx>(
494 tcx: TyCtxt<'tcx>,
495 typing_env: ty::TypingEnv<'tcx>,
496 ty: Ty<'tcx>,
497 err: &mut Diag<'_>,
498) {
499 struct UsedParamsNeedInstantiationVisitor<'tcx> {
501 tcx: TyCtxt<'tcx>,
502 typing_env: ty::TypingEnv<'tcx>,
503 adts_with_manual_partialeq: FxHashSet<Span>,
505 adts_without_partialeq: FxHashSet<Span>,
507 manual: FxHashSet<Ty<'tcx>>,
510 without: FxHashSet<Ty<'tcx>>,
513 }
514
515 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
516 type Result = ControlFlow<()>;
517 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
518 match ty.kind() {
519 ty::Dynamic(..) => return ControlFlow::Break(()),
520 ty::UnsafeBinder(..) => return ControlFlow::Break(()),
523 ty::FnPtr(..) => return ControlFlow::Continue(()),
524 ty::Adt(def, _args) => {
525 let ty_def_id = def.did();
526 let ty_def_span = self.tcx.def_span(ty_def_id);
527 let PartialEqImplStatus {
528 has_impl,
529 is_derived,
530 possibly_inapplicable_structural_partial_eq: structural_partial_eq,
531 non_blanket_impl,
532 possibly_inapplicable_derived_partial_eq: _,
533 } = type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
534 match (has_impl, is_derived, structural_partial_eq, non_blanket_impl) {
535 (_, _, true, _) => {}
536 (true, false, _, Some(def_id)) if def_id.is_local() => {
537 self.adts_with_manual_partialeq.insert(self.tcx.def_span(def_id));
538 }
539 (true, false, _, _) if ty_def_id.is_local() => {
540 self.adts_with_manual_partialeq.insert(ty_def_span);
541 }
542 (false, _, _, _) if ty_def_id.is_local() => {
543 self.adts_without_partialeq.insert(ty_def_span);
544 }
545 (true, false, _, _) => {
546 self.manual.insert(ty);
547 }
548 (false, _, _, _) => {
549 self.without.insert(ty);
550 }
551 _ => {}
552 };
553 ty.super_visit_with(self)
554 }
555 _ => ty.super_visit_with(self),
556 }
557 }
558 }
559 let mut v = UsedParamsNeedInstantiationVisitor {
560 tcx,
561 typing_env,
562 adts_with_manual_partialeq: FxHashSet::default(),
563 adts_without_partialeq: FxHashSet::default(),
564 manual: FxHashSet::default(),
565 without: FxHashSet::default(),
566 };
567 if v.visit_ty(ty).is_break() {
568 return;
569 }
570 #[allow(rustc::potential_query_instability)] for span in v.adts_with_manual_partialeq {
572 err.span_note(span, "the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details");
573 }
574 #[allow(rustc::potential_query_instability)] for span in v.adts_without_partialeq {
576 err.span_label(
577 span,
578 "must be annotated with `#[derive(PartialEq)]` to be usable in patterns",
579 );
580 }
581 #[allow(rustc::potential_query_instability)]
582 let mut manual: Vec<_> = v.manual.into_iter().map(|t| t.to_string()).collect();
583 manual.sort();
584 for ty in manual {
585 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details",
ty))
})format!(
586 "`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details"
587 ));
588 }
589 #[allow(rustc::potential_query_instability)]
590 let mut without: Vec<_> = v.without.into_iter().map(|t| t.to_string()).collect();
591 without.sort();
592 for ty in without {
593 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns",
ty))
})format!(
594 "`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns"
595 ));
596 }
597}
598
599#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PartialEqImplStatus {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"PartialEqImplStatus", "has_impl", &self.has_impl, "is_derived",
&self.is_derived, "non_blanket_impl", &self.non_blanket_impl,
"possibly_inapplicable_structural_partial_eq",
&self.possibly_inapplicable_structural_partial_eq,
"possibly_inapplicable_derived_partial_eq",
&&self.possibly_inapplicable_derived_partial_eq)
}
}Debug)]
600struct PartialEqImplStatus {
601 has_impl: bool,
603
604 is_derived: bool,
606 non_blanket_impl: Option<DefId>,
608
609 possibly_inapplicable_structural_partial_eq: bool,
612 possibly_inapplicable_derived_partial_eq: bool,
615}
616
617{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() || { false }
{
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("type_has_partial_eq_impl",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(617u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("typing_env")
}> =
::tracing::__macro_support::FieldName::new("typing_env");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&typing_env)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: PartialEqImplStatus =
loop {};
return __tracing_attr_fake_return;
}
{
let (infcx, param_env) =
tcx.infer_ctxt().build_with_typing_env(typing_env);
let partial_eq_trait_id =
tcx.require_lang_item(LangItem::PartialEq, DUMMY_SP);
let structural_partial_eq_trait_id =
tcx.require_lang_item(LangItem::StructuralPeq, DUMMY_SP);
let has_impl =
{
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env,
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]));
infcx.predicate_must_hold_modulo_regions(&obligation)
};
let possibly_inapplicable_derived_partial_eq =
{
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env,
ty::Binder::dummy(ty::TraitRef::new(tcx,
partial_eq_trait_id, [ty, ty])));
compute_applicable_impls_for_diagnostics(&infcx,
&obligation,
true).iter().any(|candidate_source|
{
#[allow(non_exhaustive_omitted_patterns)]
match candidate_source {
&CandidateSource::DefId(def_id) if
{
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx)
{
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(AutomaticallyDerived) =>
{
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some() => true,
_ => false,
}
})
};
let possibly_inapplicable_structural_partial_eq =
{
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env,
ty::Binder::dummy(ty::TraitRef::new(tcx,
structural_partial_eq_trait_id, [ty])));
compute_applicable_impls_for_diagnostics(&infcx,
&obligation,
true).iter().any(|candidate_source|
#[allow(non_exhaustive_omitted_patterns)] match candidate_source
{
CandidateSource::DefId(_) => true,
_ => false,
})
};
let mut automatically_derived = false;
let mut impl_def_id = None;
for def_id in
tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) {
automatically_derived =
{
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx)
{
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(AutomaticallyDerived) =>
{
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some();
impl_def_id = Some(def_id);
}
PartialEqImplStatus {
has_impl,
is_derived: automatically_derived,
possibly_inapplicable_structural_partial_eq,
non_blanket_impl: impl_def_id,
possibly_inapplicable_derived_partial_eq,
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs:617",
"rustc_mir_build::thir::pattern::const_to_pat",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/1d81eb4ad9cd207e3e638bd32b17ec4fce8412a6/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs"),
::tracing_core::__macro_support::Option::Some(617u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_build::thir::pattern::const_to_pat"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "trace", skip(tcx), ret)]
618fn type_has_partial_eq_impl<'tcx>(
619 tcx: TyCtxt<'tcx>,
620 typing_env: ty::TypingEnv<'tcx>,
621 ty: Ty<'tcx>,
622) -> PartialEqImplStatus {
623 let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
624 let partial_eq_trait_id = tcx.require_lang_item(LangItem::PartialEq, DUMMY_SP);
630 let structural_partial_eq_trait_id = tcx.require_lang_item(LangItem::StructuralPeq, DUMMY_SP);
631
632 let has_impl = {
643 let obligation = Obligation::new(
644 tcx,
645 ObligationCause::dummy(),
646 param_env,
647 ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
648 );
649 infcx.predicate_must_hold_modulo_regions(&obligation)
650 };
651
652 let possibly_inapplicable_derived_partial_eq = {
655 let obligation = Obligation::new(
656 tcx,
657 ObligationCause::dummy(),
658 param_env,
659 ty::Binder::dummy(ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty])),
660 );
661 compute_applicable_impls_for_diagnostics(&infcx, &obligation, true).iter().any(
662 |candidate_source| {
663 matches!(
664 candidate_source,
665 &CandidateSource::DefId(def_id)
666 if find_attr!(tcx, def_id, AutomaticallyDerived)
667 )
668 },
669 )
670 };
671
672 let possibly_inapplicable_structural_partial_eq = {
673 let obligation = Obligation::new(
674 tcx,
675 ObligationCause::dummy(),
676 param_env,
677 ty::Binder::dummy(ty::TraitRef::new(tcx, structural_partial_eq_trait_id, [ty])),
678 );
679 compute_applicable_impls_for_diagnostics(&infcx, &obligation, true)
680 .iter()
681 .any(|candidate_source| matches!(candidate_source, CandidateSource::DefId(_)))
682 };
683
684 let mut automatically_derived = false;
685 let mut impl_def_id = None;
686 for def_id in tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) {
687 automatically_derived = find_attr!(tcx, def_id, AutomaticallyDerived);
688 impl_def_id = Some(def_id);
689 }
690
691 PartialEqImplStatus {
692 has_impl,
693 is_derived: automatically_derived,
694 possibly_inapplicable_structural_partial_eq,
695 non_blanket_impl: impl_def_id,
696 possibly_inapplicable_derived_partial_eq,
697 }
698}