Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove PredicateKind::ClosureKind #118120

Merged
merged 2 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// this closure yet; this is exactly why the other
// code is looking for a self type of an unresolved
// inference variable.
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Ambiguous
=> None,
},
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,12 +906,14 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
}

pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok())
self.probe(|_| {
self.at(origin, param_env).sub(DefineOpaqueTypes::No, expected, actual).is_ok()
})
}

pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,6 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
// Nothing to elaborate in a projection predicate.
}
ty::PredicateKind::ClosureKind(..) => {
// Nothing to elaborate when waiting for a closure's kind to be inferred.
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
// Currently, we do not elaborate const-evaluatable
// predicates.
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_middle/src/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,6 @@ impl FlagComputation {
self.add_args(slice::from_ref(&arg));
}
ty::PredicateKind::ObjectSafe(_def_id) => {}
ty::PredicateKind::ClosureKind(_def_id, args, _kind) => {
self.add_args(args);
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
self.add_const(uv);
}
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,6 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
| PredicateKind::Coerce(_)
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
Expand Down Expand Up @@ -1276,7 +1275,6 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
Expand All @@ -1296,7 +1294,6 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
Expand All @@ -1317,7 +1314,6 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
| PredicateKind::Ambiguous => None,
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2781,11 +2781,6 @@ define_print! {
ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!(
"the closure `",
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind)
),
ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1699,13 +1699,6 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
PredicateKind::ObjectSafe(did) => {
stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did))
}
PredicateKind::ClosureKind(did, generic_args, closure_kind) => {
stable_mir::ty::PredicateKind::ClosureKind(
compiler-errors marked this conversation as resolved.
Show resolved Hide resolved
tables.closure_def(*did),
generic_args.stable(tables),
closure_kind.stable(tables),
)
}
PredicateKind::Subtype(subtype_predicate) => {
stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables))
}
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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;
Expand All @@ -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)| {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand Down
14 changes: 0 additions & 14 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..))
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(..)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,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;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this slightly weakens inference, does it? we now stall closure: FnMut if we don't yet know the closure kind while we could now use that goal to infer e.g. the signature of the closure?

Copy link
Member Author

@compiler-errors compiler-errors Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, since we always make progress on a corresponding FnOnce projection that gets emitted besides it, which will always make sure we constrain the signature.

I don't immediately see a case where stalling an FnMut or Fn trait goal itself will cause inference to be affected negatively, as long as we can make progress on the projection goal and make inference progress on the closure's signature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, that's because the only stable usage of the Fn traits is via paren sugar which always results in a projection predicate as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, specifically an FnOnce projection goal, which we don't even check the closure kind in (old solver) projection.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could result in inference changes if you use the unboxed_closure syntax + raw fn_traits + custom FnMut impl with where clauses that affect inference, but that's 1. unstable, and 2. not something we can support in the new trait solver, so I don't feel particularly symathetic to that use-case even if it does exist (which I'm almost certain it does not).

}
}
}
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
}

Expand Down
13 changes: 0 additions & 13 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_traits/src/normalize_erasing_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
Expand Down
24 changes: 0 additions & 24 deletions compiler/rustc_type_ir/src/predicate_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,6 @@ pub enum PredicateKind<I: Interner> {
/// Trait must be object-safe.
ObjectSafe(I::DefId),

/// No direct syntax. May be thought of as `where T: FnFoo<...>`
/// for some generic args `...` and `T` being a closure type.
/// Satisfied (or refuted) once we know the closure's kind.
ClosureKind(I::DefId, I::GenericArgs, I::ClosureKind),

/// `T1 <: T2`
///
/// This obligation is created most often when we have two
Expand Down Expand Up @@ -173,7 +168,6 @@ where
I::Term: Copy,
I::CoercePredicate: Copy,
I::SubtypePredicate: Copy,
I::ClosureKind: Copy,
ClauseKind<I>: Copy,
{
}
Expand All @@ -183,9 +177,6 @@ impl<I: Interner> PartialEq for PredicateKind<I> {
match (self, other) {
(Self::Clause(l0), Self::Clause(r0)) => l0 == r0,
(Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0 == r0,
(Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => {
l0 == r0 && l1 == r1 && l2 == r2
}
(Self::Subtype(l0), Self::Subtype(r0)) => l0 == r0,
(Self::Coerce(l0), Self::Coerce(r0)) => l0 == r0,
(Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => l0 == r0 && l1 == r1,
Expand All @@ -207,18 +198,12 @@ where
I::Term: TypeFoldable<I>,
I::CoercePredicate: TypeFoldable<I>,
I::SubtypePredicate: TypeFoldable<I>,
I::ClosureKind: TypeFoldable<I>,
ClauseKind<I>: TypeFoldable<I>,
{
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(match self {
PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?),
PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?),
PredicateKind::ClosureKind(d, g, k) => PredicateKind::ClosureKind(
d.try_fold_with(folder)?,
g.try_fold_with(folder)?,
k.try_fold_with(folder)?,
),
PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?),
PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?),
PredicateKind::ConstEquate(a, b) => {
Expand All @@ -242,18 +227,12 @@ where
I::Term: TypeVisitable<I>,
I::CoercePredicate: TypeVisitable<I>,
I::SubtypePredicate: TypeVisitable<I>,
I::ClosureKind: TypeVisitable<I>,
ClauseKind<I>: TypeVisitable<I>,
{
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self {
PredicateKind::Clause(p) => p.visit_with(visitor),
PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
PredicateKind::ClosureKind(d, g, k) => {
d.visit_with(visitor)?;
g.visit_with(visitor)?;
k.visit_with(visitor)
}
PredicateKind::Subtype(s) => s.visit_with(visitor),
PredicateKind::Coerce(s) => s.visit_with(visitor),
PredicateKind::ConstEquate(a, b) => {
Expand Down Expand Up @@ -313,9 +292,6 @@ impl<I: Interner> fmt::Debug for PredicateKind<I> {
PredicateKind::ObjectSafe(trait_def_id) => {
write!(f, "ObjectSafe({trait_def_id:?})")
}
PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
write!(f, "ClosureKind({closure_def_id:?}, {closure_args:?}, {kind:?})")
}
PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"),
PredicateKind::Ambiguous => write!(f, "Ambiguous"),
PredicateKind::AliasRelate(t1, t2, dir) => {
Expand Down
Loading
Loading