Check FnPtr/FnDef built-in fn traits correctly with effects
This commit is contained in:
@@ -355,17 +355,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// Provide an impl, but only for suitable `fn` pointers.
|
||||
ty::FnPtr(sig) => {
|
||||
if sig.is_fn_trait_compatible() {
|
||||
candidates.vec.push(FnPointerCandidate { is_const: false });
|
||||
candidates
|
||||
.vec
|
||||
.push(FnPointerCandidate { fn_host_effect: self.tcx().consts.true_ });
|
||||
}
|
||||
}
|
||||
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
||||
ty::FnDef(def_id, _) => {
|
||||
if self.tcx().fn_sig(def_id).skip_binder().is_fn_trait_compatible()
|
||||
&& self.tcx().codegen_fn_attrs(def_id).target_features.is_empty()
|
||||
ty::FnDef(def_id, args) => {
|
||||
let tcx = self.tcx();
|
||||
if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
|
||||
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||
{
|
||||
candidates
|
||||
.vec
|
||||
.push(FnPointerCandidate { is_const: self.tcx().is_const_fn(def_id) });
|
||||
candidates.vec.push(FnPointerCandidate {
|
||||
fn_host_effect: tcx
|
||||
.generics_of(def_id)
|
||||
.host_effect_index
|
||||
.map_or(tcx.consts.true_, |idx| args.const_at(idx)),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -103,8 +103,8 @@ 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)?;
|
||||
FnPointerCandidate { fn_host_effect } => {
|
||||
let data = self.confirm_fn_pointer_candidate(obligation, fn_host_effect)?;
|
||||
ImplSource::Builtin(BuiltinImplSource::Misc, data)
|
||||
}
|
||||
|
||||
@@ -653,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");
|
||||
|
||||
@@ -675,6 +674,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
self_ty,
|
||||
sig,
|
||||
util::TupleArgumentsFlag::Yes,
|
||||
fn_host_effect,
|
||||
)
|
||||
.map_bound(|(trait_ref, _)| trait_ref);
|
||||
|
||||
@@ -860,7 +860,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
bug!("closure candidate for non-closure {:?}", obligation);
|
||||
};
|
||||
|
||||
let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
|
||||
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");
|
||||
|
||||
@@ -1865,7 +1865,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
}
|
||||
|
||||
// Drop otherwise equivalent non-const fn pointer candidates
|
||||
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => DropVictim::Yes,
|
||||
(FnPointerCandidate { .. }, FnPointerCandidate { fn_host_effect }) => {
|
||||
DropVictim::drop_if(*fn_host_effect == self.tcx().consts.true_)
|
||||
}
|
||||
|
||||
(
|
||||
ParamCandidate(ref other_cand),
|
||||
@@ -2660,6 +2662,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
fn_host_effect: ty::Const<'tcx>,
|
||||
) -> ty::PolyTraitRef<'tcx> {
|
||||
let closure_sig = args.as_closure().sig();
|
||||
|
||||
@@ -2680,6 +2683,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
self_ty,
|
||||
closure_sig,
|
||||
util::TupleArgumentsFlag::No,
|
||||
fn_host_effect,
|
||||
)
|
||||
.map_bound(|(trait_ref, _)| trait_ref)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user