1use std::mem;
23use rustc_data_structures::sso::SsoHashMap;
4use rustc_data_structures::stack::ensure_sufficient_stack;
5use rustc_hir::def_id::DefId;
6use rustc_middle::bug;
7use rustc_middle::ty::error::TypeError;
8use rustc_middle::ty::{
9self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
10TypeVisitableExt, TypeVisitor,
11};
12use rustc_span::Span;
13use tracing::{debug, instrument, warn};
1415use super::{
16PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
17};
18use crate::infer::type_variable::TypeVariableValue;
19use crate::infer::unify_key::ConstVariableValue;
20use crate::infer::{InferCtxt, RegionVariableOrigin, relate};
2122#[derive(#[automatically_derived]
impl ::core::marker::Copy for TermVid { }Copy, #[automatically_derived]
impl ::core::clone::Clone for TermVid {
#[inline]
fn clone(&self) -> TermVid {
let _: ::core::clone::AssertParamIsClone<ty::TyVid>;
let _: ::core::clone::AssertParamIsClone<ty::ConstVid>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for TermVid {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<ty::TyVid>;
let _: ::core::cmp::AssertParamIsEq<ty::ConstVid>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for TermVid {
#[inline]
fn eq(&self, other: &TermVid) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(TermVid::Ty(__self_0), TermVid::Ty(__arg1_0)) =>
__self_0 == __arg1_0,
(TermVid::Const(__self_0), TermVid::Const(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for TermVid {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
TermVid::Ty(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ty",
&__self_0),
TermVid::Const(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Const",
&__self_0),
}
}
}Debug)]
23enum TermVid {
24 Ty(ty::TyVid),
25 Const(ty::ConstVid),
26}
2728impl From<ty::TyVid> for TermVid {
29fn from(value: ty::TyVid) -> Self {
30 TermVid::Ty(value)
31 }
32}
3334impl From<ty::ConstVid> for TermVid {
35fn from(value: ty::ConstVid) -> Self {
36 TermVid::Const(value)
37 }
38}
3940impl<'tcx> InferCtxt<'tcx> {
41/// The idea is that we should ensure that the type variable `target_vid`
42 /// is equal to, a subtype of, or a supertype of `source_ty`.
43 ///
44 /// For this, we will instantiate `target_vid` with a *generalized* version
45 /// of `source_ty`. Generalization introduces other inference variables wherever
46 /// subtyping could occur. This also does the occurs checks, detecting whether
47 /// instantiating `target_vid` would result in a cyclic type. We eagerly error
48 /// in this case.
49 ///
50 /// This is *not* expected to be used anywhere except for an implementation of
51 /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
52 /// other usecases (i.e. setting the value of a type var).
53#[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("instantiate_ty_var",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(53u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["target_is_expected",
"target_vid", "instantiation_variance", "source_ty"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&target_is_expected
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiation_variance)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_ty)
as &dyn 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, ()> = loop {};
return __tracing_attr_fake_return;
}
{
if true {
if !self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()
{
::core::panicking::panic("assertion failed: self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()")
};
};
self.instantiate_var(relation, target_is_expected,
target_vid.into(), instantiation_variance, source_ty.into())
}
}
}#[instrument(level = "debug", skip(self, relation))]54pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
55&self,
56 relation: &mut R,
57 target_is_expected: bool,
58 target_vid: ty::TyVid,
59 instantiation_variance: ty::Variance,
60 source_ty: Ty<'tcx>,
61 ) -> RelateResult<'tcx, ()> {
62debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
6364self.instantiate_var(
65 relation,
66 target_is_expected,
67 target_vid.into(),
68 instantiation_variance,
69 source_ty.into(),
70 )
71 }
7273/// Instantiates the const variable `target_vid` with the given constant.
74 ///
75 /// This also tests if the given const `ct` contains an inference variable which was previously
76 /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct`
77 /// would result in an infinite type as we continuously replace an inference variable
78 /// in `ct` with `ct` itself.
79 ///
80 /// This is especially important as unevaluated consts use their parents generics.
81 /// They therefore often contain unused args, making these errors far more likely.
82 ///
83 /// A good example of this is the following:
84 ///
85 /// ```compile_fail,E0308
86 /// #![feature(generic_const_exprs)]
87 ///
88 /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
89 /// todo!()
90 /// }
91 ///
92 /// fn main() {
93 /// let mut arr = Default::default();
94 /// arr = bind(arr);
95 /// }
96 /// ```
97 ///
98 /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics
99 /// of `fn bind` (meaning that its args contain `N`).
100 ///
101 /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
102 /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
103 ///
104 /// As `3 + 4` contains `N` in its args, this must not succeed.
105 ///
106 /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
107#[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("instantiate_const_var",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(107u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["target_is_expected",
"target_vid", "source_ct"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&target_is_expected
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_ct)
as &dyn 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, ()> = loop {};
return __tracing_attr_fake_return;
}
{
if true {
if !self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
{
::core::panicking::panic("assertion failed: self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()")
};
};
self.instantiate_var(relation, target_is_expected,
target_vid.into(), ty::Invariant, source_ct.into())
}
}
}#[instrument(level = "debug", skip(self, relation))]108pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
109&self,
110 relation: &mut R,
111 target_is_expected: bool,
112 target_vid: ty::ConstVid,
113 source_ct: ty::Const<'tcx>,
114 ) -> RelateResult<'tcx, ()> {
115// FIXME(generic_const_exprs): Occurs check failures for unevaluated
116 // constants and generic expressions are not yet handled correctly.
117debug_assert!(
118self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
119 );
120121self.instantiate_var(
122 relation,
123 target_is_expected,
124 target_vid.into(),
125 ty::Invariant,
126 source_ct.into(),
127 )
128 }
129130#[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("instantiate_var",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(130u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["target_is_expected",
"target_vid", "instantiation_variance", "source_term"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&target_is_expected
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiation_variance)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_term)
as &dyn 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, ()> = loop {};
return __tracing_attr_fake_return;
}
{
let Generalization { value_may_be_infer: generalized_term } =
self.generalize(relation.span(),
relation.structurally_relate_aliases(), target_vid,
instantiation_variance, source_term)?;
self.union_var_term(target_vid, generalized_term);
if generalized_term.is_infer() {
if self.next_trait_solver() {
let (lhs, rhs, direction) =
match instantiation_variance {
ty::Invariant => {
(generalized_term, source_term,
AliasRelationDirection::Equate)
}
ty::Covariant => {
(generalized_term, source_term,
AliasRelationDirection::Subtype)
}
ty::Contravariant => {
(source_term, generalized_term,
AliasRelationDirection::Subtype)
}
ty::Bivariant => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("bivariant generalization")));
}
};
relation.register_predicates([ty::PredicateKind::AliasRelate(lhs,
rhs, direction)]);
} else {
let Some(source_alias) =
source_term.to_alias_term(self.tcx) else {
::rustc_middle::util::bug::bug_fmt(format_args!("generalized `{0:?} to infer, not an alias",
source_term));
};
match source_alias.kind(self.tcx) {
ty::AliasTermKind::ProjectionTy { .. } |
ty::AliasTermKind::ProjectionConst { .. } => {
relation.register_predicates([ty::ProjectionPredicate {
projection_term: source_alias,
term: generalized_term,
}]);
}
ty::AliasTermKind::InherentTy { .. } |
ty::AliasTermKind::FreeTy { .. } |
ty::AliasTermKind::OpaqueTy { .. } => {
return Err(TypeError::CyclicTy(source_term.expect_type()));
}
ty::AliasTermKind::InherentConst { .. } |
ty::AliasTermKind::FreeConst { .. } |
ty::AliasTermKind::UnevaluatedConst { .. } => {
return Err(TypeError::CyclicConst(source_term.expect_const()));
}
}
}
} else {
match generalized_term.kind() {
ty::TermKind::Ty(_) => {
if target_is_expected {
relation.relate(generalized_term, source_term)?;
} else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/generalize.rs:238",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(238u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("flip relation")
as &dyn Value))])
});
} else { ; }
};
relation.relate(source_term, generalized_term)?;
}
}
ty::TermKind::Const(_) => {
if target_is_expected {
relation.relate_with_variance(ty::Invariant,
ty::VarianceDiagInfo::default(), generalized_term,
source_term)?;
} else {
relation.relate_with_variance(ty::Invariant,
ty::VarianceDiagInfo::default(), source_term,
generalized_term)?;
}
}
}
}
Ok(())
}
}
}#[instrument(level = "debug", skip(self, relation))]131fn instantiate_var<R: PredicateEmittingRelation<Self>>(
132&self,
133 relation: &mut R,
134 target_is_expected: bool,
135 target_vid: TermVid,
136 instantiation_variance: ty::Variance,
137 source_term: Term<'tcx>,
138 ) -> RelateResult<'tcx, ()> {
139// Generalize `source_term` depending on the current variance. As an example, assume
140 // `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
141 // variable.
142 //
143 // Then the `generalized_term` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
144 // region/type inference variables.
145 //
146 // We then relate `generalized_term <: source_term`, adding constraints like `'x: '?2` and
147 // `?1 <: ?3`.
148let Generalization { value_may_be_infer: generalized_term } = self.generalize(
149 relation.span(),
150 relation.structurally_relate_aliases(),
151 target_vid,
152 instantiation_variance,
153 source_term,
154 )?;
155156// Constrain `b_vid` to the generalized type `generalized_term`.
157self.union_var_term(target_vid, generalized_term);
158159// Finally, relate `generalized_term` to `source_term`, as described in previous comment.
160 //
161 // FIXME(#16847): This code is non-ideal because all these subtype
162 // relations wind up attributed to the same spans. We need
163 // to associate causes/spans with each of the relations in
164 // the stack to get this right.
165if generalized_term.is_infer() {
166// This happens for cases like `<?0 as Trait>::Assoc == ?0`.
167 // We can't instantiate `?0` here as that would result in a
168 // cyclic type. We instead delay the unification in case
169 // the alias can be normalized to something which does not
170 // mention `?0`.
171if self.next_trait_solver() {
172let (lhs, rhs, direction) = match instantiation_variance {
173 ty::Invariant => {
174 (generalized_term, source_term, AliasRelationDirection::Equate)
175 }
176 ty::Covariant => {
177 (generalized_term, source_term, AliasRelationDirection::Subtype)
178 }
179 ty::Contravariant => {
180 (source_term, generalized_term, AliasRelationDirection::Subtype)
181 }
182 ty::Bivariant => unreachable!("bivariant generalization"),
183 };
184185 relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
186 } else {
187let Some(source_alias) = source_term.to_alias_term(self.tcx) else {
188bug!("generalized `{source_term:?} to infer, not an alias");
189 };
190match source_alias.kind(self.tcx) {
191 ty::AliasTermKind::ProjectionTy { .. }
192 | ty::AliasTermKind::ProjectionConst { .. } => {
193// FIXME: This does not handle subtyping correctly, we could
194 // instead create a new inference variable `?normalized_source`, emitting
195 // `Projection(normalized_source, ?ty_normalized)` and
196 // `?normalized_source <: generalized_term`.
197relation.register_predicates([ty::ProjectionPredicate {
198 projection_term: source_alias,
199 term: generalized_term,
200 }]);
201 }
202// The old solver only accepts projection predicates for associated types.
203ty::AliasTermKind::InherentTy { .. }
204 | ty::AliasTermKind::FreeTy { .. }
205 | ty::AliasTermKind::OpaqueTy { .. } => {
206return Err(TypeError::CyclicTy(source_term.expect_type()));
207 }
208 ty::AliasTermKind::InherentConst { .. }
209 | ty::AliasTermKind::FreeConst { .. }
210 | ty::AliasTermKind::UnevaluatedConst { .. } => {
211return Err(TypeError::CyclicConst(source_term.expect_const()));
212 }
213 }
214 }
215 } else {
216// NOTE: The `instantiation_variance` is not the same variance as
217 // used by the relation. When instantiating `b`, `target_is_expected`
218 // is flipped and the `instantiation_variance` is also flipped. To
219 // constrain the `generalized_term` while using the original relation,
220 // we therefore only have to flip the arguments.
221 //
222 // ```ignore (not code)
223 // ?a rel B
224 // instantiate_ty_var(?a, B) # expected and variance not flipped
225 // B' rel B
226 // ```
227 // or
228 // ```ignore (not code)
229 // A rel ?b
230 // instantiate_ty_var(?b, A) # expected and variance flipped
231 // A rel A'
232 // ```
233match generalized_term.kind() {
234 ty::TermKind::Ty(_) => {
235if target_is_expected {
236 relation.relate(generalized_term, source_term)?;
237 } else {
238debug!("flip relation");
239 relation.relate(source_term, generalized_term)?;
240 }
241 }
242 ty::TermKind::Const(_) => {
243// Override consts to always be invariant
244if target_is_expected {
245 relation.relate_with_variance(
246 ty::Invariant,
247 ty::VarianceDiagInfo::default(),
248 generalized_term,
249 source_term,
250 )?;
251 } else {
252 relation.relate_with_variance(
253 ty::Invariant,
254 ty::VarianceDiagInfo::default(),
255 source_term,
256 generalized_term,
257 )?;
258 }
259 }
260 }
261 }
262263Ok(())
264 }
265266/// This is a thin wrapper around inserting into the var tables. You probably want
267 /// [`Self::instantiate_var`] instead, which calls this method.
268fn union_var_term(&self, l: TermVid, r: ty::Term<'tcx>) {
269match (l, r.kind()) {
270 (TermVid::Ty(l), ty::TermKind::Ty(r)) => {
271if let Some(r) = r.ty_vid() {
272self.inner.borrow_mut().type_variables().equate(l, r)
273 } else {
274self.inner.borrow_mut().type_variables().instantiate(l, r)
275 }
276 }
277 (TermVid::Const(l), ty::TermKind::Const(r)) => {
278if let Some(r) = r.ct_vid() {
279self.inner.borrow_mut().const_unification_table().union(l, r)
280 } else {
281self.inner
282 .borrow_mut()
283 .const_unification_table()
284 .union_value(l, ConstVariableValue::Known { value: r })
285 }
286 }
287_ => ::rustc_middle::util::bug::bug_fmt(format_args!("mismatched term kinds in generalize: {0:?}, {1:?}",
l, r))bug!("mismatched term kinds in generalize: {l:?}, {r:?}"),
288 }
289 }
290291/// Attempts to generalize `source_term` for the type variable `target_vid`.
292 /// This checks for cycles -- that is, whether `source_term` references `target_vid`.
293fn generalize(
294&self,
295 span: Span,
296 structurally_relate_aliases: StructurallyRelateAliases,
297 target_vid: TermVid,
298 ambient_variance: ty::Variance,
299 source_term: Term<'tcx>,
300 ) -> RelateResult<'tcx, Generalization<Term<'tcx>>> {
301if !!source_term.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source_term.has_escaping_bound_vars()")
};assert!(!source_term.has_escaping_bound_vars());
302let (for_universe, root_vid) = match target_vid {
303 TermVid::Ty(ty_vid) => {
304 (self.try_resolve_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid)))
305 }
306 TermVid::Const(ct_vid) => (
307self.try_resolve_const_var(ct_vid).unwrap_err(),
308 TermVid::Const(self.inner.borrow_mut().const_unification_table().find(ct_vid).vid),
309 ),
310 };
311312let mut generalizer = Generalizer {
313 infcx: self,
314span,
315structurally_relate_aliases,
316root_vid,
317for_universe,
318 root_term: source_term,
319ambient_variance,
320 in_alias: false,
321 cache: Default::default(),
322 };
323324let value_may_be_infer = generalizer.relate(source_term, source_term)?;
325Ok(Generalization { value_may_be_infer })
326 }
327}
328329/// Finds the max universe present
330struct MaxUniverse {
331 max_universe: ty::UniverseIndex,
332}
333334impl MaxUniverse {
335fn new() -> Self {
336MaxUniverse { max_universe: ty::UniverseIndex::ROOT }
337 }
338339fn max_universe(self) -> ty::UniverseIndex {
340self.max_universe
341 }
342}
343344impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
345fn visit_ty(&mut self, t: Ty<'tcx>) {
346if let ty::Placeholder(placeholder) = t.kind() {
347self.max_universe = self.max_universe.max(placeholder.universe);
348 }
349350t.super_visit_with(self)
351 }
352353fn visit_const(&mut self, c: ty::Const<'tcx>) {
354if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
355self.max_universe = self.max_universe.max(placeholder.universe);
356 }
357358c.super_visit_with(self)
359 }
360361fn visit_region(&mut self, r: ty::Region<'tcx>) {
362if let ty::RePlaceholder(placeholder) = r.kind() {
363self.max_universe = self.max_universe.max(placeholder.universe);
364 }
365 }
366}
367368/// The "generalizer" is used when handling inference variables.
369///
370/// The basic strategy for handling a constraint like `?A <: B` is to
371/// apply a "generalization strategy" to the term `B` -- this replaces
372/// all the lifetimes in the term `B` with fresh inference variables.
373/// (You can read more about the strategy in this [blog post].)
374///
375/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
376/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
377/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
378/// establishes `'0: 'x` as a constraint.
379///
380/// [blog post]: https://is.gd/0hKvIr
381struct Generalizer<'me, 'tcx> {
382 infcx: &'me InferCtxt<'tcx>,
383384 span: Span,
385386/// Whether aliases should be related structurally. If not, we have to
387 /// be careful when generalizing aliases.
388structurally_relate_aliases: StructurallyRelateAliases,
389390/// The vid of the type variable that is in the process of being
391 /// instantiated. If we find this within the value we are folding,
392 /// that means we would have created a cyclic value.
393root_vid: TermVid,
394395/// The universe of the type variable that is in the process of being
396 /// instantiated. If we find anything that this universe cannot name,
397 /// we reject the relation.
398for_universe: ty::UniverseIndex,
399400/// The root term (const or type) we're generalizing. Used for cycle errors.
401root_term: Term<'tcx>,
402403/// After we generalize this type, we are going to relate it to
404 /// some other type. What will be the variance at this point?
405ambient_variance: ty::Variance,
406407/// This is set once we're generalizing the arguments of an alias.
408 ///
409 /// This is necessary to correctly handle
410 /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
411 /// hold by either normalizing the outer or the inner associated type.
412in_alias: bool,
413414 cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
415}
416417impl<'tcx> Generalizer<'_, 'tcx> {
418/// Create an error that corresponds to the term kind in `root_term`
419fn cyclic_term_error(&self) -> TypeError<'tcx> {
420match self.root_term.kind() {
421 ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
422 ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
423 }
424 }
425426/// Create a new type variable in the universe of the target when
427 /// generalizing an alias.
428fn next_var_for_alias_of_kind(&self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> {
429if alias.kind(self.cx()).is_type() {
430self.infcx.next_ty_var_in_universe(self.span, self.for_universe).into()
431 } else {
432self.infcx.next_const_var_in_universe(self.span, self.for_universe).into()
433 }
434 }
435436/// An occurs check failure inside of an alias does not mean
437 /// that the types definitely don't unify. We may be able
438 /// to normalize the alias after all.
439 ///
440 /// We handle this by lazily equating the alias and generalizing
441 /// it to an inference variable. In the new solver, we always
442 /// generalize to an infer var unless the alias contains escaping
443 /// bound variables.
444 ///
445 /// Correctly handling aliases with escaping bound variables is
446 /// difficult and currently incomplete in two opposite ways:
447 /// - if we get an occurs check failure in the alias, replace it with a new infer var.
448 /// This causes us to later emit an alias-relate goal and is incomplete in case the
449 /// alias normalizes to type containing one of the bound variables.
450 /// - if the alias contains an inference variable not nameable by `for_universe`, we
451 /// continue generalizing the alias. This ends up pulling down the universe of the
452 /// inference variable and is incomplete in case the alias would normalize to a type
453 /// which does not mention that inference variable.
454fn generalize_alias_term(
455&mut self,
456 alias: ty::AliasTerm<'tcx>,
457 ) -> Result<Term<'tcx>, TypeError<'tcx>> {
458// We do not eagerly replace aliases with inference variables if they have
459 // escaping bound vars, see the method comment for details. However, when we
460 // are inside of an alias with escaping bound vars replacing nested aliases
461 // with inference variables can cause incorrect ambiguity.
462 //
463 // cc trait-system-refactor-initiative#110
464if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
465return Ok(self.next_var_for_alias_of_kind(alias));
466 }
467468let is_nested_alias = mem::replace(&mut self.in_alias, true);
469let result = match self.relate(alias, alias) {
470Ok(alias) => Ok(alias.to_term(self.cx())),
471Err(e) => {
472if is_nested_alias {
473return Err(e);
474 } else {
475let mut visitor = MaxUniverse::new();
476alias.visit_with(&mut visitor);
477let infer_replacement_is_complete =
478self.for_universe.can_name(visitor.max_universe())
479 && !alias.has_escaping_bound_vars();
480if !infer_replacement_is_complete {
481{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/generalize.rs:481",
"rustc_infer::infer::relate::generalize",
::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(481u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("may incompletely handle alias type: {0:?}",
alias) as &dyn Value))])
});
} else { ; }
};warn!("may incompletely handle alias type: {alias:?}");
482 }
483484{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/generalize.rs:484",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(484u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("generalization failure in alias")
as &dyn Value))])
});
} else { ; }
};debug!("generalization failure in alias");
485Ok(self.next_var_for_alias_of_kind(alias))
486 }
487 }
488 };
489self.in_alias = is_nested_alias;
490result491 }
492}
493494impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
495fn cx(&self) -> TyCtxt<'tcx> {
496self.infcx.tcx
497 }
498499fn relate_ty_args(
500&mut self,
501 a_ty: Ty<'tcx>,
502_: Ty<'tcx>,
503 def_id: DefId,
504 a_args: ty::GenericArgsRef<'tcx>,
505 b_args: ty::GenericArgsRef<'tcx>,
506 mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
507 ) -> RelateResult<'tcx, Ty<'tcx>> {
508let args = if self.ambient_variance == ty::Invariant {
509// Avoid fetching the variance if we are in an invariant
510 // context; no need, and it can induce dependency cycles
511 // (e.g., #41849).
512relate::relate_args_invariantly(self, a_args, b_args)
513 } else {
514let tcx = self.cx();
515let variances = tcx.variances_of(def_id);
516 relate::relate_args_with_variances(self, variances, a_args, b_args)
517 }?;
518if args == a_args { Ok(a_ty) } else { Ok(mk(args)) }
519 }
520521x;#[instrument(level = "debug", skip(self, variance, b), ret)]522fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
523&mut self,
524 variance: ty::Variance,
525 _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
526 a: T,
527 b: T,
528 ) -> RelateResult<'tcx, T> {
529let old_ambient_variance = self.ambient_variance;
530self.ambient_variance = self.ambient_variance.xform(variance);
531debug!(?self.ambient_variance, "new ambient variance");
532// Recursive calls to `relate` can overflow the stack. For example a deeper version of
533 // `ui/associated-consts/issue-93775.rs`.
534let r = ensure_sufficient_stack(|| self.relate(a, b));
535self.ambient_variance = old_ambient_variance;
536 r
537 }
538539x;#[instrument(level = "debug", skip(self, t2), ret)]540fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
541assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
542543if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
544return Ok(result);
545 }
546547// Check to see whether the type we are generalizing references
548 // any other type variable related to `vid` via
549 // subtyping. This is basically our "occurs check", preventing
550 // us from creating infinitely sized types.
551let g = match *t.kind() {
552 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
553bug!("unexpected infer type: {t}")
554 }
555556 ty::Infer(ty::TyVar(vid)) => {
557let mut inner = self.infcx.inner.borrow_mut();
558let vid = inner.type_variables().root_var(vid);
559if TermVid::Ty(vid) == self.root_vid {
560// If sub-roots are equal, then `root_vid` and
561 // `vid` are related via subtyping.
562Err(self.cyclic_term_error())
563 } else {
564let probe = inner.type_variables().probe(vid);
565match probe {
566 TypeVariableValue::Known { value: u } => {
567 drop(inner);
568self.relate(u, u)
569 }
570 TypeVariableValue::Unknown { universe } => {
571match self.ambient_variance {
572// Invariant: no need to make a fresh type variable
573 // if we can name the universe.
574ty::Invariant => {
575if self.for_universe.can_name(universe) {
576return Ok(t);
577 }
578 }
579580// We do need a fresh type variable otherwise.
581ty::Bivariant | ty::Covariant | ty::Contravariant => (),
582 }
583584let origin = inner.type_variables().var_origin(vid);
585let new_var_id =
586 inner.type_variables().new_var(self.for_universe, origin);
587// Record that `vid` and `new_var_id` have to be subtypes
588 // of each other. This is currently only used for diagnostics.
589 // To see why, see the docs in the `type_variables` module.
590inner.type_variables().sub_unify(vid, new_var_id);
591// If we're in the new solver and create a new inference
592 // variable inside of an alias we eagerly constrain that
593 // inference variable to prevent unexpected ambiguity errors.
594 //
595 // This is incomplete as it pulls down the universe of the
596 // original inference variable, even though the alias could
597 // normalize to a type which does not refer to that type at
598 // all. I don't expect this to cause unexpected errors in
599 // practice.
600 //
601 // We only need to do so for type and const variables, as
602 // region variables do not impact normalization, and will get
603 // correctly constrained by `AliasRelate` later on.
604 //
605 // cc trait-system-refactor-initiative#108
606if self.infcx.next_trait_solver()
607 && !self.infcx.typing_mode().is_coherence()
608 && self.in_alias
609 {
610 inner.type_variables().equate(vid, new_var_id);
611 }
612613debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
614Ok(Ty::new_var(self.cx(), new_var_id))
615 }
616 }
617 }
618 }
619620 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
621// No matter what mode we are in,
622 // integer/floating-point types must be equal to be
623 // relatable.
624Ok(t)
625 }
626627 ty::Placeholder(placeholder) => {
628if self.for_universe.can_name(placeholder.universe) {
629Ok(t)
630 } else {
631debug!(
632"root universe {:?} cannot name placeholder in universe {:?}",
633self.for_universe, placeholder.universe
634 );
635Err(TypeError::Mismatch)
636 }
637 }
638639 ty::Alias(data) => match self.structurally_relate_aliases {
640 StructurallyRelateAliases::No => {
641self.generalize_alias_term(data.into()).map(|v| v.expect_type())
642 }
643 StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
644 },
645646_ => relate::structurally_relate_tys(self, t, t),
647 }?;
648649self.cache.insert((t, self.ambient_variance, self.in_alias), g);
650Ok(g)
651 }
652653x;#[instrument(level = "debug", skip(self, r2), ret)]654fn regions(
655&mut self,
656 r: ty::Region<'tcx>,
657 r2: ty::Region<'tcx>,
658 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
659assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
660661match r.kind() {
662// Never make variables for regions bound within the type itself,
663 // nor for erased regions.
664ty::ReBound(..) | ty::ReErased => {
665return Ok(r);
666 }
667668// It doesn't really matter for correctness if we generalize ReError,
669 // since we're already on a doomed compilation path.
670ty::ReError(_) => {
671return Ok(r);
672 }
673674 ty::RePlaceholder(..)
675 | ty::ReVar(..)
676 | ty::ReStatic
677 | ty::ReEarlyParam(..)
678 | ty::ReLateParam(..) => {
679// see common code below
680}
681 }
682683// If we are in an invariant context, we can re-use the region
684 // as is, unless it happens to be in some universe that we
685 // can't name.
686if let ty::Invariant = self.ambient_variance {
687let r_universe = self.infcx.universe_of_region(r);
688if self.for_universe.can_name(r_universe) {
689return Ok(r);
690 }
691 }
692693Ok(self
694.infcx
695 .next_region_var_in_universe(RegionVariableOrigin::Misc(self.span), self.for_universe))
696 }
697698x;#[instrument(level = "debug", skip(self, c2), ret)]699fn consts(
700&mut self,
701 c: ty::Const<'tcx>,
702 c2: ty::Const<'tcx>,
703 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
704assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
705706match c.kind() {
707 ty::ConstKind::Infer(InferConst::Var(vid)) => {
708// If root const vids are equal, then `root_vid` and
709 // `vid` are related and we'd be inferring an infinitely
710 // deep const.
711if TermVid::Const(
712self.infcx.inner.borrow_mut().const_unification_table().find(vid).vid,
713 ) == self.root_vid
714 {
715return Err(self.cyclic_term_error());
716 }
717718let mut inner = self.infcx.inner.borrow_mut();
719let variable_table = &mut inner.const_unification_table();
720match variable_table.probe_value(vid) {
721 ConstVariableValue::Known { value: u } => {
722 drop(inner);
723self.relate(u, u)
724 }
725 ConstVariableValue::Unknown { origin, universe } => {
726if self.for_universe.can_name(universe) {
727Ok(c)
728 } else {
729let new_var_id = variable_table
730 .new_key(ConstVariableValue::Unknown {
731 origin,
732 universe: self.for_universe,
733 })
734 .vid;
735736// See the comment for type inference variables
737 // for more details.
738if self.infcx.next_trait_solver()
739 && !self.infcx.typing_mode().is_coherence()
740 && self.in_alias
741 {
742 variable_table.union(vid, new_var_id);
743 }
744Ok(ty::Const::new_var(self.cx(), new_var_id))
745 }
746 }
747 }
748 }
749// FIXME: Unevaluated constants are also not rigid, so the current
750 // approach of always relating them structurally is incomplete.
751 //
752 // FIXME: replace the StructurallyRelateAliases::Yes branch with
753 // `structurally_relate_consts` once it is fully structural.
754ty::ConstKind::Unevaluated(uv) => match self.structurally_relate_aliases {
755// Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes
756 // path), as doing this new No path breaks some GCE things. I expect GCE to be
757 // ripped out soon so this shouldn't matter soon.
758StructurallyRelateAliases::No if !self.cx().features().generic_const_exprs() => {
759self.generalize_alias_term(ty::AliasTerm::from_unevaluated_const(self.cx(), uv))
760 .map(|v| v.expect_const())
761 }
762_ => {
763let ty::UnevaluatedConst { def, args } = uv;
764let args = self.relate_with_variance(
765 ty::Invariant,
766 ty::VarianceDiagInfo::default(),
767 args,
768 args,
769 )?;
770Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
771 }
772 },
773 ty::ConstKind::Placeholder(placeholder) => {
774if self.for_universe.can_name(placeholder.universe) {
775Ok(c)
776 } else {
777debug!(
778"root universe {:?} cannot name placeholder in universe {:?}",
779self.for_universe, placeholder.universe
780 );
781Err(TypeError::Mismatch)
782 }
783 }
784_ => relate::structurally_relate_consts(self, c, c),
785 }
786 }
787788x;#[instrument(level = "debug", skip(self), ret)]789fn binders<T>(
790&mut self,
791 a: ty::Binder<'tcx, T>,
792_: ty::Binder<'tcx, T>,
793 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
794where
795T: Relate<TyCtxt<'tcx>>,
796 {
797let result = self.relate(a.skip_binder(), a.skip_binder())?;
798Ok(a.rebind(result))
799 }
800}
801802/// Result from a generalization operation. This includes
803/// not only the generalized type, but also a bool flag
804/// indicating whether further WF checks are needed.
805#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for Generalization<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Generalization", "value_may_be_infer", &&self.value_may_be_infer)
}
}Debug)]
806struct Generalization<T> {
807/// When generalizing `<?0 as Trait>::Assoc` or
808 /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
809 /// for `?0` generalization returns an inference
810 /// variable.
811 ///
812 /// This has to be handled with care as it can
813 /// otherwise very easily result in infinite
814 /// recursion.
815pub value_may_be_infer: T,
816}