3 //! Confirmation unifies the output type parameters of the trait
4 //! with the values found in the obligation, possibly yielding a
5 //! type error. See the [rustc dev guide] for more details.
8 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
9 use rustc_data_structures
::stack
::ensure_sufficient_stack
;
10 use rustc_hir
::lang_items
::LangItem
;
11 use rustc_hir
::Constness
;
12 use rustc_index
::bit_set
::GrowableBitSet
;
13 use rustc_infer
::infer
::InferOk
;
14 use rustc_infer
::infer
::LateBoundRegionConversionTime
::HigherRankedType
;
15 use rustc_middle
::ty
::subst
::{GenericArg, GenericArgKind, Subst, SubstsRef}
;
16 use rustc_middle
::ty
::{self, Ty}
;
17 use rustc_middle
::ty
::{ToPolyTraitRef, ToPredicate, WithConstness}
;
18 use rustc_span
::def_id
::DefId
;
20 use crate::traits
::project
::{normalize_with_depth, normalize_with_depth_to}
;
21 use crate::traits
::select
::TraitObligationExt
;
22 use crate::traits
::util
;
23 use crate::traits
::util
::{closure_trait_ref_and_return_type, predicate_for_trait_def}
;
24 use crate::traits
::ImplSource
;
25 use crate::traits
::Normalized
;
26 use crate::traits
::OutputTypeParameterMismatch
;
27 use crate::traits
::Selection
;
28 use crate::traits
::TraitNotObjectSafe
;
29 use crate::traits
::{BuiltinDerivedObligation, ImplDerivedObligation}
;
31 ImplSourceAutoImplData
, ImplSourceBuiltinData
, ImplSourceClosureData
,
32 ImplSourceDiscriminantKindData
, ImplSourceFnPointerData
, ImplSourceGeneratorData
,
33 ImplSourceObjectData
, ImplSourcePointeeData
, ImplSourceTraitAliasData
,
34 ImplSourceUserDefinedData
,
36 use crate::traits
::{ObjectCastObligation, PredicateObligation, TraitObligation}
;
37 use crate::traits
::{Obligation, ObligationCause}
;
38 use crate::traits
::{SelectionError, Unimplemented}
;
40 use super::BuiltinImplConditions
;
41 use super::SelectionCandidate
::{self, *}
;
42 use super::SelectionContext
;
46 impl<'cx
, 'tcx
> SelectionContext
<'cx
, 'tcx
> {
47 #[instrument(level = "debug", skip(self))]
48 pub(super) fn confirm_candidate(
50 obligation
: &TraitObligation
<'tcx
>,
51 candidate
: SelectionCandidate
<'tcx
>,
52 ) -> Result
<Selection
<'tcx
>, SelectionError
<'tcx
>> {
54 BuiltinCandidate { has_nested }
=> {
55 let data
= self.confirm_builtin_candidate(obligation
, has_nested
);
56 Ok(ImplSource
::Builtin(data
))
59 ParamCandidate(param
) => {
60 let obligations
= self.confirm_param_candidate(obligation
, param
.value
);
61 Ok(ImplSource
::Param(obligations
, param
.constness
))
64 ImplCandidate(impl_def_id
) => {
65 Ok(ImplSource
::UserDefined(self.confirm_impl_candidate(obligation
, impl_def_id
)))
68 AutoImplCandidate(trait_def_id
) => {
69 let data
= self.confirm_auto_impl_candidate(obligation
, trait_def_id
);
70 Ok(ImplSource
::AutoImpl(data
))
73 ProjectionCandidate(idx
) => {
74 let obligations
= self.confirm_projection_candidate(obligation
, idx
)?
;
75 // FIXME(jschievink): constness
76 Ok(ImplSource
::Param(obligations
, Constness
::NotConst
))
79 ObjectCandidate(idx
) => {
80 let data
= self.confirm_object_candidate(obligation
, idx
)?
;
81 Ok(ImplSource
::Object(data
))
85 let vtable_closure
= self.confirm_closure_candidate(obligation
)?
;
86 Ok(ImplSource
::Closure(vtable_closure
))
89 GeneratorCandidate
=> {
90 let vtable_generator
= self.confirm_generator_candidate(obligation
)?
;
91 Ok(ImplSource
::Generator(vtable_generator
))
94 FnPointerCandidate
=> {
95 let data
= self.confirm_fn_pointer_candidate(obligation
)?
;
96 Ok(ImplSource
::FnPointer(data
))
99 DiscriminantKindCandidate
=> {
100 Ok(ImplSource
::DiscriminantKind(ImplSourceDiscriminantKindData
))
103 PointeeCandidate
=> Ok(ImplSource
::Pointee(ImplSourcePointeeData
)),
105 TraitAliasCandidate(alias_def_id
) => {
106 let data
= self.confirm_trait_alias_candidate(obligation
, alias_def_id
);
107 Ok(ImplSource
::TraitAlias(data
))
110 BuiltinObjectCandidate
=> {
111 // This indicates something like `Trait + Send: Send`. In this case, we know that
112 // this holds because that's what the object type is telling us, and there's really
113 // no additional obligations to prove and no types in particular to unify, etc.
114 Ok(ImplSource
::Param(Vec
::new(), Constness
::NotConst
))
117 BuiltinUnsizeCandidate
=> {
118 let data
= self.confirm_builtin_unsize_candidate(obligation
)?
;
119 Ok(ImplSource
::Builtin(data
))
124 fn confirm_projection_candidate(
126 obligation
: &TraitObligation
<'tcx
>,
128 ) -> Result
<Vec
<PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>> {
129 self.infcx
.commit_unconditionally(|_
| {
130 let tcx
= self.tcx();
132 let trait_predicate
= self.infcx
.shallow_resolve(obligation
.predicate
);
133 let placeholder_trait_predicate
=
134 self.infcx().replace_bound_vars_with_placeholders(trait_predicate
);
135 let placeholder_self_ty
= placeholder_trait_predicate
.self_ty();
136 let (def_id
, substs
) = match *placeholder_self_ty
.kind() {
137 ty
::Projection(proj
) => (proj
.item_def_id
, proj
.substs
),
138 ty
::Opaque(def_id
, substs
) => (def_id
, substs
),
139 _
=> bug
!("projection candidate for unexpected type: {:?}", placeholder_self_ty
),
142 let candidate_predicate
= tcx
.item_bounds(def_id
)[idx
].subst(tcx
, substs
);
143 let candidate
= candidate_predicate
144 .to_opt_poly_trait_ref()
145 .expect("projection candidate is not a trait predicate");
146 let mut obligations
= Vec
::new();
147 let candidate
= normalize_with_depth_to(
149 obligation
.param_env
,
150 obligation
.cause
.clone(),
151 obligation
.recursion_depth
+ 1,
156 obligations
.extend(self.infcx
.commit_if_ok(|_
| {
158 .at(&obligation
.cause
, obligation
.param_env
)
159 .sup(placeholder_trait_predicate
.trait_ref
.to_poly_trait_ref(), candidate
.value
)
160 .map(|InferOk { obligations, .. }
| obligations
)
161 .map_err(|_
| Unimplemented
)
164 if let ty
::Projection(..) = placeholder_self_ty
.kind() {
165 for predicate
in tcx
.predicates_of(def_id
).instantiate_own(tcx
, substs
).predicates
{
166 let normalized
= normalize_with_depth_to(
168 obligation
.param_env
,
169 obligation
.cause
.clone(),
170 obligation
.recursion_depth
+ 1,
174 obligations
.push(Obligation
::with_depth(
175 obligation
.cause
.clone(),
176 obligation
.recursion_depth
+ 1,
177 obligation
.param_env
,
187 fn confirm_param_candidate(
189 obligation
: &TraitObligation
<'tcx
>,
190 param
: ty
::PolyTraitRef
<'tcx
>,
191 ) -> Vec
<PredicateObligation
<'tcx
>> {
192 debug
!(?obligation
, ?param
, "confirm_param_candidate");
194 // During evaluation, we already checked that this
195 // where-clause trait-ref could be unified with the obligation
196 // trait-ref. Repeat that unification now without any
197 // transactional boundary; it should not fail.
198 match self.match_where_clause_trait_ref(obligation
, param
) {
199 Ok(obligations
) => obligations
,
202 "Where clause `{:?}` was applicable to `{:?}` but now is not",
210 fn confirm_builtin_candidate(
212 obligation
: &TraitObligation
<'tcx
>,
214 ) -> ImplSourceBuiltinData
<PredicateObligation
<'tcx
>> {
215 debug
!(?obligation
, ?has_nested
, "confirm_builtin_candidate");
217 let lang_items
= self.tcx().lang_items();
218 let obligations
= if has_nested
{
219 let trait_def
= obligation
.predicate
.def_id();
220 let conditions
= if Some(trait_def
) == lang_items
.sized_trait() {
221 self.sized_conditions(obligation
)
222 } else if Some(trait_def
) == lang_items
.copy_trait() {
223 self.copy_clone_conditions(obligation
)
224 } else if Some(trait_def
) == lang_items
.clone_trait() {
225 self.copy_clone_conditions(obligation
)
227 bug
!("unexpected builtin trait {:?}", trait_def
)
229 let nested
= match conditions
{
230 BuiltinImplConditions
::Where(nested
) => nested
,
231 _
=> bug
!("obligation {:?} had matched a builtin impl but now doesn't", obligation
),
234 let cause
= obligation
.derived_cause(BuiltinDerivedObligation
);
235 ensure_sufficient_stack(|| {
236 self.collect_predicates_for_types(
237 obligation
.param_env
,
239 obligation
.recursion_depth
+ 1,
248 debug
!(?obligations
);
250 ImplSourceBuiltinData { nested: obligations }
253 /// This handles the case where a `auto trait Foo` impl is being used.
254 /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
256 /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
257 /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
258 fn confirm_auto_impl_candidate(
260 obligation
: &TraitObligation
<'tcx
>,
262 ) -> ImplSourceAutoImplData
<PredicateObligation
<'tcx
>> {
263 debug
!(?obligation
, ?trait_def_id
, "confirm_auto_impl_candidate");
265 let self_ty
= self.infcx
.shallow_resolve(obligation
.predicate
.self_ty());
266 let types
= self.constituent_types_for_ty(self_ty
);
267 self.vtable_auto_impl(obligation
, trait_def_id
, types
)
270 /// See `confirm_auto_impl_candidate`.
273 obligation
: &TraitObligation
<'tcx
>,
275 nested
: ty
::Binder
<Vec
<Ty
<'tcx
>>>,
276 ) -> ImplSourceAutoImplData
<PredicateObligation
<'tcx
>> {
277 debug
!(?nested
, "vtable_auto_impl");
278 ensure_sufficient_stack(|| {
279 let cause
= obligation
.derived_cause(BuiltinDerivedObligation
);
280 let mut obligations
= self.collect_predicates_for_types(
281 obligation
.param_env
,
283 obligation
.recursion_depth
+ 1,
288 let trait_obligations
: Vec
<PredicateObligation
<'_
>> =
289 self.infcx
.commit_unconditionally(|_
| {
290 let poly_trait_ref
= obligation
.predicate
.to_poly_trait_ref();
291 let trait_ref
= self.infcx
.replace_bound_vars_with_placeholders(poly_trait_ref
);
292 let cause
= obligation
.derived_cause(ImplDerivedObligation
);
293 self.impl_or_trait_obligations(
295 obligation
.recursion_depth
+ 1,
296 obligation
.param_env
,
302 // Adds the predicates from the trait. Note that this contains a `Self: Trait`
303 // predicate as usual. It won't have any effect since auto traits are coinductive.
304 obligations
.extend(trait_obligations
);
306 debug
!(?obligations
, "vtable_auto_impl");
308 ImplSourceAutoImplData { trait_def_id, nested: obligations }
312 fn confirm_impl_candidate(
314 obligation
: &TraitObligation
<'tcx
>,
316 ) -> ImplSourceUserDefinedData
<'tcx
, PredicateObligation
<'tcx
>> {
317 debug
!(?obligation
, ?impl_def_id
, "confirm_impl_candidate");
319 // First, create the substitutions by matching the impl again,
320 // this time not in a probe.
321 self.infcx
.commit_unconditionally(|_
| {
322 let substs
= self.rematch_impl(impl_def_id
, obligation
);
323 debug
!(?substs
, "impl substs");
324 let cause
= obligation
.derived_cause(ImplDerivedObligation
);
325 ensure_sufficient_stack(|| {
330 obligation
.recursion_depth
+ 1,
331 obligation
.param_env
,
340 substs
: Normalized
<'tcx
, SubstsRef
<'tcx
>>,
341 cause
: ObligationCause
<'tcx
>,
342 recursion_depth
: usize,
343 param_env
: ty
::ParamEnv
<'tcx
>,
344 ) -> ImplSourceUserDefinedData
<'tcx
, PredicateObligation
<'tcx
>> {
345 debug
!(?impl_def_id
, ?substs
, ?recursion_depth
, "vtable_impl");
347 let mut impl_obligations
= self.impl_or_trait_obligations(
355 debug
!(?impl_obligations
, "vtable_impl");
357 // Because of RFC447, the impl-trait-ref and obligations
358 // are sufficient to determine the impl substs, without
359 // relying on projections in the impl-trait-ref.
361 // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
362 impl_obligations
.extend(substs
.obligations
);
364 ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
367 fn confirm_object_candidate(
369 obligation
: &TraitObligation
<'tcx
>,
371 ) -> Result
<ImplSourceObjectData
<'tcx
, PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>> {
372 let tcx
= self.tcx();
373 debug
!(?obligation
, ?index
, "confirm_object_candidate");
375 let trait_predicate
= self.infcx
.replace_bound_vars_with_placeholders(obligation
.predicate
);
376 let self_ty
= self.infcx
.shallow_resolve(trait_predicate
.self_ty());
377 let obligation_trait_ref
= ty
::Binder
::dummy(trait_predicate
.trait_ref
);
378 let data
= match *self_ty
.kind() {
379 ty
::Dynamic(data
, ..) => data
,
380 _
=> span_bug
!(obligation
.cause
.span
, "object candidate with non-object"),
383 let object_trait_ref
= data
.principal().unwrap_or_else(|| {
384 span_bug
!(obligation
.cause
.span
, "object candidate with no principal")
386 let object_trait_ref
= self
388 .replace_bound_vars_with_fresh_vars(
389 obligation
.cause
.span
,
394 let object_trait_ref
= object_trait_ref
.with_self_ty(self.tcx(), self_ty
);
396 let mut nested
= vec
![];
398 let mut supertraits
= util
::supertraits(tcx
, ty
::Binder
::dummy(object_trait_ref
));
400 // For each of the non-matching predicates that
401 // we pass over, we sum up the set of number of vtable
402 // entries, so that we can compute the offset for the selected
404 let vtable_base
= supertraits
407 .map(|t
| super::util
::count_own_vtable_entries(tcx
, t
))
410 let unnormalized_upcast_trait_ref
=
411 supertraits
.next().expect("supertraits iterator no longer has as many elements");
413 let upcast_trait_ref
= normalize_with_depth_to(
415 obligation
.param_env
,
416 obligation
.cause
.clone(),
417 obligation
.recursion_depth
+ 1,
418 unnormalized_upcast_trait_ref
,
422 nested
.extend(self.infcx
.commit_if_ok(|_
| {
424 .at(&obligation
.cause
, obligation
.param_env
)
425 .sup(obligation_trait_ref
, upcast_trait_ref
)
426 .map(|InferOk { obligations, .. }
| obligations
)
427 .map_err(|_
| Unimplemented
)
430 // Check supertraits hold. This is so that their associated type bounds
431 // will be checked in the code below.
432 for super_trait
in tcx
433 .super_predicates_of(trait_predicate
.def_id())
434 .instantiate(tcx
, trait_predicate
.trait_ref
.substs
)
438 if let ty
::PredicateKind
::Trait(..) = super_trait
.kind().skip_binder() {
439 let normalized_super_trait
= normalize_with_depth_to(
441 obligation
.param_env
,
442 obligation
.cause
.clone(),
443 obligation
.recursion_depth
+ 1,
447 nested
.push(Obligation
::new(
448 obligation
.cause
.clone(),
449 obligation
.param_env
,
450 normalized_super_trait
,
455 let assoc_types
: Vec
<_
> = tcx
456 .associated_items(trait_predicate
.def_id())
457 .in_definition_order()
459 |item
| if item
.kind
== ty
::AssocKind
::Type { Some(item.def_id) }
else { None }
,
463 for assoc_type
in assoc_types
{
464 if !tcx
.generics_of(assoc_type
).params
.is_empty() {
465 // FIXME(generic_associated_types) generate placeholders to
466 // extend the trait substs.
468 obligation
.cause
.span
,
469 "generic associated types in trait objects are not supported yet",
472 // This maybe belongs in wf, but that can't (doesn't) handle
473 // higher-ranked things.
474 // Prevent, e.g., `dyn Iterator<Item = str>`.
475 for bound
in self.tcx().item_bounds(assoc_type
) {
476 let subst_bound
= bound
.subst(tcx
, trait_predicate
.trait_ref
.substs
);
477 let normalized_bound
= normalize_with_depth_to(
479 obligation
.param_env
,
480 obligation
.cause
.clone(),
481 obligation
.recursion_depth
+ 1,
485 nested
.push(Obligation
::new(
486 obligation
.cause
.clone(),
487 obligation
.param_env
,
493 debug
!(?nested
, "object nested obligations");
494 Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }
)
497 fn confirm_fn_pointer_candidate(
499 obligation
: &TraitObligation
<'tcx
>,
500 ) -> Result
<ImplSourceFnPointerData
<'tcx
, PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>>
502 debug
!(?obligation
, "confirm_fn_pointer_candidate");
504 // Okay to skip binder; it is reintroduced below.
505 let self_ty
= self.infcx
.shallow_resolve(obligation
.self_ty().skip_binder());
506 let sig
= self_ty
.fn_sig(self.tcx());
507 let trait_ref
= closure_trait_ref_and_return_type(
509 obligation
.predicate
.def_id(),
512 util
::TupleArgumentsFlag
::Yes
,
514 .map_bound(|(trait_ref
, _
)| trait_ref
);
516 let Normalized { value: trait_ref, mut obligations }
= ensure_sufficient_stack(|| {
517 normalize_with_depth(
519 obligation
.param_env
,
520 obligation
.cause
.clone(),
521 obligation
.recursion_depth
+ 1,
526 obligations
.extend(self.confirm_poly_trait_refs(
527 obligation
.cause
.clone(),
528 obligation
.param_env
,
529 obligation
.predicate
.to_poly_trait_ref(),
532 Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations }
)
535 fn confirm_trait_alias_candidate(
537 obligation
: &TraitObligation
<'tcx
>,
539 ) -> ImplSourceTraitAliasData
<'tcx
, PredicateObligation
<'tcx
>> {
540 debug
!(?obligation
, ?alias_def_id
, "confirm_trait_alias_candidate");
542 self.infcx
.commit_unconditionally(|_
| {
543 let predicate
= self.infcx().replace_bound_vars_with_placeholders(obligation
.predicate
);
544 let trait_ref
= predicate
.trait_ref
;
545 let trait_def_id
= trait_ref
.def_id
;
546 let substs
= trait_ref
.substs
;
548 let trait_obligations
= self.impl_or_trait_obligations(
549 obligation
.cause
.clone(),
550 obligation
.recursion_depth
,
551 obligation
.param_env
,
556 debug
!(?trait_def_id
, ?trait_obligations
, "trait alias obligations");
558 ImplSourceTraitAliasData { alias_def_id, substs, nested: trait_obligations }
562 fn confirm_generator_candidate(
564 obligation
: &TraitObligation
<'tcx
>,
565 ) -> Result
<ImplSourceGeneratorData
<'tcx
, PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>>
567 // Okay to skip binder because the substs on generator types never
568 // touch bound regions, they just capture the in-scope
569 // type/region parameters.
570 let self_ty
= self.infcx
.shallow_resolve(obligation
.self_ty().skip_binder());
571 let (generator_def_id
, substs
) = match *self_ty
.kind() {
572 ty
::Generator(id
, substs
, _
) => (id
, substs
),
573 _
=> bug
!("closure candidate for non-closure {:?}", obligation
),
576 debug
!(?obligation
, ?generator_def_id
, ?substs
, "confirm_generator_candidate");
578 let trait_ref
= self.generator_trait_ref_unnormalized(obligation
, substs
);
579 let Normalized { value: trait_ref, mut obligations }
= ensure_sufficient_stack(|| {
580 normalize_with_depth(
582 obligation
.param_env
,
583 obligation
.cause
.clone(),
584 obligation
.recursion_depth
+ 1,
589 debug
!(?trait_ref
, ?obligations
, "generator candidate obligations");
591 obligations
.extend(self.confirm_poly_trait_refs(
592 obligation
.cause
.clone(),
593 obligation
.param_env
,
594 obligation
.predicate
.to_poly_trait_ref(),
598 Ok(ImplSourceGeneratorData { generator_def_id, substs, nested: obligations }
)
601 fn confirm_closure_candidate(
603 obligation
: &TraitObligation
<'tcx
>,
604 ) -> Result
<ImplSourceClosureData
<'tcx
, PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>> {
605 debug
!(?obligation
, "confirm_closure_candidate");
609 .fn_trait_kind_from_lang_item(obligation
.predicate
.def_id())
610 .unwrap_or_else(|| bug
!("closure candidate for non-fn trait {:?}", obligation
));
612 // Okay to skip binder because the substs on closure types never
613 // touch bound regions, they just capture the in-scope
614 // type/region parameters.
615 let self_ty
= self.infcx
.shallow_resolve(obligation
.self_ty().skip_binder());
616 let (closure_def_id
, substs
) = match *self_ty
.kind() {
617 ty
::Closure(id
, substs
) => (id
, substs
),
618 _
=> bug
!("closure candidate for non-closure {:?}", obligation
),
621 let trait_ref
= self.closure_trait_ref_unnormalized(obligation
, substs
);
622 let Normalized { value: trait_ref, mut obligations }
= ensure_sufficient_stack(|| {
623 normalize_with_depth(
625 obligation
.param_env
,
626 obligation
.cause
.clone(),
627 obligation
.recursion_depth
+ 1,
632 debug
!(?closure_def_id
, ?trait_ref
, ?obligations
, "confirm closure candidate obligations");
634 obligations
.extend(self.confirm_poly_trait_refs(
635 obligation
.cause
.clone(),
636 obligation
.param_env
,
637 obligation
.predicate
.to_poly_trait_ref(),
643 if !self.tcx().sess
.opts
.debugging_opts
.chalk
{
644 obligations
.push(Obligation
::new(
645 obligation
.cause
.clone(),
646 obligation
.param_env
,
647 ty
::PredicateKind
::ClosureKind(closure_def_id
, substs
, kind
)
648 .to_predicate(self.tcx()),
652 Ok(ImplSourceClosureData { closure_def_id, substs, nested: obligations }
)
655 /// In the case of closure types and fn pointers,
656 /// we currently treat the input type parameters on the trait as
657 /// outputs. This means that when we have a match we have only
658 /// considered the self type, so we have to go back and make sure
659 /// to relate the argument types too. This is kind of wrong, but
660 /// since we control the full set of impls, also not that wrong,
661 /// and it DOES yield better error messages (since we don't report
662 /// errors as if there is no applicable impl, but rather report
663 /// errors are about mismatched argument types.
665 /// Here is an example. Imagine we have a closure expression
666 /// and we desugared it so that the type of the expression is
667 /// `Closure`, and `Closure` expects `i32` as argument. Then it
668 /// is "as if" the compiler generated this impl:
670 /// impl Fn(i32) for Closure { ... }
672 /// Now imagine our obligation is `Closure: Fn(usize)`. So far
673 /// we have matched the self type `Closure`. At this point we'll
674 /// compare the `i32` to `usize` and generate an error.
676 /// Note that this checking occurs *after* the impl has selected,
677 /// because these output type parameters should not affect the
678 /// selection of the impl. Therefore, if there is a mismatch, we
679 /// report an error to the user.
680 fn confirm_poly_trait_refs(
682 obligation_cause
: ObligationCause
<'tcx
>,
683 obligation_param_env
: ty
::ParamEnv
<'tcx
>,
684 obligation_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
685 expected_trait_ref
: ty
::PolyTraitRef
<'tcx
>,
686 ) -> Result
<Vec
<PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>> {
688 .at(&obligation_cause
, obligation_param_env
)
689 .sup(obligation_trait_ref
, expected_trait_ref
)
690 .map(|InferOk { obligations, .. }
| obligations
)
691 .map_err(|e
| OutputTypeParameterMismatch(expected_trait_ref
, obligation_trait_ref
, e
))
694 fn confirm_builtin_unsize_candidate(
696 obligation
: &TraitObligation
<'tcx
>,
697 ) -> Result
<ImplSourceBuiltinData
<PredicateObligation
<'tcx
>>, SelectionError
<'tcx
>> {
698 let tcx
= self.tcx();
700 // `assemble_candidates_for_unsizing` should ensure there are no late-bound
701 // regions here. See the comment there for more details.
702 let source
= self.infcx
.shallow_resolve(obligation
.self_ty().no_bound_vars().unwrap());
703 let target
= obligation
.predicate
.skip_binder().trait_ref
.substs
.type_at(1);
704 let target
= self.infcx
.shallow_resolve(target
);
706 debug
!(?source
, ?target
, "confirm_builtin_unsize_candidate");
708 let mut nested
= vec
![];
709 match (source
.kind(), target
.kind()) {
710 // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
711 (&ty
::Dynamic(ref data_a
, r_a
), &ty
::Dynamic(ref data_b
, r_b
)) => {
712 // See `assemble_candidates_for_unsizing` for more info.
715 .map(|b
| b
.map_bound(ty
::ExistentialPredicate
::Trait
))
720 .map(|b
| b
.map_bound(ty
::ExistentialPredicate
::Projection
)),
725 .map(ty
::ExistentialPredicate
::AutoTrait
)
726 .map(ty
::Binder
::dummy
),
728 let existential_predicates
= tcx
.mk_poly_existential_predicates(iter
);
729 let source_trait
= tcx
.mk_dynamic(existential_predicates
, r_b
);
731 // Require that the traits involved in this upcast are **equal**;
732 // only the **lifetime bound** is changed.
733 let InferOk { obligations, .. }
= self
735 .at(&obligation
.cause
, obligation
.param_env
)
736 .sup(target
, source_trait
)
737 .map_err(|_
| Unimplemented
)?
;
738 nested
.extend(obligations
);
740 // Register one obligation for 'a: 'b.
741 let cause
= ObligationCause
::new(
742 obligation
.cause
.span
,
743 obligation
.cause
.body_id
,
744 ObjectCastObligation(target
),
746 let outlives
= ty
::OutlivesPredicate(r_a
, r_b
);
747 nested
.push(Obligation
::with_depth(
749 obligation
.recursion_depth
+ 1,
750 obligation
.param_env
,
751 ty
::Binder
::bind(outlives
).to_predicate(tcx
),
756 (_
, &ty
::Dynamic(ref data
, r
)) => {
757 let mut object_dids
= data
.auto_traits().chain(data
.principal_def_id());
758 if let Some(did
) = object_dids
.find(|did
| !tcx
.is_object_safe(*did
)) {
759 return Err(TraitNotObjectSafe(did
));
762 let cause
= ObligationCause
::new(
763 obligation
.cause
.span
,
764 obligation
.cause
.body_id
,
765 ObjectCastObligation(target
),
768 let predicate_to_obligation
= |predicate
| {
769 Obligation
::with_depth(
771 obligation
.recursion_depth
+ 1,
772 obligation
.param_env
,
777 // Create obligations:
778 // - Casting `T` to `Trait`
779 // - For all the various builtin bounds attached to the object cast. (In other
780 // words, if the object type is `Foo + Send`, this would create an obligation for
781 // the `Send` check.)
782 // - Projection predicates
784 data
.iter().map(|predicate
| {
785 predicate_to_obligation(predicate
.with_self_ty(tcx
, source
))
789 // We can only make objects from sized types.
790 let tr
= ty
::TraitRef
::new(
791 tcx
.require_lang_item(LangItem
::Sized
, None
),
792 tcx
.mk_substs_trait(source
, &[]),
794 nested
.push(predicate_to_obligation(tr
.without_const().to_predicate(tcx
)));
796 // If the type is `Foo + 'a`, ensure that the type
797 // being cast to `Foo + 'a` outlives `'a`:
798 let outlives
= ty
::OutlivesPredicate(source
, r
);
799 nested
.push(predicate_to_obligation(ty
::Binder
::dummy(outlives
).to_predicate(tcx
)));
803 (&ty
::Array(a
, _
), &ty
::Slice(b
)) => {
804 let InferOk { obligations, .. }
= self
806 .at(&obligation
.cause
, obligation
.param_env
)
808 .map_err(|_
| Unimplemented
)?
;
809 nested
.extend(obligations
);
812 // `Struct<T>` -> `Struct<U>`
813 (&ty
::Adt(def
, substs_a
), &ty
::Adt(_
, substs_b
)) => {
814 let maybe_unsizing_param_idx
= |arg
: GenericArg
<'tcx
>| match arg
.unpack() {
815 GenericArgKind
::Type(ty
) => match ty
.kind() {
816 ty
::Param(p
) => Some(p
.index
),
820 // Lifetimes aren't allowed to change during unsizing.
821 GenericArgKind
::Lifetime(_
) => None
,
823 GenericArgKind
::Const(ct
) => match ct
.val
{
824 ty
::ConstKind
::Param(p
) => Some(p
.index
),
829 // FIXME(eddyb) cache this (including computing `unsizing_params`)
830 // by putting it in a query; it would only need the `DefId` as it
831 // looks at declared field types, not anything substituted.
833 // The last field of the structure has to exist and contain type/const parameters.
834 let (tail_field
, prefix_fields
) =
835 def
.non_enum_variant().fields
.split_last().ok_or(Unimplemented
)?
;
836 let tail_field_ty
= tcx
.type_of(tail_field
.did
);
838 let mut unsizing_params
= GrowableBitSet
::new_empty();
839 if tcx
.features().relaxed_struct_unsize
{
840 for arg
in tail_field_ty
.walk() {
841 if let Some(i
) = maybe_unsizing_param_idx(arg
) {
842 unsizing_params
.insert(i
);
846 // Ensure none of the other fields mention the parameters used
848 for field
in prefix_fields
{
849 for arg
in tcx
.type_of(field
.did
).walk() {
850 if let Some(i
) = maybe_unsizing_param_idx(arg
) {
851 unsizing_params
.remove(i
);
856 if unsizing_params
.is_empty() {
857 return Err(Unimplemented
);
860 let mut found
= false;
861 for arg
in tail_field_ty
.walk() {
862 if let Some(i
) = maybe_unsizing_param_idx(arg
) {
863 unsizing_params
.insert(i
);
868 return Err(Unimplemented
);
871 // Ensure none of the other fields mention the parameters used
873 // FIXME(eddyb) cache this (including computing `unsizing_params`)
874 // by putting it in a query; it would only need the `DefId` as it
875 // looks at declared field types, not anything substituted.
876 for field
in prefix_fields
{
877 for arg
in tcx
.type_of(field
.did
).walk() {
878 if let Some(i
) = maybe_unsizing_param_idx(arg
) {
879 if unsizing_params
.contains(i
) {
880 return Err(Unimplemented
);
887 // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
888 let source_tail
= tail_field_ty
.subst(tcx
, substs_a
);
889 let target_tail
= tail_field_ty
.subst(tcx
, substs_b
);
891 // Check that the source struct with the target's
892 // unsizing parameters is equal to the target.
893 let substs
= tcx
.mk_substs(substs_a
.iter().enumerate().map(|(i
, k
)| {
894 if unsizing_params
.contains(i
as u32) { substs_b[i] }
else { k }
896 let new_struct
= tcx
.mk_adt(def
, substs
);
897 let InferOk { obligations, .. }
= self
899 .at(&obligation
.cause
, obligation
.param_env
)
900 .eq(target
, new_struct
)
901 .map_err(|_
| Unimplemented
)?
;
902 nested
.extend(obligations
);
904 // Construct the nested `TailField<T>: Unsize<TailField<U>>` predicate.
905 nested
.push(predicate_for_trait_def(
907 obligation
.param_env
,
908 obligation
.cause
.clone(),
909 obligation
.predicate
.def_id(),
910 obligation
.recursion_depth
+ 1,
912 &[target_tail
.into()],
916 // `(.., T)` -> `(.., U)`
917 (&ty
::Tuple(tys_a
), &ty
::Tuple(tys_b
)) => {
918 assert_eq
!(tys_a
.len(), tys_b
.len());
920 // The last field of the tuple has to exist.
921 let (&a_last
, a_mid
) = tys_a
.split_last().ok_or(Unimplemented
)?
;
922 let &b_last
= tys_b
.last().unwrap();
924 // Check that the source tuple with the target's
925 // last element is equal to the target.
926 let new_tuple
= tcx
.mk_tup(
927 a_mid
.iter().map(|k
| k
.expect_ty()).chain(iter
::once(b_last
.expect_ty())),
929 let InferOk { obligations, .. }
= self
931 .at(&obligation
.cause
, obligation
.param_env
)
932 .eq(target
, new_tuple
)
933 .map_err(|_
| Unimplemented
)?
;
934 nested
.extend(obligations
);
936 // Construct the nested `T: Unsize<U>` predicate.
937 nested
.push(ensure_sufficient_stack(|| {
938 predicate_for_trait_def(
940 obligation
.param_env
,
941 obligation
.cause
.clone(),
942 obligation
.predicate
.def_id(),
943 obligation
.recursion_depth
+ 1,
953 Ok(ImplSourceBuiltinData { nested }
)