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

Delegation: partial generics support #123958

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
//! HIR ty lowering.
//!
//! Similarly generics, predicates and header are set to the "default" values.
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
//! In case of discrepancy with callee function the `UnsupportedDelegation` error will
//! also be emitted during HIR ty lowering.

use crate::{ImplTraitPosition, ResolverAstLoweringExt};
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,6 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
hir_analysis_not_supported_delegation =
{$descr} is not supported yet
.label = callee defined here
hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate
hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
};
}

if tcx.hir().opt_delegation_sig_id(def_id).is_some()
&& let Some(generics) = &tcx.lower_delegation_ty(def_id).generics
{
return generics.clone();
}

let hir_id = tcx.local_def_id_to_hir_id(def_id);

let node = tcx.hir_node(hir_id);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
None => {}
}

if tcx.hir().opt_delegation_sig_id(def_id).is_some()
&& let Some(predicates) = tcx.lower_delegation_ty(def_id).predicates
{
return predicates;
}

let hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_id);

Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1569,16 +1569,6 @@ pub enum RefOfMutStaticSugg {
},
}

#[derive(Diagnostic)]
#[diag(hir_analysis_not_supported_delegation)]
pub struct NotSupportedDelegation<'a> {
#[primary_span]
pub span: Span,
pub descr: &'a str,
#[label]
pub callee_span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_method_should_return_future)]
pub struct MethodShouldReturnFuture {
Expand Down
95 changes: 5 additions & 90 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1939,94 +1939,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self.lower_ty_common(hir_ty, false, true)
}

fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
let mut error_occured = false;
let sig_span = self.tcx().def_span(sig_id);
let mut try_emit = |descr| {
if emit {
self.tcx().dcx().emit_err(crate::errors::NotSupportedDelegation {
span,
descr,
callee_span: sig_span,
});
}
error_occured = true;
};

if let Some(node) = self.tcx().hir().get_if_local(sig_id)
&& let Some(decl) = node.fn_decl()
&& let hir::FnRetTy::Return(ty) = decl.output
&& let hir::TyKind::InferDelegation(_, _) = ty.kind
{
try_emit("recursive delegation");
}

let sig_generics = self.tcx().generics_of(sig_id);
let parent = self.tcx().parent(self.item_def_id());
let parent_generics = self.tcx().generics_of(parent);

let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
let sig_has_self = sig_generics.has_self as usize;

if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait {
try_emit("delegation with early bound generics");
}

// There is no way to instantiate `Self` param for caller if
// 1. callee is a trait method
// 2. delegation item isn't an associative item
if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
&& let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
&& self.tcx().associated_item(sig_id).container
== ty::AssocItemContainer::TraitContainer
{
try_emit("delegation to a trait method from a free function");
}

error_occured
}

fn lower_delegation_ty(
&self,
sig_id: DefId,
idx: hir::InferDelegationKind,
span: Span,
) -> Ty<'tcx> {
if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
{
let e = self.tcx().dcx().span_delayed_bug(span, "not supported delegation case");
self.set_tainted_by_errors(e);
return Ty::new_error(self.tcx(), e);
};
let sig = self.tcx().fn_sig(sig_id);
let sig_generics = self.tcx().generics_of(sig_id);

let parent = self.tcx().parent(self.item_def_id());
let parent_def_kind = self.tcx().def_kind(parent);

let sig = if let DefKind::Impl { .. } = parent_def_kind
&& sig_generics.has_self
{
// Generic params can't be here except the trait self type.
// They are not supported yet.
assert_eq!(sig_generics.count(), 1);
assert_eq!(self.tcx().generics_of(parent).count(), 0);

let self_ty = self.tcx().type_of(parent).instantiate_identity();
let generic_self_ty = ty::GenericArg::from(self_ty);
let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
sig.instantiate(self.tcx(), args)
} else {
sig.instantiate_identity()
};

// Bound vars are also inherited from `sig_id`.
// They will be rebound later in `lower_fn_ty`.
let sig = sig.skip_binder();

fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
let delegation_res = self.tcx().lower_delegation_ty(self.item_def_id().expect_local());
match idx {
hir::InferDelegationKind::Input(id) => sig.inputs()[id],
hir::InferDelegationKind::Output => sig.output(),
hir::InferDelegationKind::Input(idx) => delegation_res.inputs[idx],
hir::InferDelegationKind::Output => delegation_res.output,
}
}

Expand All @@ -2043,9 +1960,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();

let result_ty = match &hir_ty.kind {
hir::TyKind::InferDelegation(sig_id, idx) => {
self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
}
hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
hir::TyKind::Ref(region, mt) => {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
*[other] {" "}in the current scope
}
hir_typeck_not_supported_delegation =
{$descr}
.label = callee defined here
hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}`
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
Expand Down
Loading
Loading