1 //! Trait Resolution. See the [rustc dev guide] for more information on how this works.
3 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
9 pub mod const_evaluatable
;
11 pub mod error_reporting
;
18 pub(crate) mod relationships
;
25 use crate::infer
::outlives
::env
::OutlivesEnvironment
;
26 use crate::infer
::{InferCtxt, TyCtxtInferExt}
;
27 use crate::traits
::error_reporting
::InferCtxtExt
as _
;
28 use crate::traits
::query
::evaluate_obligation
::InferCtxtExt
as _
;
29 use rustc_errors
::ErrorGuaranteed
;
31 use rustc_hir
::def_id
::DefId
;
32 use rustc_hir
::lang_items
::LangItem
;
33 use rustc_middle
::ty
::fold
::TypeFoldable
;
34 use rustc_middle
::ty
::subst
::{InternalSubsts, SubstsRef}
;
35 use rustc_middle
::ty
::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry}
;
36 use rustc_span
::{sym, Span}
;
37 use smallvec
::SmallVec
;
40 use std
::ops
::ControlFlow
;
42 pub use self::FulfillmentErrorCode
::*;
43 pub use self::ImplSource
::*;
44 pub use self::ObligationCauseCode
::*;
45 pub use self::SelectionError
::*;
47 pub use self::coherence
::{add_placeholder_note, orphan_check, overlapping_impls}
;
48 pub use self::coherence
::{OrphanCheckErr, OverlapResult}
;
49 pub use self::engine
::TraitEngineExt
;
50 pub use self::fulfill
::{FulfillmentContext, PendingPredicateObligation}
;
51 pub use self::object_safety
::astconv_object_safety_violations
;
52 pub use self::object_safety
::is_vtable_safe_method
;
53 pub use self::object_safety
::MethodViolationCode
;
54 pub use self::object_safety
::ObjectSafetyViolation
;
55 pub use self::on_unimplemented
::{OnUnimplementedDirective, OnUnimplementedNote}
;
56 pub use self::project
::{normalize, normalize_projection_type, normalize_to}
;
57 pub use self::select
::{EvaluationCache, SelectionCache, SelectionContext}
;
58 pub use self::select
::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}
;
59 pub use self::specialize
::specialization_graph
::FutureCompatOverlapError
;
60 pub use self::specialize
::specialization_graph
::FutureCompatOverlapErrorKind
;
61 pub use self::specialize
::{specialization_graph, translate_substs, OverlapError}
;
62 pub use self::structural_match
::search_for_structural_match_violation
;
63 pub use self::structural_match
::{NonStructuralMatchTy, NonStructuralMatchTyKind}
;
65 elaborate_obligations
, elaborate_predicates
, elaborate_predicates_with_span
,
66 elaborate_trait_ref
, elaborate_trait_refs
,
68 pub use self::util
::{expand_trait_aliases, TraitAliasExpander}
;
70 get_vtable_index_of_object_method
, impl_item_is_final
, predicate_for_trait_def
, upcast_choices
,
73 supertrait_def_ids
, supertraits
, transitive_bounds
, transitive_bounds_that_define_assoc_type
,
74 SupertraitDefIds
, Supertraits
,
77 pub use self::chalk_fulfill
::FulfillmentContext
as ChalkFulfillmentContext
;
79 pub use rustc_infer
::traits
::*;
81 /// Whether to skip the leak check, as part of a future compatibility warning step.
83 /// The "default" for skip-leak-check corresponds to the current
84 /// behavior (do not skip the leak check) -- not the behavior we are
85 /// transitioning into.
86 #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
87 pub enum SkipLeakCheck
{
94 fn is_yes(self) -> bool
{
95 self == SkipLeakCheck
::Yes
99 /// The mode that trait queries run in.
100 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
101 pub enum TraitQueryMode
{
102 /// Standard/un-canonicalized queries get accurate
103 /// spans etc. passed in and hence can do reasonable
104 /// error reporting on their own.
106 /// Canonicalized queries get dummy spans and hence
107 /// must generally propagate errors to
108 /// pre-canonicalization callsites.
112 /// Creates predicate obligations from the generic bounds.
113 pub fn predicates_for_generics
<'tcx
>(
114 cause
: ObligationCause
<'tcx
>,
115 param_env
: ty
::ParamEnv
<'tcx
>,
116 generic_bounds
: ty
::InstantiatedPredicates
<'tcx
>,
117 ) -> impl Iterator
<Item
= PredicateObligation
<'tcx
>> {
118 util
::predicates_for_generics(cause
, 0, param_env
, generic_bounds
)
121 /// Determines whether the type `ty` is known to meet `bound` and
122 /// returns true if so. Returns false if `ty` either does not meet
123 /// `bound` or is not known to meet bound (note that this is
124 /// conservative towards *no impl*, which is the opposite of the
125 /// `evaluate` methods).
126 pub fn type_known_to_meet_bound_modulo_regions
<'a
, 'tcx
>(
127 infcx
: &InferCtxt
<'a
, 'tcx
>,
128 param_env
: ty
::ParamEnv
<'tcx
>,
134 "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
136 infcx
.tcx
.def_path_str(def_id
)
140 ty
::Binder
::dummy(ty
::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }
);
141 let obligation
= Obligation
{
143 cause
: ObligationCause
::misc(span
, hir
::CRATE_HIR_ID
),
145 predicate
: trait_ref
.without_const().to_predicate(infcx
.tcx
),
148 let result
= infcx
.predicate_must_hold_modulo_regions(&obligation
);
150 "type_known_to_meet_ty={:?} bound={} => {:?}",
152 infcx
.tcx
.def_path_str(def_id
),
156 if result
&& ty
.has_infer_types_or_consts() {
157 // Because of inference "guessing", selection can sometimes claim
158 // to succeed while the success requires a guess. To ensure
159 // this function's result remains infallible, we must confirm
160 // that guess. While imperfect, I believe this is sound.
162 // The handling of regions in this area of the code is terrible,
163 // see issue #29149. We should be able to improve on this with
165 let mut fulfill_cx
= FulfillmentContext
::new_ignoring_regions();
167 // We can use a dummy node-id here because we won't pay any mind
168 // to region obligations that arise (there shouldn't really be any
170 let cause
= ObligationCause
::misc(span
, hir
::CRATE_HIR_ID
);
172 fulfill_cx
.register_bound(infcx
, param_env
, ty
, def_id
, cause
);
174 // Note: we only assume something is `Copy` if we can
175 // *definitively* show that it implements `Copy`. Otherwise,
176 // assume it is move; linear is always ok.
177 match fulfill_cx
.select_all_or_error(infcx
).as_slice() {
180 "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
182 infcx
.tcx
.def_path_str(def_id
)
189 bound
= %infcx
.tcx
.def_path_str(def_id
),
191 "type_known_to_meet_bound_modulo_regions"
201 fn do_normalize_predicates
<'tcx
>(
203 region_context
: DefId
,
204 cause
: ObligationCause
<'tcx
>,
205 elaborated_env
: ty
::ParamEnv
<'tcx
>,
206 predicates
: Vec
<ty
::Predicate
<'tcx
>>,
207 ) -> Result
<Vec
<ty
::Predicate
<'tcx
>>, ErrorGuaranteed
> {
209 "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
210 predicates
, region_context
, cause
,
212 let span
= cause
.span
;
213 tcx
.infer_ctxt().enter(|infcx
| {
214 // FIXME. We should really... do something with these region
215 // obligations. But this call just continues the older
216 // behavior (i.e., doesn't cause any new bugs), and it would
217 // take some further refactoring to actually solve them. In
218 // particular, we would have to handle implied bounds
219 // properly, and that code is currently largely confined to
220 // regionck (though I made some efforts to extract it
223 // @arielby: In any case, these obligations are checked
224 // by wfcheck anyway, so I'm not sure we have to check
225 // them here too, and we will remove this function when
226 // we move over to lazy normalization *anyway*.
227 let fulfill_cx
= FulfillmentContext
::new_ignoring_regions();
229 match fully_normalize(&infcx
, fulfill_cx
, cause
, elaborated_env
, predicates
) {
230 Ok(predicates
) => predicates
,
232 let reported
= infcx
.report_fulfillment_errors(&errors
, None
, false);
233 return Err(reported
);
237 debug
!("do_normalize_predictes: normalized predicates = {:?}", predicates
);
239 // We can use the `elaborated_env` here; the region code only
240 // cares about declarations like `'a: 'b`.
241 let outlives_env
= OutlivesEnvironment
::new(elaborated_env
);
243 infcx
.resolve_regions_and_report_errors(region_context
, &outlives_env
);
245 let predicates
= match infcx
.fully_resolve(predicates
) {
246 Ok(predicates
) => predicates
,
248 // If we encounter a fixup error, it means that some type
249 // variable wound up unconstrained. I actually don't know
250 // if this can happen, and I certainly don't expect it to
251 // happen often, but if it did happen it probably
252 // represents a legitimate failure due to some kind of
253 // unconstrained variable, and it seems better not to ICE,
254 // all things considered.
255 let reported
= tcx
.sess
.span_err(span
, &fixup_err
.to_string());
256 return Err(reported
);
259 if predicates
.needs_infer() {
262 .delay_span_bug(span
, "encountered inference variables after `fully_resolve`");
270 // FIXME: this is gonna need to be removed ...
271 /// Normalizes the parameter environment, reporting errors if they occur.
272 pub fn normalize_param_env_or_error
<'tcx
>(
274 region_context
: DefId
,
275 unnormalized_env
: ty
::ParamEnv
<'tcx
>,
276 cause
: ObligationCause
<'tcx
>,
277 ) -> ty
::ParamEnv
<'tcx
> {
278 // I'm not wild about reporting errors here; I'd prefer to
279 // have the errors get reported at a defined place (e.g.,
280 // during typeck). Instead I have all parameter
281 // environments, in effect, going through this function
282 // and hence potentially reporting errors. This ensures of
283 // course that we never forget to normalize (the
284 // alternative seemed like it would involve a lot of
285 // manual invocations of this fn -- and then we'd have to
286 // deal with the errors at each of those sites).
288 // In any case, in practice, typeck constructs all the
289 // parameter environments once for every fn as it goes,
290 // and errors will get reported then; so outside of type inference we
291 // can be sure that no errors should occur.
294 "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})",
295 region_context
, unnormalized_env
, cause
298 let mut predicates
: Vec
<_
> =
299 util
::elaborate_predicates(tcx
, unnormalized_env
.caller_bounds().into_iter())
300 .map(|obligation
| obligation
.predicate
)
303 debug
!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates
);
305 let elaborated_env
= ty
::ParamEnv
::new(
306 tcx
.intern_predicates(&predicates
),
307 unnormalized_env
.reveal(),
308 unnormalized_env
.constness(),
311 // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
312 // normalization expects its param-env to be already normalized, which means we have
315 // The way we handle this is by normalizing the param-env inside an unnormalized version
316 // of the param-env, which means that if the param-env contains unnormalized projections,
317 // we'll have some normalization failures. This is unfortunate.
319 // Lazy normalization would basically handle this by treating just the
320 // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
322 // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
323 // types, so to make the situation less bad, we normalize all the predicates *but*
324 // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
325 // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
327 // This works fairly well because trait matching does not actually care about param-env
328 // TypeOutlives predicates - these are normally used by regionck.
329 let outlives_predicates
: Vec
<_
> = predicates
330 .drain_filter(|predicate
| {
331 matches
!(predicate
.kind().skip_binder(), ty
::PredicateKind
::TypeOutlives(..))
336 "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
337 predicates
, outlives_predicates
339 let Ok(non_outlives_predicates
) = do_normalize_predicates(
346 // An unnormalized env is better than nothing.
347 debug
!("normalize_param_env_or_error: errored resolving non-outlives predicates");
348 return elaborated_env
;
351 debug
!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates
);
353 // Not sure whether it is better to include the unnormalized TypeOutlives predicates
354 // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
355 // predicates here anyway. Keeping them here anyway because it seems safer.
356 let outlives_env
: Vec
<_
> =
357 non_outlives_predicates
.iter().chain(&outlives_predicates
).cloned().collect();
358 let outlives_env
= ty
::ParamEnv
::new(
359 tcx
.intern_predicates(&outlives_env
),
360 unnormalized_env
.reveal(),
361 unnormalized_env
.constness(),
363 let Ok(outlives_predicates
) = do_normalize_predicates(
370 // An unnormalized env is better than nothing.
371 debug
!("normalize_param_env_or_error: errored resolving outlives predicates");
372 return elaborated_env
;
374 debug
!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates
);
376 let mut predicates
= non_outlives_predicates
;
377 predicates
.extend(outlives_predicates
);
378 debug
!("normalize_param_env_or_error: final predicates={:?}", predicates
);
380 tcx
.intern_predicates(&predicates
),
381 unnormalized_env
.reveal(),
382 unnormalized_env
.constness(),
386 pub fn fully_normalize
<'a
, 'tcx
, T
>(
387 infcx
: &InferCtxt
<'a
, 'tcx
>,
388 mut fulfill_cx
: FulfillmentContext
<'tcx
>,
389 cause
: ObligationCause
<'tcx
>,
390 param_env
: ty
::ParamEnv
<'tcx
>,
392 ) -> Result
<T
, Vec
<FulfillmentError
<'tcx
>>>
394 T
: TypeFoldable
<'tcx
>,
396 debug
!("fully_normalize_with_fulfillcx(value={:?})", value
);
397 let selcx
= &mut SelectionContext
::new(infcx
);
398 let Normalized { value: normalized_value, obligations }
=
399 project
::normalize(selcx
, param_env
, cause
, value
);
401 "fully_normalize: normalized_value={:?} obligations={:?}",
402 normalized_value
, obligations
404 for obligation
in obligations
{
405 fulfill_cx
.register_predicate_obligation(selcx
.infcx(), obligation
);
408 debug
!("fully_normalize: select_all_or_error start");
409 let errors
= fulfill_cx
.select_all_or_error(infcx
);
410 if !errors
.is_empty() {
413 debug
!("fully_normalize: select_all_or_error complete");
414 let resolved_value
= infcx
.resolve_vars_if_possible(normalized_value
);
415 debug
!("fully_normalize: resolved_value={:?}", resolved_value
);
419 /// Normalizes the predicates and checks whether they hold in an empty environment. If this
420 /// returns true, then either normalize encountered an error or one of the predicates did not
421 /// hold. Used when creating vtables to check for unsatisfiable methods.
422 pub fn impossible_predicates
<'tcx
>(
424 predicates
: Vec
<ty
::Predicate
<'tcx
>>,
426 debug
!("impossible_predicates(predicates={:?})", predicates
);
428 let result
= tcx
.infer_ctxt().enter(|infcx
| {
429 // HACK: Set tainted by errors to gracefully exit in case of overflow.
430 infcx
.set_tainted_by_errors();
432 let param_env
= ty
::ParamEnv
::reveal_all();
433 let mut selcx
= SelectionContext
::new(&infcx
);
434 let mut fulfill_cx
= FulfillmentContext
::new();
435 let cause
= ObligationCause
::dummy();
436 let Normalized { value: predicates, obligations }
=
437 normalize(&mut selcx
, param_env
, cause
.clone(), predicates
);
438 for obligation
in obligations
{
439 fulfill_cx
.register_predicate_obligation(&infcx
, obligation
);
441 for predicate
in predicates
{
442 let obligation
= Obligation
::new(cause
.clone(), param_env
, predicate
);
443 fulfill_cx
.register_predicate_obligation(&infcx
, obligation
);
446 let errors
= fulfill_cx
.select_all_or_error(&infcx
);
448 // Clean up after ourselves
449 let _
= infcx
.inner
.borrow_mut().opaque_type_storage
.take_opaque_types();
453 debug
!("impossible_predicates = {:?}", result
);
457 fn subst_and_check_impossible_predicates
<'tcx
>(
459 key
: (DefId
, SubstsRef
<'tcx
>),
461 debug
!("subst_and_check_impossible_predicates(key={:?})", key
);
463 let mut predicates
= tcx
.predicates_of(key
.0).instantiate(tcx
, key
.1).predicates
;
465 // Specifically check trait fulfillment to avoid an error when trying to resolve
467 if let Some(trait_def_id
) = tcx
.trait_of_item(key
.0) {
468 let trait_ref
= ty
::TraitRef
::from_method(tcx
, trait_def_id
, key
.1);
469 predicates
.push(ty
::Binder
::dummy(trait_ref
).to_poly_trait_predicate().to_predicate(tcx
));
472 predicates
.retain(|predicate
| !predicate
.needs_subst());
473 let result
= impossible_predicates(tcx
, predicates
);
475 debug
!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key
, result
);
479 #[derive(Clone, Debug)]
480 enum VtblSegment
<'tcx
> {
482 TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool }
,
485 /// Prepare the segments for a vtable
486 fn prepare_vtable_segments
<'tcx
, T
>(
488 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
489 mut segment_visitor
: impl FnMut(VtblSegment
<'tcx
>) -> ControlFlow
<T
>,
491 // The following constraints holds for the final arrangement.
492 // 1. The whole virtual table of the first direct super trait is included as the
493 // the prefix. If this trait doesn't have any super traits, then this step
494 // consists of the dsa metadata.
495 // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
496 // other super traits except those already included as part of the first
497 // direct super trait virtual table.
498 // 3. finally, the own methods of this trait.
500 // This has the advantage that trait upcasting to the first direct super trait on each level
501 // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
502 // while not using too much extra memory.
504 // For a single inheritance relationship like this,
505 // D --> C --> B --> A
506 // The resulting vtable will consists of these segments:
509 // For a multiple inheritance relationship like this,
512 // The resulting vtable will consists of these segments:
513 // DSA, A, B, B-vptr, C, D
515 // For a diamond inheritance relationship like this,
518 // The resulting vtable will consists of these segments:
519 // DSA, A, B, C, C-vptr, D
521 // For a more complex inheritance relationship like this:
522 // O --> G --> C --> A
530 // The resulting vtable will consists of these segments:
531 // DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
532 // H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
535 // emit dsa segment first.
536 if let ControlFlow
::Break(v
) = (segment_visitor
)(VtblSegment
::MetadataDSA
) {
540 let mut emit_vptr_on_new_entry
= false;
541 let mut visited
= util
::PredicateSet
::new(tcx
);
542 let predicate
= trait_ref
.without_const().to_predicate(tcx
);
543 let mut stack
: SmallVec
<[(ty
::PolyTraitRef
<'tcx
>, _
, _
); 5]> =
544 smallvec
![(trait_ref
, emit_vptr_on_new_entry
, None
)];
545 visited
.insert(predicate
);
547 // the main traversal loop:
548 // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
549 // that each node is emitted after all its descendents have been emitted.
550 // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
551 // this is done on the fly.
552 // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
553 // stops after it finds a node that has a next-sibling node.
554 // This next-sibling node will used as the starting point of next slice.
557 // For a diamond inheritance relationship like this,
558 // D#1 --> B#0 --> A#0
561 // Starting point 0 stack [D]
562 // Loop run #0: Stack after diving in is [D B A], A is "childless"
563 // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
564 // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
565 // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
566 // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
567 // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
568 // Loop run #1: Stack after exiting out is []. Now the function exits.
571 // dive deeper into the stack, recording the path
573 if let Some((inner_most_trait_ref
, _
, _
)) = stack
.last() {
574 let inner_most_trait_ref
= *inner_most_trait_ref
;
575 let mut direct_super_traits_iter
= tcx
576 .super_predicates_of(inner_most_trait_ref
.def_id())
579 .filter_map(move |(pred
, _
)| {
580 pred
.subst_supertrait(tcx
, &inner_most_trait_ref
).to_opt_poly_trait_pred()
583 'diving_in_skip_visited_traits
: loop {
584 if let Some(next_super_trait
) = direct_super_traits_iter
.next() {
585 if visited
.insert(next_super_trait
.to_predicate(tcx
)) {
586 // We're throwing away potential constness of super traits here.
587 // FIXME: handle ~const super traits
588 let next_super_trait
= next_super_trait
.map_bound(|t
| t
.trait_ref
);
591 emit_vptr_on_new_entry
,
592 Some(direct_super_traits_iter
),
594 break 'diving_in_skip_visited_traits
;
596 continue 'diving_in_skip_visited_traits
;
605 // Other than the left-most path, vptr should be emitted for each trait.
606 emit_vptr_on_new_entry
= true;
608 // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
610 if let Some((inner_most_trait_ref
, emit_vptr
, siblings_opt
)) = stack
.last_mut() {
611 if let ControlFlow
::Break(v
) = (segment_visitor
)(VtblSegment
::TraitOwnEntries
{
612 trait_ref
: *inner_most_trait_ref
,
613 emit_vptr
: *emit_vptr
,
618 'exiting_out_skip_visited_traits
: loop {
619 if let Some(siblings
) = siblings_opt
{
620 if let Some(next_inner_most_trait_ref
) = siblings
.next() {
621 if visited
.insert(next_inner_most_trait_ref
.to_predicate(tcx
)) {
622 // We're throwing away potential constness of super traits here.
623 // FIXME: handle ~const super traits
624 let next_inner_most_trait_ref
=
625 next_inner_most_trait_ref
.map_bound(|t
| t
.trait_ref
);
626 *inner_most_trait_ref
= next_inner_most_trait_ref
;
627 *emit_vptr
= emit_vptr_on_new_entry
;
630 continue 'exiting_out_skip_visited_traits
;
635 continue 'exiting_out
;
644 fn dump_vtable_entries
<'tcx
>(
647 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
648 entries
: &[VtblEntry
<'tcx
>],
650 let msg
= format
!("vtable entries for `{}`: {:#?}", trait_ref
, entries
);
651 tcx
.sess
.struct_span_err(sp
, &msg
).emit();
654 fn own_existential_vtable_entries
<'tcx
>(
656 trait_ref
: ty
::PolyExistentialTraitRef
<'tcx
>,
658 let trait_methods
= tcx
659 .associated_items(trait_ref
.def_id())
660 .in_definition_order()
661 .filter(|item
| item
.kind
== ty
::AssocKind
::Fn
);
662 // Now list each method's DefId (for within its trait).
663 let own_entries
= trait_methods
.filter_map(move |trait_method
| {
664 debug
!("own_existential_vtable_entry: trait_method={:?}", trait_method
);
665 let def_id
= trait_method
.def_id
;
667 // Some methods cannot be called on an object; skip those.
668 if !is_vtable_safe_method(tcx
, trait_ref
.def_id(), &trait_method
) {
669 debug
!("own_existential_vtable_entry: not vtable safe");
676 tcx
.arena
.alloc_from_iter(own_entries
.into_iter())
679 /// Given a trait `trait_ref`, iterates the vtable entries
680 /// that come from `trait_ref`, including its supertraits.
681 fn vtable_entries
<'tcx
>(
683 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
684 ) -> &'tcx
[VtblEntry
<'tcx
>] {
685 debug
!("vtable_entries({:?})", trait_ref
);
687 let mut entries
= vec
![];
689 let vtable_segment_callback
= |segment
| -> ControlFlow
<()> {
691 VtblSegment
::MetadataDSA
=> {
692 entries
.extend(TyCtxt
::COMMON_VTABLE_ENTRIES
);
694 VtblSegment
::TraitOwnEntries { trait_ref, emit_vptr }
=> {
695 let existential_trait_ref
= trait_ref
696 .map_bound(|trait_ref
| ty
::ExistentialTraitRef
::erase_self_ty(tcx
, trait_ref
));
698 // Lookup the shape of vtable for the trait.
699 let own_existential_entries
=
700 tcx
.own_existential_vtable_entries(existential_trait_ref
);
702 let own_entries
= own_existential_entries
.iter().copied().map(|def_id
| {
703 debug
!("vtable_entries: trait_method={:?}", def_id
);
705 // The method may have some early-bound lifetimes; add regions for those.
706 let substs
= trait_ref
.map_bound(|trait_ref
| {
707 InternalSubsts
::for_item(tcx
, def_id
, |param
, _
| match param
.kind
{
708 GenericParamDefKind
::Lifetime
=> tcx
.lifetimes
.re_erased
.into(),
709 GenericParamDefKind
::Type { .. }
710 | GenericParamDefKind
::Const { .. }
=> {
711 trait_ref
.substs
[param
.index
as usize]
716 // The trait type may have higher-ranked lifetimes in it;
717 // erase them if they appear, so that we get the type
718 // at some particular call site.
720 .normalize_erasing_late_bound_regions(ty
::ParamEnv
::reveal_all(), substs
);
722 // It's possible that the method relies on where-clauses that
723 // do not hold for this particular set of type parameters.
724 // Note that this method could then never be called, so we
725 // do not want to try and codegen it, in that case (see #23435).
726 let predicates
= tcx
.predicates_of(def_id
).instantiate_own(tcx
, substs
);
727 if impossible_predicates(tcx
, predicates
.predicates
) {
728 debug
!("vtable_entries: predicates do not hold");
729 return VtblEntry
::Vacant
;
732 let instance
= ty
::Instance
::resolve_for_vtable(
734 ty
::ParamEnv
::reveal_all(),
738 .expect("resolution failed during building vtable representation");
739 VtblEntry
::Method(instance
)
742 entries
.extend(own_entries
);
745 entries
.push(VtblEntry
::TraitVPtr(trait_ref
));
750 ControlFlow
::Continue(())
753 let _
= prepare_vtable_segments(tcx
, trait_ref
, vtable_segment_callback
);
755 if tcx
.has_attr(trait_ref
.def_id(), sym
::rustc_dump_vtable
) {
756 let sp
= tcx
.def_span(trait_ref
.def_id());
757 dump_vtable_entries(tcx
, sp
, trait_ref
, &entries
);
760 tcx
.arena
.alloc_from_iter(entries
.into_iter())
763 /// Find slot base for trait methods within vtable entries of another trait
764 fn vtable_trait_first_method_offset
<'tcx
>(
767 ty
::PolyTraitRef
<'tcx
>, // trait_to_be_found
768 ty
::PolyTraitRef
<'tcx
>, // trait_owning_vtable
771 let (trait_to_be_found
, trait_owning_vtable
) = key
;
774 let trait_to_be_found_erased
= tcx
.erase_regions(trait_to_be_found
);
776 let vtable_segment_callback
= {
777 let mut vtable_base
= 0;
781 VtblSegment
::MetadataDSA
=> {
782 vtable_base
+= TyCtxt
::COMMON_VTABLE_ENTRIES
.len();
784 VtblSegment
::TraitOwnEntries { trait_ref, emit_vptr }
=> {
785 if tcx
.erase_regions(trait_ref
) == trait_to_be_found_erased
{
786 return ControlFlow
::Break(vtable_base
);
788 vtable_base
+= util
::count_own_vtable_entries(tcx
, trait_ref
);
794 ControlFlow
::Continue(())
798 if let Some(vtable_base
) =
799 prepare_vtable_segments(tcx
, trait_owning_vtable
, vtable_segment_callback
)
803 bug
!("Failed to find info for expected trait in vtable");
807 /// Find slot offset for trait vptr within vtable entries of another trait
808 pub fn vtable_trait_upcasting_coercion_new_vptr_slot
<'tcx
>(
811 Ty
<'tcx
>, // trait object type whose trait owning vtable
812 Ty
<'tcx
>, // trait object for supertrait
815 let (source
, target
) = key
;
816 assert
!(matches
!(&source
.kind(), &ty
::Dynamic(..)) && !source
.needs_infer());
817 assert
!(matches
!(&target
.kind(), &ty
::Dynamic(..)) && !target
.needs_infer());
819 // this has been typecked-before, so diagnostics is not really needed.
820 let unsize_trait_did
= tcx
.require_lang_item(LangItem
::Unsize
, None
);
822 let trait_ref
= ty
::TraitRef
{
823 def_id
: unsize_trait_did
,
824 substs
: tcx
.mk_substs_trait(source
, &[target
.into()]),
826 let obligation
= Obligation
::new(
827 ObligationCause
::dummy(),
828 ty
::ParamEnv
::reveal_all(),
829 ty
::Binder
::dummy(ty
::TraitPredicate
{
831 constness
: ty
::BoundConstness
::NotConst
,
832 polarity
: ty
::ImplPolarity
::Positive
,
836 let implsrc
= tcx
.infer_ctxt().enter(|infcx
| {
837 let mut selcx
= SelectionContext
::new(&infcx
);
838 selcx
.select(&obligation
).unwrap()
841 let Some(ImplSource
::TraitUpcasting(implsrc_traitcasting
)) = implsrc
else {
845 implsrc_traitcasting
.vtable_vptr_slot
848 pub fn provide(providers
: &mut ty
::query
::Providers
) {
849 object_safety
::provide(providers
);
850 structural_match
::provide(providers
);
851 *providers
= ty
::query
::Providers
{
852 specialization_graph_of
: specialize
::specialization_graph_provider
,
853 specializes
: specialize
::specializes
,
854 codegen_fulfill_obligation
: codegen
::codegen_fulfill_obligation
,
855 own_existential_vtable_entries
,
857 vtable_trait_upcasting_coercion_new_vptr_slot
,
858 subst_and_check_impossible_predicates
,
859 thir_abstract_const
: |tcx
, def_id
| {
860 let def_id
= def_id
.expect_local();
861 if let Some(def
) = ty
::WithOptConstParam
::try_lookup(def_id
, tcx
) {
862 tcx
.thir_abstract_const_of_const_arg(def
)
864 const_evaluatable
::thir_abstract_const(tcx
, ty
::WithOptConstParam
::unknown(def_id
))
867 thir_abstract_const_of_const_arg
: |tcx
, (did
, param_did
)| {
868 const_evaluatable
::thir_abstract_const(
870 ty
::WithOptConstParam { did, const_param_did: Some(param_did) }
,
873 try_unify_abstract_consts
: |tcx
, param_env_and
| {
874 let (param_env
, (a
, b
)) = param_env_and
.into_parts();
875 const_evaluatable
::try_unify_abstract_consts(tcx
, (a
, b
), param_env
)