1
Fork 0

Auto merge of #118120 - compiler-errors:closure-kind, r=lcnr

Remove `PredicateKind::ClosureKind`

We don't need the `ClosureKind` predicate kind -- instead, `Fn`-family trait goals are left as ambiguous, and we only need to make progress on `FnOnce` projection goals for inference purposes.

This is similar to how we do confirmation of `Fn`-family trait and projection goals in the new trait solver, which also doesn't use the `ClosureKind` predicate.

Some hacky logic is added in the second commit so that we can keep the error messages the same.
This commit is contained in:
bors 2023-11-22 21:09:01 +00:00
commit 1e9dda77b5
19 changed files with 53 additions and 102 deletions

View file

@ -406,8 +406,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::Coerce(predicate) => {
self.compute_coerce_goal(Goal { param_env, predicate })
}
ty::PredicateKind::ClosureKind(def_id, args, kind) => self
.compute_closure_kind_goal(Goal { param_env, predicate: (def_id, args, kind) }),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
self.compute_object_safe_goal(trait_def_id)
}

View file

@ -135,7 +135,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
}
ty::PredicateKind::Clause(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::Ambiguous => {
FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,

View file

@ -822,7 +822,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
// FIXME(generic_const_exprs): you can absolutely add this as a where clauses
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))

View file

@ -98,6 +98,12 @@ pub trait TypeErrCtxtExt<'tcx> {
error: &SelectionError<'tcx>,
);
fn emit_specialized_closure_kind_error(
&self,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Option<ErrorGuaranteed>;
fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool;
fn report_const_param_not_wf(
@ -411,6 +417,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
let trait_ref = trait_predicate.to_poly_trait_ref();
if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
return;
}
// FIXME(effects)
let predicate_is_const = false;
@ -425,7 +436,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// reported on the binding definition (#56607).
return;
}
let trait_ref = trait_predicate.to_poly_trait_ref();
let (post_message, pre_message, type_def, file_note) = self
.get_parent_trait_ref(obligation.cause.code())
.map(|(t, s)| {
@ -786,11 +796,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
report_object_safety_error(self.tcx, span, trait_def_id, violations)
}
ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
let found_kind = self.closure_kind(closure_args).unwrap();
self.report_closure_error(&obligation, closure_def_id, found_kind, kind)
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
let ty = self.resolve_vars_if_possible(ty);
match self.tcx.sess.opts.unstable_opts.trait_solver {
@ -927,6 +932,38 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.emit();
}
fn emit_specialized_closure_kind_error(
&self,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Option<ErrorGuaranteed> {
if let ty::Closure(closure_def_id, closure_args) = *trait_ref.self_ty().skip_binder().kind()
&& let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id())
&& let Some(found_kind) = self.closure_kind(closure_args)
&& !found_kind.extends(expected_kind)
&& let sig = closure_args.as_closure().sig()
&& self.can_sub(
obligation.param_env,
trait_ref,
sig.map_bound(|sig| {
ty::TraitRef::new(
self.tcx,
trait_ref.def_id(),
[trait_ref.self_ty().skip_binder(), sig.inputs()[0]],
)
}),
)
{
let mut err =
self.report_closure_error(&obligation, closure_def_id, found_kind, expected_kind);
self.note_obligation_cause(&mut err, &obligation);
self.point_at_returns_when_relevant(&mut err, &obligation);
Some(err.emit())
} else {
None
}
}
fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool {
if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
obligation.cause.code()

View file

@ -350,7 +350,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
@ -411,19 +410,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
}
ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
match self.selcx.infcx.closure_kind(closure_args) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
ProcessResult::Changed(vec![])
} else {
ProcessResult::Error(CodeSelectionError(Unimplemented))
}
}
None => ProcessResult::Unchanged,
}
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
match wf::obligations(
self.selcx.infcx,

View file

@ -130,7 +130,6 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)

View file

@ -288,8 +288,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
None => {
debug!("assemble_unboxed_candidates: closure_kind not yet known");
candidates.vec.push(ClosureCandidate { is_const });
if kind == ty::ClosureKind::FnOnce {
candidates.vec.push(ClosureCandidate { is_const });
} else {
candidates.ambiguous = true;
}
}
}
}

View file

@ -821,11 +821,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.
@ -835,15 +830,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
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)
}

View file

@ -885,19 +885,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
match self.infcx.closure_kind(closure_args) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
Ok(EvaluatedToOk)
} else {
Ok(EvaluatedToErr)
}
}
None => Ok(EvaluatedToAmbig),
}
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
match const_evaluatable::is_const_evaluatable(
self.infcx,