Skip to content

Commit

Permalink
Rollup merge of rust-lang#104732 - WaffleLapkin:from_def_idn't, r=com…
Browse files Browse the repository at this point in the history
…piler-errors

Refactor `ty::ClosureKind` related stuff

I've tried to fix all duplication and weirdness, but if I missed something do tell :p

r? `@compiler-errors`
  • Loading branch information
Manishearth authored Nov 23, 2022
2 parents 8aa6ab8 + 48fee7a commit 1f1bbfc
Show file tree
Hide file tree
Showing 14 changed files with 44 additions and 60 deletions.
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
let kind = object_type
.principal_def_id()
.and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did));
.and_then(|did| self.tcx.fn_trait_kind_from_def_id(did));
(sig, kind)
}
ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates(
Expand Down Expand Up @@ -235,7 +235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
};
if let Some(closure_kind) =
trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_lang_item(def_id))
trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id))
{
expected_kind = Some(
expected_kind
Expand Down Expand Up @@ -263,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let trait_def_id = projection.trait_def_id(tcx);

let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some();
let is_fn = tcx.is_fn_trait(trait_def_id);
let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span);
let is_gen = gen_trait == trait_def_id;
if !is_fn && !is_gen {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2097,7 +2097,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
&& let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
// Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
&& let Some(call_kind) = ty::ClosureKind::from_def_id(self.tcx, maybe_trait_def_id)
&& let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
&& let Some(callee_ty) = callee_ty
{
let callee_ty = callee_ty.peel_refs();
Expand All @@ -2123,7 +2123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
if let ty::PredicateKind::Trait(pred) = predicate.kind().skip_binder()
&& pred.self_ty().peel_refs() == callee_ty
&& ty::ClosureKind::from_def_id(self.tcx, pred.def_id()).is_some()
&& self.tcx.is_fn_trait(pred.def_id())
{
err.span_note(span, "callable defined here");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);

if self_ty.value.is_closure()
&& self
.tcx()
.fn_trait_kind_from_lang_item(expected_trait_ref.value.def_id)
.is_some()
&& self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
{
let closure_sig = self_ty.map(|closure| {
if let ty::Closure(_, substs) = closure.kind() {
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_middle/src/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ impl<'tcx> TyCtxt<'tcx> {
})
}

pub fn fn_trait_kind_from_lang_item(self, id: DefId) -> Option<ty::ClosureKind> {
/// Given a [`DefId`] of a [`Fn`], [`FnMut`] or [`FnOnce`] traits,
/// returns a corresponding [`ty::ClosureKind`].
/// For any other [`DefId`] return `None`.
pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option<ty::ClosureKind> {
let items = self.lang_items();
match Some(id) {
x if x == items.fn_trait() => Some(ty::ClosureKind::Fn),
Expand All @@ -36,6 +39,11 @@ impl<'tcx> TyCtxt<'tcx> {
_ => None,
}
}

/// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits.
pub fn is_fn_trait(self, id: DefId) -> bool {
self.fn_trait_kind_from_def_id(id).is_some()
}
}

/// Returns `true` if the specified `lang_item` must be present for this
Expand Down
41 changes: 12 additions & 29 deletions compiler/rustc_middle/src/ty/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,18 @@ impl<'tcx> ClosureKind {
/// Returns `true` if a type that impls this closure kind
/// must also implement `other`.
pub fn extends(self, other: ty::ClosureKind) -> bool {
matches!(
(self, other),
(ClosureKind::Fn, ClosureKind::Fn)
| (ClosureKind::Fn, ClosureKind::FnMut)
| (ClosureKind::Fn, ClosureKind::FnOnce)
| (ClosureKind::FnMut, ClosureKind::FnMut)
| (ClosureKind::FnMut, ClosureKind::FnOnce)
| (ClosureKind::FnOnce, ClosureKind::FnOnce)
)
self <= other
}

/// Converts `self` to a [`DefId`] of the corresponding trait.
///
/// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`].
pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId {
match self {
ClosureKind::Fn => tcx.lang_items().fn_once_trait().unwrap(),
ClosureKind::FnMut => tcx.lang_items().fn_mut_trait().unwrap(),
ClosureKind::FnOnce => tcx.lang_items().fn_trait().unwrap(),
}
}

/// Returns the representative scalar type for this closure kind.
Expand All @@ -116,26 +119,6 @@ impl<'tcx> ClosureKind {
ClosureKind::FnOnce => tcx.types.i32,
}
}

pub fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ClosureKind> {
if Some(def_id) == tcx.lang_items().fn_once_trait() {
Some(ClosureKind::FnOnce)
} else if Some(def_id) == tcx.lang_items().fn_mut_trait() {
Some(ClosureKind::FnMut)
} else if Some(def_id) == tcx.lang_items().fn_trait() {
Some(ClosureKind::Fn)
} else {
None
}
}

pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId {
match self {
ClosureKind::Fn => tcx.lang_items().fn_once_trait().unwrap(),
ClosureKind::FnMut => tcx.lang_items().fn_mut_trait().unwrap(),
ClosureKind::FnOnce => tcx.lang_items().fn_trait().unwrap(),
}
}
}

/// A composite describing a `Place` that is captured by a closure.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ pub trait PrettyPrinter<'tcx>:
let mut resugared = false;

// Special-case `Fn(...) -> ...` and re-sugar it.
let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id);
let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id);
if !cx.should_print_verbose() && fn_trait_kind.is_some() {
if let ty::Tuple(tys) = principal.substs.type_at(0).kind() {
let mut projections = predicates.projection_bounds();
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2130,8 +2130,7 @@ impl<'tcx> Ty<'tcx> {
/// parameter. This is kind of a phantom type, except that the
/// most convenient thing for us to are the integral types. This
/// function converts such a special type into the closure
/// kind. To go the other way, use
/// `tcx.closure_kind_ty(closure_kind)`.
/// kind. To go the other way, use `closure_kind.to_ty(tcx)`.
///
/// Note that during type checking, we use an inference variable
/// to represent the closure kind, because it has not yet been
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
}
ty::InstanceDef::FnPtrShim(def_id, ty) => {
let trait_ = tcx.trait_of_item(def_id).unwrap();
let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) {
let adjustment = match tcx.fn_trait_kind_from_def_id(trait_) {
Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
Some(ty::ClosureKind::FnMut | ty::ClosureKind::Fn) => Adjustment::Deref,
None => bug!("fn pointer {:?} is not an fn", ty),
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fulfill_cx.register_predicate_obligation(self, obligation);
if fulfill_cx.select_all_or_error(self).is_empty() {
return Ok((
ty::ClosureKind::from_def_id(self.tcx, trait_def_id)
self.tcx
.fn_trait_kind_from_def_id(trait_def_id)
.expect("expected to map DefId to ClosureKind"),
ty.rebind(self.resolve_vars_if_possible(var)),
));
Expand Down Expand Up @@ -687,7 +688,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::BindingObligation(def_id, _)
| ObligationCauseCode::ItemObligation(def_id)
if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() =>
if tcx.is_fn_trait(*def_id) =>
{
err.code(rustc_errors::error_code!(E0059));
err.set_primary_message(format!(
Expand Down Expand Up @@ -847,8 +848,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}

let is_fn_trait =
ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some();
let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id());
let is_target_feature_fn = if let ty::FnDef(def_id, _) =
*trait_ref.skip_binder().self_ty().kind()
{
Expand Down Expand Up @@ -878,7 +878,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Note if the `FnMut` or `FnOnce` is less general than the trait we're trying
// to implement.
let selected_kind =
ty::ClosureKind::from_def_id(self.tcx, trait_ref.def_id())
self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id())
.expect("expected to map DefId to ClosureKind");
if !implemented_kind.extends(selected_kind) {
err.note(
Expand Down Expand Up @@ -2154,7 +2154,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if generics.params.iter().any(|p| p.name != kw::SelfUpper)
&& !snippet.ends_with('>')
&& !generics.has_impl_trait()
&& !self.tcx.fn_trait_kind_from_lang_item(def_id).is_some()
&& !self.tcx.is_fn_trait(def_id)
{
// FIXME: To avoid spurious suggestions in functions where type arguments
// where already supplied, we check the snippet to make sure it doesn't
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1684,9 +1684,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> Ty<'tcx> {
let inputs = trait_ref.skip_binder().substs.type_at(1);
let sig = match inputs.kind() {
ty::Tuple(inputs)
if infcx.tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() =>
{
ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
infcx.tcx.mk_fn_sig(
inputs.iter(),
infcx.next_ty_var(TypeVariableOrigin {
Expand Down Expand Up @@ -1757,7 +1755,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&& let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
&& let Some(pred) = predicates.predicates.get(*idx)
&& let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder()
&& ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()).is_some()
&& self.tcx.is_fn_trait(trait_pred.def_id())
{
let expected_self =
self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
Expand All @@ -1771,8 +1769,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.enumerate()
.find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(trait_pred)
if ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id())
.is_some()
if self.tcx.is_fn_trait(trait_pred.def_id())
&& other_idx != idx
// Make sure that the self type matches
// (i.e. constraining this closure)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let Some(kind) = self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) else {
let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
return;
};

Expand Down Expand Up @@ -473,7 +473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// We provide impl of all fn traits for fn pointers.
if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() {
if !self.tcx().is_fn_trait(obligation.predicate.def_id()) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,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
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ fn resolve_associated_item<'tcx>(
substs: generator_data.substs,
}),
traits::ImplSource::Closure(closure_data) => {
let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
Instance::resolve_closure(
tcx,
closure_data.closure_def_id,
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fn external_generic_args<'tcx>(
) -> GenericArgs {
let args = substs_to_args(cx, substs, has_self);

if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
let inputs =
// The trait's first substitution is the one after self, if there is one.
match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
Expand Down

0 comments on commit 1f1bbfc

Please sign in to comment.