1 use rustc_errors
::ErrorGuaranteed
;
2 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
3 use rustc_infer
::infer
::TyCtxtInferExt
;
4 use rustc_middle
::traits
::CodegenObligationError
;
5 use rustc_middle
::ty
::subst
::SubstsRef
;
6 use rustc_middle
::ty
::{self, Instance, TyCtxt, TypeVisitable}
;
8 use rustc_trait_selection
::traits
;
9 use traits
::{translate_substs, Reveal}
;
11 fn resolve_instance
<'tcx
>(
13 key
: ty
::ParamEnvAnd
<'tcx
, (DefId
, SubstsRef
<'tcx
>)>,
14 ) -> Result
<Option
<Instance
<'tcx
>>, ErrorGuaranteed
> {
15 let (param_env
, (did
, substs
)) = key
.into_parts();
16 if let Some(did
) = did
.as_local() {
17 if let Some(param_did
) = tcx
.opt_const_param_of(did
) {
18 return tcx
.resolve_instance_of_const_arg(param_env
.and((did
, param_did
, substs
)));
22 inner_resolve_instance(tcx
, param_env
.and((ty
::WithOptConstParam
::unknown(did
), substs
)))
25 fn resolve_instance_of_const_arg
<'tcx
>(
27 key
: ty
::ParamEnvAnd
<'tcx
, (LocalDefId
, DefId
, SubstsRef
<'tcx
>)>,
28 ) -> Result
<Option
<Instance
<'tcx
>>, ErrorGuaranteed
> {
29 let (param_env
, (did
, const_param_did
, substs
)) = key
.into_parts();
30 inner_resolve_instance(
33 ty
::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) }
,
39 fn inner_resolve_instance
<'tcx
>(
41 key
: ty
::ParamEnvAnd
<'tcx
, (ty
::WithOptConstParam
<DefId
>, SubstsRef
<'tcx
>)>,
42 ) -> Result
<Option
<Instance
<'tcx
>>, ErrorGuaranteed
> {
43 let (param_env
, (def
, substs
)) = key
.into_parts();
45 let result
= if let Some(trait_def_id
) = tcx
.trait_of_item(def
.did
) {
46 debug
!(" => associated item, attempting to find impl in param_env {:#?}", param_env
);
47 resolve_associated_item(tcx
, def
.did
, param_env
, trait_def_id
, substs
)
49 let ty
= tcx
.type_of(def
.def_id_for_type_of());
50 let item_type
= tcx
.subst_and_normalize_erasing_regions(substs
, param_env
, ty
);
52 let def
= match *item_type
.kind() {
53 ty
::FnDef(def_id
, ..) if tcx
.is_intrinsic(def_id
) => {
54 debug
!(" => intrinsic");
55 ty
::InstanceDef
::Intrinsic(def
.did
)
57 ty
::FnDef(def_id
, substs
) if Some(def_id
) == tcx
.lang_items().drop_in_place_fn() => {
58 let ty
= substs
.type_at(0);
60 if ty
.needs_drop(tcx
, param_env
) {
61 debug
!(" => nontrivial drop glue");
70 // Drop shims can only be built from ADTs.
74 ty
::InstanceDef
::DropGlue(def_id
, Some(ty
))
76 debug
!(" => trivial drop glue");
77 ty
::InstanceDef
::DropGlue(def_id
, None
)
81 debug
!(" => free item");
82 ty
::InstanceDef
::Item(def
)
85 Ok(Some(Instance { def, substs }
))
87 debug
!("inner_resolve_instance: result={:?}", result
);
91 fn resolve_associated_item
<'tcx
>(
94 param_env
: ty
::ParamEnv
<'tcx
>,
96 rcvr_substs
: SubstsRef
<'tcx
>,
97 ) -> Result
<Option
<Instance
<'tcx
>>, ErrorGuaranteed
> {
98 debug
!(?trait_item_id
, ?param_env
, ?trait_id
, ?rcvr_substs
, "resolve_associated_item");
100 let trait_ref
= ty
::TraitRef
::from_method(tcx
, trait_id
, rcvr_substs
);
102 let vtbl
= match tcx
.codegen_select_candidate((param_env
, ty
::Binder
::dummy(trait_ref
))) {
104 Err(CodegenObligationError
::Ambiguity
) => {
105 let reported
= tcx
.sess
.delay_span_bug(
106 tcx
.def_span(trait_item_id
),
108 "encountered ambiguity selecting `{trait_ref:?}` during codegen, presuming due to \
109 overflow or prior type error",
112 return Err(reported
);
114 Err(CodegenObligationError
::Unimplemented
) => return Ok(None
),
115 Err(CodegenObligationError
::FulfillmentError
) => return Ok(None
),
118 // Now that we know which impl is being used, we can dispatch to
119 // the actual function:
121 traits
::ImplSource
::UserDefined(impl_data
) => {
123 "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}",
124 param_env
, trait_item_id
, rcvr_substs
, impl_data
126 assert
!(!rcvr_substs
.needs_infer());
127 assert
!(!trait_ref
.needs_infer());
129 let trait_def_id
= tcx
.trait_id_of_impl(impl_data
.impl_def_id
).unwrap();
130 let trait_def
= tcx
.trait_def(trait_def_id
);
131 let leaf_def
= trait_def
132 .ancestors(tcx
, impl_data
.impl_def_id
)?
133 .leaf_def(tcx
, trait_item_id
)
135 bug
!("{:?} not found in {:?}", trait_item_id
, impl_data
.impl_def_id
);
137 let infcx
= tcx
.infer_ctxt().build();
138 let param_env
= param_env
.with_reveal_all_normalized(tcx
);
139 let substs
= rcvr_substs
.rebase_onto(tcx
, trait_def_id
, impl_data
.substs
);
140 let substs
= translate_substs(
143 impl_data
.impl_def_id
,
145 leaf_def
.defining_node
,
147 let substs
= infcx
.tcx
.erase_regions(substs
);
149 // Since this is a trait item, we need to see if the item is either a trait default item
150 // or a specialization because we can't resolve those unless we can `Reveal::All`.
151 // NOTE: This should be kept in sync with the similar code in
152 // `rustc_trait_selection::traits::project::assemble_candidates_from_impls()`.
153 let eligible
= if leaf_def
.is_final() {
154 // Non-specializable items are always projectable.
157 // Only reveal a specializable default if we're past type-checking
158 // and the obligation is monomorphic, otherwise passes such as
159 // transmute checking and polymorphic MIR optimizations could
160 // get a result which isn't correct for all monomorphizations.
161 if param_env
.reveal() == Reveal
::All
{
162 !trait_ref
.still_further_specializable()
172 // Any final impl is required to define all associated items.
173 if !leaf_def
.item
.defaultness(tcx
).has_value() {
174 let guard
= tcx
.sess
.delay_span_bug(
175 tcx
.def_span(leaf_def
.item
.def_id
),
176 "missing value for assoc item in impl",
181 let substs
= tcx
.erase_regions(substs
);
183 // Check if we just resolved an associated `const` declaration from
184 // a `trait` to an associated `const` definition in an `impl`, where
185 // the definition in the `impl` has the wrong type (for which an
186 // error has already been/will be emitted elsewhere).
187 if leaf_def
.item
.kind
== ty
::AssocKind
::Const
188 && trait_item_id
!= leaf_def
.item
.def_id
189 && let Some(leaf_def_item
) = leaf_def
.item
.def_id
.as_local()
191 tcx
.compare_assoc_const_impl_item_with_trait_item((
197 Some(ty
::Instance
::new(leaf_def
.item
.def_id
, substs
))
199 traits
::ImplSource
::Generator(generator_data
) => Some(Instance
{
200 def
: ty
::InstanceDef
::Item(ty
::WithOptConstParam
::unknown(
201 generator_data
.generator_def_id
,
203 substs
: generator_data
.substs
,
205 traits
::ImplSource
::Future(future_data
) => Some(Instance
{
206 def
: ty
::InstanceDef
::Item(ty
::WithOptConstParam
::unknown(
207 future_data
.generator_def_id
,
209 substs
: future_data
.substs
,
211 traits
::ImplSource
::Closure(closure_data
) => {
212 let trait_closure_kind
= tcx
.fn_trait_kind_from_def_id(trait_id
).unwrap();
213 Instance
::resolve_closure(
215 closure_data
.closure_def_id
,
220 traits
::ImplSource
::FnPointer(ref data
) => match data
.fn_ty
.kind() {
221 ty
::FnDef(..) | ty
::FnPtr(..) => Some(Instance
{
222 def
: ty
::InstanceDef
::FnPtrShim(trait_item_id
, data
.fn_ty
),
227 traits
::ImplSource
::Object(ref data
) => {
228 if let Some(index
) = traits
::get_vtable_index_of_object_method(tcx
, data
, trait_item_id
)
231 def
: ty
::InstanceDef
::Virtual(trait_item_id
, index
),
238 traits
::ImplSource
::Builtin(..) => {
239 if Some(trait_ref
.def_id
) == tcx
.lang_items().clone_trait() {
240 // FIXME(eddyb) use lang items for methods instead of names.
241 let name
= tcx
.item_name(trait_item_id
);
242 if name
== sym
::clone
{
243 let self_ty
= trait_ref
.self_ty();
245 let is_copy
= self_ty
.is_copy_modulo_regions(tcx
, param_env
);
246 match self_ty
.kind() {
249 | ty
::GeneratorWitness(..)
251 | ty
::Tuple(..) => {}
252 _
=> return Ok(None
),
256 def
: ty
::InstanceDef
::CloneShim(trait_item_id
, self_ty
),
260 assert_eq
!(name
, sym
::clone_from
);
262 // Use the default `fn clone_from` from `trait Clone`.
263 let substs
= tcx
.erase_regions(rcvr_substs
);
264 Some(ty
::Instance
::new(trait_item_id
, substs
))
270 traits
::ImplSource
::AutoImpl(..)
271 | traits
::ImplSource
::Param(..)
272 | traits
::ImplSource
::TraitAlias(..)
273 | traits
::ImplSource
::TraitUpcasting(_
)
274 | traits
::ImplSource
::ConstDestruct(_
) => None
,
278 pub fn provide(providers
: &mut ty
::query
::Providers
) {
280 ty
::query
::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers }
;