1use rustc_hir::def::DefKind;
2use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
3use rustc_infer::traits::Obligation;
4use rustc_middle::traits::query::NoSolution;
5pub use rustc_middle::traits::query::type_op::AscribeUserType;
6use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
7use rustc_middle::ty::{
8 self, ParamEnvAnd, Ty, TyCtxt, Unnormalized, UserArgs, UserSelfTy, UserTypeKind,
9};
10use rustc_span::{DUMMY_SP, Span};
11use tracing::{debug, instrument};
12
13use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
14use crate::traits::ObligationCtxt;
15
16impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
17 type QueryResponse = ();
18
19 fn try_fast_path(
20 _tcx: TyCtxt<'tcx>,
21 _key: &ParamEnvAnd<'tcx, Self>,
22 ) -> Option<Self::QueryResponse> {
23 None
24 }
25
26 fn perform_query(
27 tcx: TyCtxt<'tcx>,
28 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
29 ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
30 tcx.type_op_ascribe_user_type(canonicalized)
31 }
32
33 fn perform_locally_with_next_solver(
34 ocx: &ObligationCtxt<'_, 'tcx>,
35 key: ParamEnvAnd<'tcx, Self>,
36 span: Span,
37 ) -> Result<Self::QueryResponse, NoSolution> {
38 type_op_ascribe_user_type_with_span(ocx, key, span)
39 }
40}
41
42pub fn type_op_ascribe_user_type_with_span<'tcx>(
46 ocx: &ObligationCtxt<'_, 'tcx>,
47 key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
48 span: Span,
49) -> Result<(), NoSolution> {
50 let ty::ParamEnvAnd { param_env, value: AscribeUserType { mir_ty, user_ty } } = key;
51 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs:51",
"rustc_trait_selection::traits::query::type_op::ascribe_user_type",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs"),
::tracing_core::__macro_support::Option::Some(51u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::query::type_op::ascribe_user_type"),
::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!("type_op_ascribe_user_type: mir_ty={0:?} user_ty={1:?}",
mir_ty, user_ty) as &dyn Value))])
});
} else { ; }
};debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
52 match user_ty.kind {
53 UserTypeKind::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
54 UserTypeKind::TypeOf(def_id, user_args) => {
55 relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)?
56 }
57 };
58
59 ocx.register_obligations(user_ty.bounds.iter().map(|clause| {
61 Obligation::new(ocx.infcx.tcx, ObligationCause::dummy_with_span(span), param_env, clause)
62 }));
63
64 Ok(())
65}
66
67#[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("relate_mir_and_user_ty",
"rustc_trait_selection::traits::query::type_op::ascribe_user_type",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs"),
::tracing_core::__macro_support::Option::Some(67u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::query::type_op::ascribe_user_type"),
::tracing_core::field::FieldSet::new(&["mir_ty", "user_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(&::tracing::field::debug(&mir_ty)
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(&user_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: Result<(), NoSolution> = loop {};
return __tracing_attr_fake_return;
}
{
let cause = ObligationCause::dummy_with_span(span);
ocx.register_obligation(Obligation::new(ocx.infcx.tcx,
cause.clone(), param_env,
ty::ClauseKind::WellFormed(user_ty.into())));
let user_ty =
ocx.normalize(&cause, param_env,
Unnormalized::new_wip(user_ty));
ocx.eq(&cause, param_env, mir_ty, user_ty)?;
Ok(())
}
}
}#[instrument(level = "debug", skip(ocx, param_env, span))]
68fn relate_mir_and_user_ty<'tcx>(
69 ocx: &ObligationCtxt<'_, 'tcx>,
70 param_env: ty::ParamEnv<'tcx>,
71 span: Span,
72 mir_ty: Ty<'tcx>,
73 user_ty: Ty<'tcx>,
74) -> Result<(), NoSolution> {
75 let cause = ObligationCause::dummy_with_span(span);
76 ocx.register_obligation(Obligation::new(
77 ocx.infcx.tcx,
78 cause.clone(),
79 param_env,
80 ty::ClauseKind::WellFormed(user_ty.into()),
81 ));
82
83 let user_ty = ocx.normalize(&cause, param_env, Unnormalized::new_wip(user_ty));
84 ocx.eq(&cause, param_env, mir_ty, user_ty)?;
85
86 Ok(())
87}
88
89#[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("relate_mir_and_user_args",
"rustc_trait_selection::traits::query::type_op::ascribe_user_type",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs"),
::tracing_core::__macro_support::Option::Some(89u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::query::type_op::ascribe_user_type"),
::tracing_core::field::FieldSet::new(&["mir_ty", "def_id",
"user_args"],
::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(&::tracing::field::debug(&mir_ty)
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(&def_id)
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(&user_args)
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: Result<(), NoSolution> = loop {};
return __tracing_attr_fake_return;
}
{
let UserArgs { user_self_ty, args } = user_args;
let tcx = ocx.infcx.tcx;
let cause = ObligationCause::dummy_with_span(span);
let is_inherent_assoc_const =
#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(def_id)
{
DefKind::AssocConst { .. } => true,
_ => false,
} &&
tcx.def_kind(tcx.parent(def_id)) ==
DefKind::Impl { of_trait: false } &&
tcx.is_type_const(def_id);
let args =
if is_inherent_assoc_const {
let impl_def_id = tcx.parent(def_id);
let impl_args =
ocx.infcx.fresh_args_for_item(span, impl_def_id);
let impl_self_ty =
ocx.normalize(&cause, param_env,
tcx.type_of(impl_def_id).instantiate(tcx, impl_args));
let user_self_ty =
ocx.normalize(&cause, param_env,
Unnormalized::new_wip(args[0].expect_ty()));
ocx.eq(&cause, param_env, impl_self_ty, user_self_ty)?;
let gat_args = &args[1..];
tcx.mk_args_from_iter(impl_args.iter().chain(gat_args.iter().copied()))
} else { args };
let ty = tcx.type_of(def_id).instantiate(tcx, args);
let ty = ocx.normalize(&cause, param_env, ty);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs:125",
"rustc_trait_selection::traits::query::type_op::ascribe_user_type",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs"),
::tracing_core::__macro_support::Option::Some(125u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::query::type_op::ascribe_user_type"),
::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!("relate_type_and_user_type: ty of def-id is {0:?}",
ty) as &dyn Value))])
});
} else { ; }
};
ocx.eq(&cause, param_env, mir_ty, ty)?;
let instantiated_predicates =
tcx.predicates_of(def_id).instantiate(tcx, args);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs:136",
"rustc_trait_selection::traits::query::type_op::ascribe_user_type",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs"),
::tracing_core::__macro_support::Option::Some(136u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::query::type_op::ascribe_user_type"),
::tracing_core::field::FieldSet::new(&["instantiated_predicates"],
::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(&debug(&instantiated_predicates)
as &dyn Value))])
});
} else { ; }
};
for (instantiated_predicate, predicate_span) in
instantiated_predicates {
let span =
if span == DUMMY_SP { predicate_span } else { span };
let cause =
ObligationCause::new(span, CRATE_DEF_ID,
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span));
let instantiated_predicate =
ocx.normalize(&cause, param_env, instantiated_predicate);
ocx.register_obligation(Obligation::new(tcx, cause, param_env,
instantiated_predicate));
}
for term in args.iter().filter_map(ty::GenericArg::as_term) {
ocx.register_obligation(Obligation::new(tcx, cause.clone(),
param_env, ty::ClauseKind::WellFormed(term)));
}
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
ocx.register_obligation(Obligation::new(tcx, cause.clone(),
param_env, ty::ClauseKind::WellFormed(self_ty.into())));
let self_ty =
ocx.normalize(&cause, param_env,
Unnormalized::new_wip(self_ty));
let impl_self_ty =
tcx.type_of(impl_def_id).instantiate(tcx,
args).skip_norm_wip();
let impl_self_ty =
ocx.normalize(&cause, param_env,
Unnormalized::new_wip(impl_self_ty));
ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
}
Ok(())
}
}
}#[instrument(level = "debug", skip(ocx, param_env, span))]
90fn relate_mir_and_user_args<'tcx>(
91 ocx: &ObligationCtxt<'_, 'tcx>,
92 param_env: ty::ParamEnv<'tcx>,
93 span: Span,
94 mir_ty: Ty<'tcx>,
95 def_id: DefId,
96 user_args: UserArgs<'tcx>,
97) -> Result<(), NoSolution> {
98 let UserArgs { user_self_ty, args } = user_args;
99 let tcx = ocx.infcx.tcx;
100 let cause = ObligationCause::dummy_with_span(span);
101
102 let is_inherent_assoc_const = matches!(tcx.def_kind(def_id), DefKind::AssocConst { .. })
105 && tcx.def_kind(tcx.parent(def_id)) == DefKind::Impl { of_trait: false }
106 && tcx.is_type_const(def_id);
107
108 let args = if is_inherent_assoc_const {
109 let impl_def_id = tcx.parent(def_id);
110 let impl_args = ocx.infcx.fresh_args_for_item(span, impl_def_id);
111 let impl_self_ty =
112 ocx.normalize(&cause, param_env, tcx.type_of(impl_def_id).instantiate(tcx, impl_args));
113 let user_self_ty =
114 ocx.normalize(&cause, param_env, Unnormalized::new_wip(args[0].expect_ty()));
115 ocx.eq(&cause, param_env, impl_self_ty, user_self_ty)?;
116
117 let gat_args = &args[1..];
118 tcx.mk_args_from_iter(impl_args.iter().chain(gat_args.iter().copied()))
119 } else {
120 args
121 };
122
123 let ty = tcx.type_of(def_id).instantiate(tcx, args);
124 let ty = ocx.normalize(&cause, param_env, ty);
125 debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
126
127 ocx.eq(&cause, param_env, mir_ty, ty)?;
128
129 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
135
136 debug!(?instantiated_predicates);
137 for (instantiated_predicate, predicate_span) in instantiated_predicates {
138 let span = if span == DUMMY_SP { predicate_span } else { span };
139 let cause = ObligationCause::new(
140 span,
141 CRATE_DEF_ID,
142 ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
143 );
144 let instantiated_predicate = ocx.normalize(&cause, param_env, instantiated_predicate);
145
146 ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
147 }
148
149 for term in args.iter().filter_map(ty::GenericArg::as_term) {
159 ocx.register_obligation(Obligation::new(
160 tcx,
161 cause.clone(),
162 param_env,
163 ty::ClauseKind::WellFormed(term),
164 ));
165 }
166
167 if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
168 ocx.register_obligation(Obligation::new(
169 tcx,
170 cause.clone(),
171 param_env,
172 ty::ClauseKind::WellFormed(self_ty.into()),
173 ));
174
175 let self_ty = ocx.normalize(&cause, param_env, Unnormalized::new_wip(self_ty));
176 let impl_self_ty = tcx.type_of(impl_def_id).instantiate(tcx, args).skip_norm_wip();
177 let impl_self_ty = ocx.normalize(&cause, param_env, Unnormalized::new_wip(impl_self_ty));
178
179 ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
180 }
181
182 Ok(())
183}