Skip to content

Commit f02af50

Browse files
committed
Delegation: partial generics support
1 parent b582f80 commit f02af50

27 files changed

+1049
-253
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
//! HIR ty lowering.
3434
//!
3535
//! Similarly generics, predicates and header are set to the "default" values.
36-
//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
36+
//! In case of discrepancy with callee function the `UnsupportedDelegation` error will
3737
//! also be emitted during HIR ty lowering.
3838
3939
use crate::{ImplTraitPosition, ResolverAstLoweringExt};

compiler/rustc_hir_analysis/messages.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,6 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation
309309
310310
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
311311
312-
hir_analysis_not_supported_delegation =
313-
{$descr} is not supported yet
314-
.label = callee defined here
315-
316312
hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate
317313
318314
hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
5151
};
5252
}
5353

54+
if tcx.hir().opt_delegation_sig_id(def_id).is_some()
55+
&& let Some(generics) = &tcx.lower_delegation_ty(def_id).generics
56+
{
57+
return generics.clone();
58+
}
59+
5460
let hir_id = tcx.local_def_id_to_hir_id(def_id);
5561

5662
let node = tcx.hir_node(hir_id);

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+6
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
111111
None => {}
112112
}
113113

114+
if tcx.hir().opt_delegation_sig_id(def_id).is_some()
115+
&& let Some(predicates) = tcx.lower_delegation_ty(def_id).predicates
116+
{
117+
return predicates;
118+
}
119+
114120
let hir_id = tcx.local_def_id_to_hir_id(def_id);
115121
let node = tcx.hir_node(hir_id);
116122

compiler/rustc_hir_analysis/src/errors.rs

-10
Original file line numberDiff line numberDiff line change
@@ -1569,16 +1569,6 @@ pub enum RefOfMutStaticSugg {
15691569
},
15701570
}
15711571

1572-
#[derive(Diagnostic)]
1573-
#[diag(hir_analysis_not_supported_delegation)]
1574-
pub struct NotSupportedDelegation<'a> {
1575-
#[primary_span]
1576-
pub span: Span,
1577-
pub descr: &'a str,
1578-
#[label]
1579-
pub callee_span: Span,
1580-
}
1581-
15821572
#[derive(Diagnostic)]
15831573
#[diag(hir_analysis_method_should_return_future)]
15841574
pub struct MethodShouldReturnFuture {

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+5-90
Original file line numberDiff line numberDiff line change
@@ -1939,94 +1939,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19391939
self.lower_ty_common(hir_ty, false, true)
19401940
}
19411941

1942-
fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
1943-
let mut error_occured = false;
1944-
let sig_span = self.tcx().def_span(sig_id);
1945-
let mut try_emit = |descr| {
1946-
if emit {
1947-
self.tcx().dcx().emit_err(crate::errors::NotSupportedDelegation {
1948-
span,
1949-
descr,
1950-
callee_span: sig_span,
1951-
});
1952-
}
1953-
error_occured = true;
1954-
};
1955-
1956-
if let Some(node) = self.tcx().hir().get_if_local(sig_id)
1957-
&& let Some(decl) = node.fn_decl()
1958-
&& let hir::FnRetTy::Return(ty) = decl.output
1959-
&& let hir::TyKind::InferDelegation(_, _) = ty.kind
1960-
{
1961-
try_emit("recursive delegation");
1962-
}
1963-
1964-
let sig_generics = self.tcx().generics_of(sig_id);
1965-
let parent = self.tcx().parent(self.item_def_id());
1966-
let parent_generics = self.tcx().generics_of(parent);
1967-
1968-
let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
1969-
let sig_has_self = sig_generics.has_self as usize;
1970-
1971-
if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait {
1972-
try_emit("delegation with early bound generics");
1973-
}
1974-
1975-
// There is no way to instantiate `Self` param for caller if
1976-
// 1. callee is a trait method
1977-
// 2. delegation item isn't an associative item
1978-
if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
1979-
&& let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
1980-
&& self.tcx().associated_item(sig_id).container
1981-
== ty::AssocItemContainer::TraitContainer
1982-
{
1983-
try_emit("delegation to a trait method from a free function");
1984-
}
1985-
1986-
error_occured
1987-
}
1988-
1989-
fn lower_delegation_ty(
1990-
&self,
1991-
sig_id: DefId,
1992-
idx: hir::InferDelegationKind,
1993-
span: Span,
1994-
) -> Ty<'tcx> {
1995-
if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
1996-
{
1997-
let e = self.tcx().dcx().span_delayed_bug(span, "not supported delegation case");
1998-
self.set_tainted_by_errors(e);
1999-
return Ty::new_error(self.tcx(), e);
2000-
};
2001-
let sig = self.tcx().fn_sig(sig_id);
2002-
let sig_generics = self.tcx().generics_of(sig_id);
2003-
2004-
let parent = self.tcx().parent(self.item_def_id());
2005-
let parent_def_kind = self.tcx().def_kind(parent);
2006-
2007-
let sig = if let DefKind::Impl { .. } = parent_def_kind
2008-
&& sig_generics.has_self
2009-
{
2010-
// Generic params can't be here except the trait self type.
2011-
// They are not supported yet.
2012-
assert_eq!(sig_generics.count(), 1);
2013-
assert_eq!(self.tcx().generics_of(parent).count(), 0);
2014-
2015-
let self_ty = self.tcx().type_of(parent).instantiate_identity();
2016-
let generic_self_ty = ty::GenericArg::from(self_ty);
2017-
let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
2018-
sig.instantiate(self.tcx(), args)
2019-
} else {
2020-
sig.instantiate_identity()
2021-
};
2022-
2023-
// Bound vars are also inherited from `sig_id`.
2024-
// They will be rebound later in `lower_fn_ty`.
2025-
let sig = sig.skip_binder();
2026-
1942+
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
1943+
let delegation_res = self.tcx().lower_delegation_ty(self.item_def_id().expect_local());
20271944
match idx {
2028-
hir::InferDelegationKind::Input(id) => sig.inputs()[id],
2029-
hir::InferDelegationKind::Output => sig.output(),
1945+
hir::InferDelegationKind::Input(idx) => delegation_res.inputs[idx],
1946+
hir::InferDelegationKind::Output => delegation_res.output,
20301947
}
20311948
}
20321949

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

20451962
let result_ty = match &hir_ty.kind {
2046-
hir::TyKind::InferDelegation(sig_id, idx) => {
2047-
self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
2048-
}
1963+
hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
20491964
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
20501965
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
20511966
hir::TyKind::Ref(region, mt) => {

compiler/rustc_hir_typeck/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {
111111
*[other] {" "}in the current scope
112112
}
113113
114+
hir_typeck_not_supported_delegation =
115+
{$descr}
116+
.label = callee defined here
117+
114118
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}`
115119
116120
hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide

0 commit comments

Comments
 (0)