Skip to content

Commit ba05af3

Browse files
committed
Delegation: partial generics support
1 parent a6a017d commit ba05af3

27 files changed

+1046
-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
@@ -1944,94 +1944,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19441944
self.lower_ty_common(hir_ty, false, true)
19451945
}
19461946

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

@@ -2048,9 +1965,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20481965
let tcx = self.tcx();
20491966

20501967
let result_ty = match &hir_ty.kind {
2051-
hir::TyKind::InferDelegation(sig_id, idx) => {
2052-
self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
2053-
}
1968+
hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
20541969
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
20551970
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
20561971
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)