1use rustc_hir::def_id::DefId;
21use rustc_middle::traits::solve::Goal;
22use rustc_middle::ty::relate::combine::{combine_ty_args, super_combine_consts, super_combine_tys};
23use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
24use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
25use rustc_span::{Span, span_bug};
26use tracing::{debug, instrument};
27
28use super::combine::PredicateEmittingRelation;
29use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace};
30use crate::traits::{Obligation, PredicateObligations};
31
32#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for LatticeOpKind { }
#[automatically_derived]
impl ::core::clone::Clone for LatticeOpKind {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for LatticeOpKind { }Copy)]
33pub(crate) enum LatticeOpKind {
34 Glb,
35 Lub,
36}
37
38impl LatticeOpKind {
39 fn invert(self) -> Self {
40 match self {
41 LatticeOpKind::Glb => LatticeOpKind::Lub,
42 LatticeOpKind::Lub => LatticeOpKind::Glb,
43 }
44 }
45}
46
47pub(crate) struct LatticeOp<'infcx, 'tcx> {
49 infcx: &'infcx InferCtxt<'tcx>,
50 trace: TypeTrace<'tcx>,
52 param_env: ty::ParamEnv<'tcx>,
53 kind: LatticeOpKind,
55 obligations: PredicateObligations<'tcx>,
56}
57
58impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> {
59 pub(crate) fn new(
60 infcx: &'infcx InferCtxt<'tcx>,
61 trace: TypeTrace<'tcx>,
62 param_env: ty::ParamEnv<'tcx>,
63 kind: LatticeOpKind,
64 ) -> LatticeOp<'infcx, 'tcx> {
65 LatticeOp { infcx, trace, param_env, kind, obligations: PredicateObligations::new() }
66 }
67
68 pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> {
69 self.obligations
70 }
71}
72
73impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
74 fn cx(&self) -> TyCtxt<'tcx> {
75 self.infcx.tcx
76 }
77
78 fn relate_ty_args(
79 &mut self,
80 a_ty: Ty<'tcx>,
81 b_ty: Ty<'tcx>,
82 def_id: DefId,
83 a_args: ty::GenericArgsRef<'tcx>,
84 b_args: ty::GenericArgsRef<'tcx>,
85 mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
86 ) -> RelateResult<'tcx, Ty<'tcx>> {
87 let variances = self.cx().variances_of(def_id);
88 combine_ty_args(self.infcx, self, a_ty, b_ty, variances, a_args, b_args, |args| mk(args))
89 }
90
91 fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
92 &mut self,
93 variance: ty::Variance,
94 _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
95 a: T,
96 b: T,
97 ) -> RelateResult<'tcx, T> {
98 match variance {
99 ty::Invariant => {
100 self.obligations.extend(
101 self.infcx
102 .at(&self.trace.cause, self.param_env)
103 .eq_trace(DefineOpaqueTypes::Yes, self.trace.clone(), a, b)?
104 .into_obligations(),
105 );
106 Ok(a)
107 }
108 ty::Covariant => self.relate(a, b),
109 ty::Bivariant => Ok(a),
111 ty::Contravariant => {
112 self.kind = self.kind.invert();
113 let res = self.relate(a, b);
114 self.kind = self.kind.invert();
115 res
116 }
117 }
118 }
119
120 {}
#[allow(clippy :: suspicious_else_formatting)]
{
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("tys",
"rustc_infer::infer::relate::lattice",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/7bbda45cb1ec0a378d91959646a8fa904be3192a/compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(121u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
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(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
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: RelateResult<'tcx, Ty<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
if a == b { return Ok(a); }
let infcx = self.infcx;
let a = infcx.shallow_resolve(a);
let b = infcx.shallow_resolve(b);
match (a.kind(), b.kind()) {
(&ty::Infer(TyVar(..)), _) => {
let v = infcx.next_ty_var(self.trace.cause.span);
self.relate_bound(v, b, a)?;
Ok(v)
}
(_, &ty::Infer(TyVar(..))) => {
let v = infcx.next_ty_var(self.trace.cause.span);
self.relate_bound(v, a, b)?;
Ok(v)
}
(&ty::Alias(ty::IsRigid::No, _), _) |
(_, &ty::Alias(ty::IsRigid::No, _)) if
infcx.next_trait_solver() => {
::rustc_span::macros::bug_impl(Some(self.span()),
format_args!("it should not be possible to encounter unnormalized aliases in lattice relation"),
Location::caller());
}
(&ty::Alias(_, ty::AliasTy {
kind: ty::Opaque { def_id: a_def_id }, .. }),
&ty::Alias(_, ty::AliasTy {
kind: ty::Opaque { def_id: b_def_id }, .. })) if
a_def_id == b_def_id =>
super_combine_tys(infcx, self, a, b),
(&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, ..
}), _) |
(_,
&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, ..
})) if def_id.is_local() && !infcx.next_trait_solver() => {
self.register_goals(infcx.handle_opaque_type(a, b,
self.span(), self.param_env())?);
Ok(a)
}
_ => super_combine_tys(infcx, self, a, b),
}
}
}
}#[instrument(skip(self), level = "trace")]
122 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
123 if a == b {
124 return Ok(a);
125 }
126
127 let infcx = self.infcx;
128
129 let a = infcx.shallow_resolve(a);
130 let b = infcx.shallow_resolve(b);
131
132 match (a.kind(), b.kind()) {
133 (&ty::Infer(TyVar(..)), _) => {
152 let v = infcx.next_ty_var(self.trace.cause.span);
153 self.relate_bound(v, b, a)?;
154 Ok(v)
155 }
156 (_, &ty::Infer(TyVar(..))) => {
157 let v = infcx.next_ty_var(self.trace.cause.span);
158 self.relate_bound(v, a, b)?;
159 Ok(v)
160 }
161
162 (&ty::Alias(ty::IsRigid::No, _), _) | (_, &ty::Alias(ty::IsRigid::No, _))
163 if infcx.next_trait_solver() =>
164 {
165 span_bug!(
170 self.span(),
171 "it should not be possible to encounter unnormalized aliases in lattice relation"
172 );
173 }
174
175 (
176 &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }),
177 &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }),
178 ) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b),
179
180 (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _)
181 | (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }))
182 if def_id.is_local() && !infcx.next_trait_solver() =>
183 {
184 self.register_goals(infcx.handle_opaque_type(
185 a,
186 b,
187 self.span(),
188 self.param_env(),
189 )?);
190 Ok(a)
191 }
192
193 _ => super_combine_tys(infcx, self, a, b),
194 }
195 }
196
197 {}
#[allow(clippy :: suspicious_else_formatting)]
{
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("regions",
"rustc_infer::infer::relate::lattice",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/7bbda45cb1ec0a378d91959646a8fa904be3192a/compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(197u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
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(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
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:
RelateResult<'tcx, ty::Region<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let origin =
SubregionOrigin::Subtype(Box::new(self.trace.clone()));
let mut inner = self.infcx.inner.borrow_mut();
let mut constraints = inner.unwrap_region_constraints();
Ok(match self.kind {
LatticeOpKind::Glb =>
constraints.lub_regions(self.cx(), origin, a, b),
LatticeOpKind::Lub =>
constraints.glb_regions(self.cx(), origin, a, b),
})
}
}
}#[instrument(skip(self), level = "trace")]
198 fn regions(
199 &mut self,
200 a: ty::Region<'tcx>,
201 b: ty::Region<'tcx>,
202 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
203 let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone()));
204 let mut inner = self.infcx.inner.borrow_mut();
205 let mut constraints = inner.unwrap_region_constraints();
206 Ok(match self.kind {
207 LatticeOpKind::Glb => constraints.lub_regions(self.cx(), origin, a, b),
209
210 LatticeOpKind::Lub => constraints.glb_regions(self.cx(), origin, a, b),
212 })
213 }
214
215 {}
#[allow(clippy :: suspicious_else_formatting)]
{
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("consts",
"rustc_infer::infer::relate::lattice",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/7bbda45cb1ec0a378d91959646a8fa904be3192a/compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(215u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
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(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
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:
RelateResult<'tcx, ty::Const<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{ super_combine_consts(self.infcx, self, a, b) }
}
}#[instrument(skip(self), level = "trace")]
216 fn consts(
217 &mut self,
218 a: ty::Const<'tcx>,
219 b: ty::Const<'tcx>,
220 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
221 super_combine_consts(self.infcx, self, a, b)
222 }
223
224 fn binders<T>(
225 &mut self,
226 a: ty::Binder<'tcx, T>,
227 b: ty::Binder<'tcx, T>,
228 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
229 where
230 T: Relate<TyCtxt<'tcx>>,
231 {
232 if a == b {
234 return Ok(a);
235 }
236
237 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/7bbda45cb1ec0a378d91959646a8fa904be3192a/compiler/rustc_infer/src/infer/relate/lattice.rs:237",
"rustc_infer::infer::relate::lattice",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/7bbda45cb1ec0a378d91959646a8fa904be3192a/compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(237u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&["message"],
::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!("binders(a={0:?}, b={1:?})",
a, b) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("binders(a={:?}, b={:?})", a, b);
238 if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
239 self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
243 Ok(a)
244 } else {
245 Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
246 }
247 }
248}
249
250impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> {
251 fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
258 let at = self.infcx.at(&self.trace.cause, self.param_env);
259 match self.kind {
260 LatticeOpKind::Glb => {
261 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, a)?.into_obligations());
262 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, b)?.into_obligations());
263 }
264 LatticeOpKind::Lub => {
265 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, a, v)?.into_obligations());
266 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, b, v)?.into_obligations());
267 }
268 }
269 Ok(())
270 }
271}
272
273impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
274 fn span(&self) -> Span {
275 self.trace.span()
276 }
277
278 fn param_env(&self) -> ty::ParamEnv<'tcx> {
279 self.param_env
280 }
281
282 fn register_predicates(
283 &mut self,
284 preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
285 ) {
286 self.obligations.extend(preds.into_iter().map(|pred| {
287 Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
288 }))
289 }
290
291 fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
292 self.obligations.extend(goals.into_iter().map(|goal| {
293 Obligation::new(
294 self.infcx.tcx,
295 self.trace.cause.clone(),
296 goal.param_env,
297 goal.predicate,
298 )
299 }))
300 }
301}