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.rs135
1 files changed, 81 insertions, 54 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 4bfa341e3..ce3fc2185 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -9,7 +9,7 @@
use rustc_ast::Mutability;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
+use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
use rustc_middle::ty::{
@@ -71,7 +71,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
- ProjectionCandidate(idx, _) => {
+ ProjectionCandidate(idx) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?;
ImplSource::Param(obligations)
}
@@ -98,8 +98,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::Builtin(BuiltinImplSource::Misc, vtable_iterator)
}
- FnPointerCandidate { is_const } => {
- let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
+ AsyncIteratorCandidate => {
+ let vtable_iterator = self.confirm_async_iterator_candidate(obligation)?;
+ ImplSource::Builtin(BuiltinImplSource::Misc, vtable_iterator)
+ }
+
+ FnPointerCandidate { fn_host_effect } => {
+ let data = self.confirm_fn_pointer_candidate(obligation, fn_host_effect)?;
ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
@@ -327,8 +332,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// care about other regions. Erasing late-bound regions is equivalent
// to instantiating the binder with placeholders then erasing those
// placeholder regions.
- let predicate =
- self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate));
+ let predicate = self
+ .tcx()
+ .erase_regions(self.tcx().instantiate_bound_regions_with_erased(obligation.predicate));
let Some(assume) = rustc_transmute::Assume::from_const(
self.infcx.tcx,
@@ -393,7 +399,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.recursion_depth + 1,
obligation.param_env,
trait_def_id,
- &trait_ref.args,
+ trait_ref.args,
obligation.predicate,
);
@@ -454,7 +460,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
recursion_depth,
param_env,
impl_def_id,
- &args.value,
+ args.value,
parent_trait_pred,
);
@@ -552,7 +558,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let defs: &ty::Generics = tcx.generics_of(assoc_type);
if !defs.params.is_empty() && !tcx.features().generic_associated_types_extended {
- tcx.sess.delay_span_bug(
+ tcx.sess.span_delayed_bug(
obligation.cause.span,
"GATs in trait object shouldn't have been considered",
);
@@ -592,7 +598,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
- ty::Region::new_late_bound(
+ ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion {
@@ -647,8 +653,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_fn_pointer_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
- // FIXME(effects)
- _is_const: bool,
+ fn_host_effect: ty::Const<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_fn_pointer_candidate");
@@ -669,6 +674,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self_ty,
sig,
util::TupleArgumentsFlag::Yes,
+ fn_host_effect,
)
.map_bound(|(trait_ref, _)| trait_ref);
@@ -707,7 +713,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.recursion_depth,
obligation.param_env,
trait_def_id,
- &args,
+ args,
obligation.predicate,
);
@@ -730,7 +736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, ?coroutine_def_id, ?args, "confirm_coroutine_candidate");
- let coroutine_sig = args.as_coroutine().poly_sig();
+ let coroutine_sig = args.as_coroutine().sig();
// NOTE: The self-type is a coroutine type and hence is
// in fact unparameterized (or at least does not reference any
@@ -741,15 +747,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.no_bound_vars()
.expect("unboxed closure type should not capture bound vars from the predicate");
- let trait_ref = super::util::coroutine_trait_ref_and_outputs(
+ let (trait_ref, _, _) = super::util::coroutine_trait_ref_and_outputs(
self.tcx(),
obligation.predicate.def_id(),
self_ty,
coroutine_sig,
- )
- .map_bound(|(trait_ref, ..)| trait_ref);
+ );
- let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
debug!(?trait_ref, ?nested, "coroutine candidate obligations");
Ok(nested)
@@ -769,17 +774,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, ?coroutine_def_id, ?args, "confirm_future_candidate");
- let coroutine_sig = args.as_coroutine().poly_sig();
+ let coroutine_sig = args.as_coroutine().sig();
- let trait_ref = super::util::future_trait_ref_and_outputs(
+ 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(),
coroutine_sig,
- )
- .map_bound(|(trait_ref, ..)| trait_ref);
+ );
- let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
debug!(?trait_ref, ?nested, "future candidate obligations");
Ok(nested)
@@ -799,17 +803,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, ?coroutine_def_id, ?args, "confirm_iterator_candidate");
- let gen_sig = args.as_coroutine().poly_sig();
+ let gen_sig = args.as_coroutine().sig();
- let trait_ref = super::util::iterator_trait_ref_and_outputs(
+ let (trait_ref, _) = super::util::iterator_trait_ref_and_outputs(
self.tcx(),
obligation.predicate.def_id(),
obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(),
gen_sig,
- )
- .map_bound(|(trait_ref, ..)| trait_ref);
+ );
- let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
+ debug!(?trait_ref, ?nested, "iterator candidate obligations");
+
+ Ok(nested)
+ }
+
+ fn confirm_async_iterator_candidate(
+ &mut self,
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ // Okay to skip binder because the args on coroutine 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::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else {
+ bug!("closure candidate for non-closure {:?}", obligation);
+ };
+
+ debug!(?obligation, ?coroutine_def_id, ?args, "confirm_async_iterator_candidate");
+
+ let gen_sig = args.as_coroutine().sig();
+
+ let (trait_ref, _) = super::util::async_iterator_trait_ref_and_outputs(
+ self.tcx(),
+ obligation.predicate.def_id(),
+ obligation.predicate.no_bound_vars().expect("iterator has no bound vars").self_ty(),
+ gen_sig,
+ );
+
+ let nested = self.confirm_poly_trait_refs(obligation, ty::Binder::dummy(trait_ref))?;
debug!(?trait_ref, ?nested, "iterator candidate obligations");
Ok(nested)
@@ -820,11 +852,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- let kind = self
- .tcx()
- .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 args on closure types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
@@ -833,16 +860,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
bug!("closure candidate for non-closure {:?}", obligation);
};
- let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
- let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let trait_ref =
+ self.closure_trait_ref_unnormalized(obligation, args, self.tcx().consts.true_);
+ let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
- nested.push(obligation.with(
- self.tcx(),
- ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)),
- ));
-
Ok(nested)
}
@@ -920,8 +943,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let a_ty = self.infcx.shallow_resolve(predicate.self_ty());
let b_ty = self.infcx.shallow_resolve(predicate.trait_ref.args.type_at(1));
- let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { bug!() };
- let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { bug!() };
+ let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else {
+ bug!("expected `dyn` type in `confirm_trait_upcasting_unsize_candidate`")
+ };
+ let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
+ bug!("expected `dyn` type in `confirm_trait_upcasting_unsize_candidate`")
+ };
let source_principal = a_data.principal().unwrap().with_self_ty(tcx, a_ty);
let unnormalized_upcast_principal =
@@ -985,7 +1012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(match (source.kind(), target.kind()) {
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
- (&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b))
+ (&ty::Dynamic(data_a, r_a, dyn_a), &ty::Dynamic(data_b, r_b, dyn_b))
if dyn_a == dyn_b =>
{
// See `assemble_candidates_for_unsizing` for more info.
@@ -1030,7 +1057,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
// `T` -> `Trait`
- (_, &ty::Dynamic(ref data, r, ty::Dyn)) => {
+ (_, &ty::Dynamic(data, r, ty::Dyn)) => {
let mut object_dids = data.auto_traits().chain(data.principal_def_id());
if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) {
return Err(TraitNotObjectSafe(did));
@@ -1184,11 +1211,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PolyTraitObligation<'tcx>,
impl_def_id: Option<DefId>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
- // FIXME(effects)
- if true {
- return Ok(vec![]);
- }
+ let Some(host_effect_index) =
+ self.tcx().generics_of(obligation.predicate.def_id()).host_effect_index
+ else {
+ bug!()
+ };
+ let host_effect_param: ty::GenericArg<'tcx> =
+ obligation.predicate.skip_binder().trait_ref.args.const_at(host_effect_index).into();
let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
@@ -1277,7 +1306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tcx = self.tcx();
stack.extend(tcx.coroutine_hidden_types(def_id).map(|bty| {
let ty = bty.instantiate(tcx, args);
- debug_assert!(!ty.has_late_bound_regions());
+ debug_assert!(!ty.has_bound_regions());
ty
}))
}
@@ -1285,7 +1314,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
ty::Alias(ty::Projection | ty::Inherent, ..) => {
- // FIXME(effects) this needs constness
let predicate = normalize_with_depth_to(
self,
obligation.param_env,
@@ -1296,7 +1324,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.tcx(),
LangItem::Destruct,
cause.span,
- [nested_ty],
+ [nested_ty.into(), host_effect_param],
),
polarity: ty::ImplPolarity::Positive,
}),
@@ -1316,13 +1344,12 @@ 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)
_ => {
- // FIXME(effects) this needs constness
let predicate = self_ty.rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef::from_lang_item(
self.tcx(),
LangItem::Destruct,
cause.span,
- [nested_ty],
+ [nested_ty.into(), host_effect_param],
),
polarity: ty::ImplPolarity::Positive,
});