summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/select/confirmation.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs214
1 files changed, 121 insertions, 93 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index ed22058c6..fda415155 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -19,14 +19,18 @@ use rustc_span::def_id::DefId;
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
+use crate::traits::vtable::{
+ count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
+ VtblSegment,
+};
use crate::traits::{
BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
- ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
- ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
+ ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
+ ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
- SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
+ SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
};
use super::BuiltinImplConditions;
@@ -89,17 +93,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::Generator(vtable_generator)
}
+ FutureCandidate => {
+ let vtable_future = self.confirm_future_candidate(obligation)?;
+ ImplSource::Future(vtable_future)
+ }
+
FnPointerCandidate { .. } => {
let data = self.confirm_fn_pointer_candidate(obligation)?;
ImplSource::FnPointer(data)
}
- DiscriminantKindCandidate => {
- ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- }
-
- PointeeCandidate => ImplSource::Pointee(ImplSourcePointeeData),
-
TraitAliasCandidate => {
let data = self.confirm_trait_alias_candidate(obligation);
ImplSource::TraitAlias(data)
@@ -148,7 +151,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref;
+ self.infcx.replace_bound_vars_with_placeholders(trait_predicate).trait_ref;
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, substs) = match *placeholder_self_ty.kind() {
@@ -194,6 +197,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut obligations,
);
obligations.push(Obligation::with_depth(
+ self.tcx(),
obligation.cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
@@ -482,11 +486,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
super_trait,
&mut nested,
);
- nested.push(Obligation::new(
- obligation.cause.clone(),
- obligation.param_env,
- normalized_super_trait,
- ));
+ nested.push(obligation.with(tcx, normalized_super_trait));
}
let assoc_types: Vec<_> = tcx
@@ -555,13 +555,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
GenericParamDefKind::Const { .. } => {
let bound_var = ty::BoundVariableKind::Const;
bound_vars.push(bound_var);
- tcx.mk_const(ty::ConstS {
- ty: tcx.type_of(param.def_id),
- kind: ty::ConstKind::Bound(
+ tcx.mk_const(
+ ty::ConstKind::Bound(
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
),
- })
+ tcx.type_of(param.def_id),
+ )
.into()
}
});
@@ -581,17 +581,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
subst_bound,
&mut nested,
);
- nested.push(Obligation::new(
- obligation.cause.clone(),
- obligation.param_env,
- normalized_bound,
- ));
+ nested.push(obligation.with(tcx, normalized_bound));
}
}
debug!(?nested, "object nested obligations");
- let vtable_base = super::super::vtable_trait_first_method_offset(
+ let vtable_base = vtable_trait_first_method_offset(
tcx,
(unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
);
@@ -606,8 +602,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
{
debug!(?obligation, "confirm_fn_pointer_candidate");
- // Okay to skip binder; it is reintroduced below.
- let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+ let self_ty = self
+ .infcx
+ .shallow_resolve(obligation.self_ty().no_bound_vars())
+ .expect("fn pointer should not capture bound vars from predicate");
let sig = self_ty.fn_sig(self.tcx());
let trait_ref = closure_trait_ref_and_return_type(
self.tcx(),
@@ -622,15 +620,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
let cause = obligation.derived_cause(BuiltinDerivedObligation);
- // The binder on the Fn obligation is "less" important than the one on
- // the signature, as evidenced by how we treat it during projection.
- // The safe thing to do here is to liberate it, though, which should
- // have no worse effect than skipping the binder here.
- let liberated_fn_ty =
- self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty));
- let output_ty = self
- .infcx
- .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output());
+ let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output());
let output_ty = normalize_with_depth_to(
self,
obligation.param_env,
@@ -639,15 +629,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
output_ty,
&mut nested,
);
- let tr = ty::Binder::dummy(ty::TraitRef::new(
- self.tcx().require_lang_item(LangItem::Sized, None),
- self.tcx().mk_substs_trait(output_ty, &[]),
- ));
- nested.push(Obligation::new(
- cause,
- obligation.param_env,
- tr.to_poly_trait_predicate().to_predicate(self.tcx()),
- ));
+ let tr =
+ ty::Binder::dummy(self.tcx().at(cause.span).mk_trait_ref(LangItem::Sized, [output_ty]));
+ nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
}
@@ -659,7 +643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, "confirm_trait_alias_candidate");
let alias_def_id = obligation.predicate.def_id();
- let predicate = self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
+ let predicate = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
let substs = trait_ref.substs;
@@ -693,7 +677,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate");
- let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs);
+ let gen_sig = substs.as_generator().poly_sig();
+
+ // NOTE: The self-type is a generator type and hence is
+ // in fact unparameterized (or at least does not reference any
+ // regions bound in the obligation).
+ let self_ty = obligation
+ .predicate
+ .self_ty()
+ .no_bound_vars()
+ .expect("unboxed closure type should not capture bound vars from the predicate");
+
+ let trait_ref = super::util::generator_trait_ref_and_outputs(
+ self.tcx(),
+ obligation.predicate.def_id(),
+ self_ty,
+ gen_sig,
+ )
+ .map_bound(|(trait_ref, ..)| trait_ref);
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?trait_ref, ?nested, "generator candidate obligations");
@@ -701,6 +702,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
}
+ fn confirm_future_candidate(
+ &mut self,
+ obligation: &TraitObligation<'tcx>,
+ ) -> Result<ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ // Okay to skip binder because the substs on generator types never
+ // touch bound regions, they just capture the in-scope
+ // type/region parameters.
+ let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+ let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+ bug!("closure candidate for non-closure {:?}", obligation);
+ };
+
+ debug!(?obligation, ?generator_def_id, ?substs, "confirm_future_candidate");
+
+ let gen_sig = substs.as_generator().poly_sig();
+
+ let trait_ref = super::util::future_trait_ref_and_outputs(
+ self.tcx(),
+ obligation.predicate.def_id(),
+ obligation.predicate.no_bound_vars().expect("future has no bound vars").self_ty(),
+ gen_sig,
+ )
+ .map_bound(|(trait_ref, ..)| trait_ref);
+
+ let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ debug!(?trait_ref, ?nested, "future candidate obligations");
+
+ Ok(ImplSourceFutureData { generator_def_id, substs, nested })
+ }
+
#[instrument(skip(self), level = "debug")]
fn confirm_closure_candidate(
&mut self,
@@ -708,7 +739,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let kind = self
.tcx()
- .fn_trait_kind_from_lang_item(obligation.predicate.def_id())
+ .fn_trait_kind_from_def_id(obligation.predicate.def_id())
.unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
// Okay to skip binder because the substs on closure types never
@@ -727,11 +758,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// FIXME: Chalk
if !self.tcx().sess.opts.unstable_opts.chalk {
- nested.push(Obligation::new(
- obligation.cause.clone(),
- obligation.param_env,
- ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind))
- .to_predicate(self.tcx()),
+ nested.push(obligation.with(
+ self.tcx(),
+ ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
));
}
@@ -813,9 +842,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let upcast_trait_ref;
match (source.kind(), target.kind()) {
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
- (&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b))
- if repr_a == repr_b =>
- {
+ (
+ &ty::Dynamic(ref data_a, r_a, repr_a @ ty::Dyn),
+ &ty::Dynamic(ref data_b, r_b, ty::Dyn),
+ ) => {
// See `assemble_candidates_for_unsizing` for more info.
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
let principal_a = data_a.principal().unwrap();
@@ -841,7 +871,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::Binder::dummy),
);
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
- let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b);
+ let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a);
// Require that the traits involved in this upcast are **equal**;
// only the **lifetime bound** is changed.
@@ -860,10 +890,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
+ tcx,
cause,
obligation.recursion_depth + 1,
obligation.param_env,
- obligation.predicate.rebind(outlives).to_predicate(tcx),
+ obligation.predicate.rebind(outlives),
));
}
_ => bug!(),
@@ -877,7 +908,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
}
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
- vptr_offset += util::count_own_vtable_entries(tcx, trait_ref);
+ vptr_offset += count_own_vtable_entries(tcx, trait_ref);
if trait_ref == upcast_trait_ref {
if emit_vptr {
return ControlFlow::Break(Some(vptr_offset));
@@ -896,8 +927,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
let vtable_vptr_slot =
- super::super::prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback)
- .unwrap();
+ prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested })
}
@@ -919,7 +949,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let mut nested = vec![];
match (source.kind(), target.kind()) {
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
- (&ty::Dynamic(ref data_a, r_a, ty::Dyn), &ty::Dynamic(ref data_b, r_b, ty::Dyn)) => {
+ (&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b))
+ if dyn_a == dyn_b =>
+ {
// See `assemble_candidates_for_unsizing` for more info.
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
let iter = data_a
@@ -938,7 +970,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::Binder::dummy),
);
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
- let source_trait = tcx.mk_dynamic(existential_predicates, r_b, ty::Dyn);
+ let source_trait = tcx.mk_dynamic(existential_predicates, r_b, dyn_a);
// Require that the traits involved in this upcast are **equal**;
// only the **lifetime bound** is changed.
@@ -957,10 +989,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(
+ tcx,
cause,
obligation.recursion_depth + 1,
obligation.param_env,
- obligation.predicate.rebind(outlives).to_predicate(tcx),
+ obligation.predicate.rebind(outlives),
));
}
@@ -979,6 +1012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let predicate_to_obligation = |predicate| {
Obligation::with_depth(
+ tcx,
cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
@@ -999,10 +1033,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
// We can only make objects from sized types.
- let tr = ty::Binder::dummy(ty::TraitRef::new(
- tcx.require_lang_item(LangItem::Sized, None),
- tcx.mk_substs_trait(source, &[]),
- ));
+ let tr =
+ ty::Binder::dummy(tcx.at(cause.span).mk_trait_ref(LangItem::Sized, [source]));
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
// If the type is `Foo + 'a`, ensure that the type
@@ -1108,8 +1140,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.cause.clone(),
obligation.predicate.def_id(),
obligation.recursion_depth + 1,
- source_tail,
- &[target_tail.into()],
+ [source_tail, target_tail],
));
}
@@ -1139,13 +1170,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.cause.clone(),
obligation.predicate.def_id(),
obligation.recursion_depth + 1,
- a_last,
- &[b_last.into()],
+ [a_last, b_last],
)
}));
}
- _ => bug!(),
+ _ => bug!("source: {source}, target: {target}"),
};
Ok(ImplSourceBuiltinData { nested })
@@ -1255,20 +1285,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.param_env,
cause.clone(),
obligation.recursion_depth + 1,
- self_ty
- .rebind(ty::TraitPredicate {
- trait_ref: ty::TraitRef {
- def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
- substs: self.tcx().mk_substs_trait(nested_ty, &[]),
- },
- constness: ty::BoundConstness::ConstIfConst,
- polarity: ty::ImplPolarity::Positive,
- })
- .to_predicate(tcx),
+ self_ty.rebind(ty::TraitPredicate {
+ trait_ref: self
+ .tcx()
+ .at(cause.span)
+ .mk_trait_ref(LangItem::Destruct, [nested_ty]),
+ constness: ty::BoundConstness::ConstIfConst,
+ polarity: ty::ImplPolarity::Positive,
+ }),
&mut nested,
);
nested.push(Obligation::with_depth(
+ tcx,
cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
@@ -1280,18 +1309,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// since it's either not `const Drop` (and we raise an error during selection),
// or it's an ADT (and we need to check for a custom impl during selection)
_ => {
- let predicate = self_ty
- .rebind(ty::TraitPredicate {
- trait_ref: ty::TraitRef {
- def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
- substs: self.tcx().mk_substs_trait(nested_ty, &[]),
- },
- constness: ty::BoundConstness::ConstIfConst,
- polarity: ty::ImplPolarity::Positive,
- })
- .to_predicate(tcx);
+ let predicate = self_ty.rebind(ty::TraitPredicate {
+ trait_ref: self
+ .tcx()
+ .at(cause.span)
+ .mk_trait_ref(LangItem::Destruct, [nested_ty]),
+ constness: ty::BoundConstness::ConstIfConst,
+ polarity: ty::ImplPolarity::Positive,
+ });
nested.push(Obligation::with_depth(
+ tcx,
cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,