Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9f07683

Browse files
committedSep 3, 2024
Delegation: support generics in associated delegation items
1 parent 59885f5 commit 9f07683

14 files changed

+502
-272
lines changed
 

‎compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
5858
let hir_id = tcx.local_def_id_to_hir_id(def_id);
5959

6060
let node = tcx.hir_node(hir_id);
61+
if let Some(sig) = node.fn_sig()
62+
&& let Some(sig_id) = sig.decl.opt_delegation_sig_id()
63+
{
64+
return inherit_generics_for_delegation_item(tcx, def_id, sig_id);
65+
}
66+
6167
let parent_def_id = match node {
6268
Node::ImplItem(_)
6369
| Node::TraitItem(_)
@@ -228,16 +234,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
228234
// inherit the generics of the item.
229235
Some(parent.to_def_id())
230236
}
231-
ItemKind::Fn(sig, _, _) => {
232-
// For a delegation item inherit generics from callee.
233-
if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
234-
&& let Some(generics) =
235-
inherit_generics_for_delegation_item(tcx, def_id, sig_id)
236-
{
237-
return generics;
238-
}
239-
None
240-
}
241237
_ => None,
242238
},
243239
_ => None,

‎compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
120120
let hir_id = tcx.local_def_id_to_hir_id(def_id);
121121
let node = tcx.hir_node(hir_id);
122122

123+
if let Some(sig) = node.fn_sig()
124+
&& let Some(sig_id) = sig.decl.opt_delegation_sig_id()
125+
{
126+
return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
127+
}
128+
123129
let mut is_trait = None;
124130
let mut is_default_impl_trait = None;
125131

@@ -146,16 +152,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
146152
ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
147153
is_trait = Some(self_bounds);
148154
}
149-
150-
ItemKind::Fn(sig, _, _) => {
151-
// For a delegation item inherit predicates from callee.
152-
if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
153-
&& let Some(predicates) =
154-
inherit_predicates_for_delegation_item(tcx, def_id, sig_id)
155-
{
156-
return predicates;
157-
}
158-
}
159155
_ => {}
160156
}
161157
};

‎compiler/rustc_hir_analysis/src/delegation.rs

Lines changed: 194 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
//! Support inheriting generic parameters and predicates for function delegation.
2+
//!
3+
//! For more information about delegation design, see the tracking issue #118212.
4+
15
use std::assert_matches::debug_assert_matches;
26

37
use rustc_data_structures::fx::FxHashMap;
48
use rustc_hir::def::DefKind;
59
use rustc_hir::def_id::{DefId, LocalDefId};
610
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
711
use rustc_middle::ty::{self, Ty, TyCtxt};
8-
use rustc_span::ErrorGuaranteed;
12+
use rustc_span::{ErrorGuaranteed, Span};
913
use rustc_type_ir::visit::TypeVisitableExt;
1014

1115
type RemapTable = FxHashMap<u32, u32>;
@@ -76,24 +80,60 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
7680
}
7781
}
7882

83+
/// Given the current context(caller and callee `FnKind`), it specifies
84+
/// the policy of predicates and generic parameters inheritance.
85+
#[derive(Clone, Copy, Debug, PartialEq)]
86+
enum InheritanceKind {
87+
/// Copying all predicates and parameters, including those of the parent
88+
/// container.
89+
///
90+
/// Boolean value defines whether the `Self` parameter or `Self: Trait`
91+
/// predicate are copied. It's always equal to `false` except when
92+
/// delegating from a free function to a trait method.
93+
///
94+
/// FIXME(fn_delegation): This often leads to type inference
95+
/// errors. Support providing generic arguments or restrict use sites.
96+
WithParent(bool),
97+
/// The trait implementation should be compatible with the original trait.
98+
/// Therefore, for trait implementations only the method's own parameters
99+
/// and predicates are copied.
100+
Own,
101+
}
102+
79103
struct GenericsBuilder<'tcx> {
80104
tcx: TyCtxt<'tcx>,
81105
sig_id: DefId,
82106
parent: Option<DefId>,
107+
inh_kind: InheritanceKind,
83108
}
84109

85110
impl<'tcx> GenericsBuilder<'tcx> {
86111
fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
87-
GenericsBuilder { tcx, sig_id, parent: None }
112+
GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) }
113+
}
114+
115+
fn with_parent(mut self, parent: DefId) -> Self {
116+
self.parent = Some(parent);
117+
self
118+
}
119+
120+
fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
121+
self.inh_kind = inh_kind;
122+
self
88123
}
89124

90125
fn build(self) -> ty::Generics {
91126
let mut own_params = vec![];
92127

93128
let sig_generics = self.tcx.generics_of(self.sig_id);
94-
if let Some(parent_def_id) = sig_generics.parent {
129+
if let InheritanceKind::WithParent(has_self) = self.inh_kind
130+
&& let Some(parent_def_id) = sig_generics.parent
131+
{
95132
let sig_parent_generics = self.tcx.generics_of(parent_def_id);
96133
own_params.append(&mut sig_parent_generics.own_params.clone());
134+
if !has_self {
135+
own_params.remove(0);
136+
}
97137
}
98138
own_params.append(&mut sig_generics.own_params.clone());
99139

@@ -115,8 +155,16 @@ impl<'tcx> GenericsBuilder<'tcx> {
115155
let param_def_id_to_index =
116156
own_params.iter().map(|param| (param.def_id, param.index)).collect();
117157

158+
let (parent_count, has_self) = if let Some(def_id) = self.parent {
159+
let parent_generics = self.tcx.generics_of(def_id);
160+
let parent_kind = self.tcx.def_kind(def_id);
161+
(parent_generics.count(), parent_kind == DefKind::Trait)
162+
} else {
163+
(0, false)
164+
};
165+
118166
for (idx, param) in own_params.iter_mut().enumerate() {
119-
param.index = idx as u32;
167+
param.index = (idx + parent_count) as u32;
120168
// FIXME(fn_delegation): Default parameters are not inherited, because they are
121169
// not permitted in functions. Therefore, there are 2 options here:
122170
//
@@ -133,10 +181,10 @@ impl<'tcx> GenericsBuilder<'tcx> {
133181

134182
ty::Generics {
135183
parent: self.parent,
136-
parent_count: 0,
184+
parent_count,
137185
own_params,
138186
param_def_id_to_index,
139-
has_self: false,
187+
has_self,
140188
has_late_bound_regions: sig_generics.has_late_bound_regions,
141189
host_effect_index: sig_generics.host_effect_index,
142190
}
@@ -145,9 +193,10 @@ impl<'tcx> GenericsBuilder<'tcx> {
145193

146194
struct PredicatesBuilder<'tcx> {
147195
tcx: TyCtxt<'tcx>,
148-
args: ty::GenericArgsRef<'tcx>,
149-
parent: Option<DefId>,
150196
sig_id: DefId,
197+
parent: Option<DefId>,
198+
inh_kind: InheritanceKind,
199+
args: ty::GenericArgsRef<'tcx>,
151200
}
152201

153202
impl<'tcx> PredicatesBuilder<'tcx> {
@@ -156,18 +205,73 @@ impl<'tcx> PredicatesBuilder<'tcx> {
156205
args: ty::GenericArgsRef<'tcx>,
157206
sig_id: DefId,
158207
) -> PredicatesBuilder<'tcx> {
159-
PredicatesBuilder { tcx, args, parent: None, sig_id }
208+
PredicatesBuilder {
209+
tcx,
210+
sig_id,
211+
parent: None,
212+
inh_kind: InheritanceKind::WithParent(false),
213+
args,
214+
}
215+
}
216+
217+
fn with_parent(mut self, parent: DefId) -> Self {
218+
self.parent = Some(parent);
219+
self
220+
}
221+
222+
fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
223+
self.inh_kind = inh_kind;
224+
self
160225
}
161226

162227
fn build(self) -> ty::GenericPredicates<'tcx> {
163-
let mut preds = vec![];
228+
struct PredicatesCollector<'tcx> {
229+
tcx: TyCtxt<'tcx>,
230+
preds: Vec<(ty::Clause<'tcx>, Span)>,
231+
args: ty::GenericArgsRef<'tcx>,
232+
}
233+
234+
impl<'tcx> PredicatesCollector<'tcx> {
235+
fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
236+
PredicatesCollector { tcx, preds: vec![], args }
237+
}
238+
239+
fn with_own_preds(
240+
mut self,
241+
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
242+
def_id: DefId,
243+
) -> Self {
244+
let preds = f(def_id).instantiate_own(self.tcx, self.args);
245+
self.preds.extend(preds);
246+
self
247+
}
248+
249+
fn with_preds(
250+
mut self,
251+
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
252+
def_id: DefId,
253+
) -> Self {
254+
let preds = f(def_id);
255+
if let Some(parent_def_id) = preds.parent {
256+
self = self.with_own_preds(f, parent_def_id);
257+
}
258+
self.with_own_preds(f, def_id)
259+
}
260+
}
261+
let collector = PredicatesCollector::new(self.tcx, self.args);
164262

165-
let sig_predicates = self.tcx.predicates_of(self.sig_id);
166-
if let Some(parent) = sig_predicates.parent {
167-
let sig_parent_preds = self.tcx.predicates_of(parent);
168-
preds.extend(sig_parent_preds.instantiate_own(self.tcx, self.args));
263+
let preds = match self.inh_kind {
264+
InheritanceKind::WithParent(false) => {
265+
collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id)
266+
}
267+
InheritanceKind::WithParent(true) => {
268+
collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
269+
}
270+
InheritanceKind::Own => {
271+
collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
272+
}
169273
}
170-
preds.extend(sig_predicates.instantiate_own(self.tcx, self.args));
274+
.preds;
171275

172276
ty::GenericPredicates {
173277
parent: self.parent,
@@ -214,7 +318,6 @@ fn create_generic_args<'tcx>(
214318

215319
let caller_kind = fn_kind(tcx, def_id.into());
216320
let callee_kind = fn_kind(tcx, sig_id);
217-
218321
match (caller_kind, callee_kind) {
219322
(FnKind::Free, FnKind::Free)
220323
| (FnKind::Free, FnKind::AssocTrait)
@@ -224,14 +327,32 @@ fn create_generic_args<'tcx>(
224327
let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
225328
builder.build_from_args(args)
226329
}
227-
// FIXME(fn_delegation): Only `Self` param supported here.
228-
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
229-
| (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
330+
331+
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
332+
let callee_generics = tcx.generics_of(sig_id);
333+
let parent = tcx.parent(def_id.into());
334+
let parent_args =
335+
tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args;
336+
337+
let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
338+
let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
339+
let method_args = builder.build_from_args(method_args);
340+
341+
tcx.mk_args_from_iter(parent_args.iter().chain(method_args))
342+
}
343+
344+
(FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
230345
let parent = tcx.parent(def_id.into());
231346
let self_ty = tcx.type_of(parent).instantiate_identity();
232347
let generic_self_ty = ty::GenericArg::from(self_ty);
233-
tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
348+
349+
let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
350+
let trait_args = builder.build_from_args(trait_args);
351+
352+
let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
353+
tcx.mk_args_from_iter(args)
234354
}
355+
235356
// For trait impl's `sig_id` is always equal to the corresponding trait method.
236357
(FnKind::AssocTraitImpl, _)
237358
| (_, FnKind::AssocTraitImpl)
@@ -240,27 +361,53 @@ fn create_generic_args<'tcx>(
240361
}
241362
}
242363

364+
// FIXME(fn_delegation): Move generics inheritance to the AST->HIR lowering.
365+
// For now, generic parameters are not propagated to the generated call,
366+
// which leads to inference errors:
367+
//
368+
// fn foo<T>(x: i32) {}
369+
//
370+
// reuse foo as bar;
371+
// desugaring:
372+
// fn bar<T>() {
373+
// foo::<_>() // ERROR: type annotations needed
374+
// }
243375
pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
244376
tcx: TyCtxt<'tcx>,
245377
def_id: LocalDefId,
246378
sig_id: DefId,
247-
) -> Option<ty::Generics> {
379+
) -> ty::Generics {
248380
let builder = GenericsBuilder::new(tcx, sig_id);
249381

250382
let caller_kind = fn_kind(tcx, def_id.into());
251383
let callee_kind = fn_kind(tcx, sig_id);
252-
253-
// FIXME(fn_delegation): Support generics on associated delegation items.
254-
// Error will be reported in `check_constraints`.
255384
match (caller_kind, callee_kind) {
256385
(FnKind::Free, FnKind::Free)
257-
| (FnKind::Free, FnKind::AssocTrait) => Some(builder.build()),
386+
| (FnKind::Free, FnKind::AssocTrait) => builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build(),
258387

259-
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
260-
| (FnKind::AssocInherentImpl, FnKind::AssocTrait)
261-
| (FnKind::AssocTrait, FnKind::AssocTrait)
262-
| (FnKind::AssocInherentImpl, FnKind::Free)
263-
| (FnKind::AssocTrait, FnKind::Free) => None,
388+
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
389+
let parent = tcx.parent(def_id.into());
390+
builder
391+
.with_parent(parent)
392+
.with_inheritance_kind(InheritanceKind::Own)
393+
.build()
394+
}
395+
396+
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
397+
| (FnKind::AssocTrait, FnKind::AssocTrait) => {
398+
let parent = tcx.parent(def_id.into());
399+
builder
400+
.with_parent(parent)
401+
.build()
402+
}
403+
404+
(FnKind::AssocInherentImpl, FnKind::Free)
405+
| (FnKind::AssocTrait, FnKind::Free) => {
406+
let parent = tcx.parent(def_id.into());
407+
builder
408+
.with_parent(parent)
409+
.build()
410+
}
264411

265412
// For trait impl's `sig_id` is always equal to the corresponding trait method.
266413
(FnKind::AssocTraitImpl, _)
@@ -274,26 +421,35 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
274421
tcx: TyCtxt<'tcx>,
275422
def_id: LocalDefId,
276423
sig_id: DefId,
277-
) -> Option<ty::GenericPredicates<'tcx>> {
424+
) -> ty::GenericPredicates<'tcx> {
278425
let args = create_generic_args(tcx, def_id, sig_id);
279426
let builder = PredicatesBuilder::new(tcx, args, sig_id);
280427

281428
let caller_kind = fn_kind(tcx, def_id.into());
282429
let callee_kind = fn_kind(tcx, sig_id);
283-
284-
// FIXME(fn_delegation): Support generics on associated delegation items.
285-
// Error will be reported in `check_constraints`.
286430
match (caller_kind, callee_kind) {
287431
(FnKind::Free, FnKind::Free)
288432
| (FnKind::Free, FnKind::AssocTrait) => {
289-
Some(builder.build())
433+
builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build()
434+
}
435+
436+
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
437+
let parent = tcx.parent(def_id.into());
438+
builder
439+
.with_parent(parent)
440+
.with_inheritance_kind(InheritanceKind::Own)
441+
.build()
290442
}
291443

292-
(FnKind::AssocTraitImpl, FnKind::AssocTrait)
293-
| (FnKind::AssocInherentImpl, FnKind::AssocTrait)
444+
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
294445
| (FnKind::AssocTrait, FnKind::AssocTrait)
295446
| (FnKind::AssocInherentImpl, FnKind::Free)
296-
| (FnKind::AssocTrait, FnKind::Free) => None,
447+
| (FnKind::AssocTrait, FnKind::Free) => {
448+
let parent = tcx.parent(def_id.into());
449+
builder
450+
.with_parent(parent)
451+
.build()
452+
}
297453

298454
// For trait impl's `sig_id` is always equal to the corresponding trait method.
299455
(FnKind::AssocTraitImpl, _)
@@ -328,19 +484,6 @@ fn check_constraints<'tcx>(
328484
emit("recursive delegation is not supported yet");
329485
}
330486

331-
if fn_kind(tcx, def_id.into()) != FnKind::Free {
332-
let sig_generics = tcx.generics_of(sig_id);
333-
let parent = tcx.parent(def_id.into());
334-
let parent_generics = tcx.generics_of(parent);
335-
336-
let parent_has_self = parent_generics.has_self as usize;
337-
let sig_has_self = sig_generics.has_self as usize;
338-
339-
if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self {
340-
emit("early bound generics are not supported for associated delegation items");
341-
}
342-
}
343-
344487
ret
345488
}
346489

‎compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
12531253
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
12541254
&& self.tecx.tcx.trait_of_item(def_id).is_some()
12551255
&& !has_impl_trait(def_id)
1256+
// FIXME(fn_delegation): In delegation item argument spans are equal to last path
1257+
// segment. This leads to ICE's when emitting `multipart_suggestion`.
1258+
&& tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
12561259
{
12571260
let successor =
12581261
method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ run-pass
2+
#![feature(fn_delegation)]
3+
#![allow(incomplete_features)]
4+
5+
mod to_reuse {
6+
pub fn foo<T, U>(_: T, y: U) -> U { y }
7+
}
8+
9+
trait Trait<T> {
10+
fn foo(&self, x: T) -> T { x }
11+
}
12+
struct F;
13+
impl<T> Trait<T> for F {}
14+
15+
struct S<T>(F, T);
16+
17+
impl<T, U> Trait<T> for S<U> {
18+
reuse to_reuse::foo { &self.0 }
19+
}
20+
21+
impl<T> S<T> {
22+
reuse to_reuse::foo;
23+
}
24+
25+
fn main() {
26+
let s = S(F, 42);
27+
assert_eq!(S::<i32>::foo(F, 1), 1);
28+
assert_eq!(<S<_> as Trait<_>>::foo(&s, 1), 1);
29+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![feature(fn_delegation)]
2+
#![allow(incomplete_features)]
3+
4+
mod bounds {
5+
trait Trait0 {}
6+
7+
trait Trait1<T> {
8+
fn foo<U>(&self)
9+
where
10+
T: Trait0,
11+
U: Trait0,
12+
Self: Trait0,
13+
//~^ ERROR the trait bound `bounds::S: Trait0` is not satisfied
14+
{
15+
}
16+
}
17+
18+
struct F;
19+
impl<T> Trait1<T> for F {}
20+
21+
struct S(F);
22+
23+
impl<T> Trait1<T> for S {
24+
reuse Trait1::<T>::foo { &self.0 }
25+
//~^ ERROR the trait bound `bounds::F: Trait0` is not satisfied
26+
}
27+
}
28+
29+
mod unconstrained_parameter {
30+
trait Trait<T> {
31+
fn foo(&self) {}
32+
}
33+
34+
struct F;
35+
impl<T> Trait<T> for F {}
36+
37+
struct S(F);
38+
impl S {
39+
reuse Trait::foo { &self.0 }
40+
//~^ ERROR type annotations needed
41+
}
42+
}
43+
44+
fn main() {}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error[E0277]: the trait bound `bounds::S: Trait0` is not satisfied
2+
--> $DIR/impl-to-trait-method.rs:12:19
3+
|
4+
LL | Self: Trait0,
5+
| ^^^^^^ the trait `Trait0` is not implemented for `bounds::S`
6+
|
7+
help: this trait has no implementations, consider adding one
8+
--> $DIR/impl-to-trait-method.rs:5:5
9+
|
10+
LL | trait Trait0 {}
11+
| ^^^^^^^^^^^^
12+
= help: see issue #48214
13+
help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
14+
|
15+
LL + #![feature(trivial_bounds)]
16+
|
17+
18+
error[E0277]: the trait bound `bounds::F: Trait0` is not satisfied
19+
--> $DIR/impl-to-trait-method.rs:24:34
20+
|
21+
LL | reuse Trait1::<T>::foo { &self.0 }
22+
| --- ^^^^^^^ the trait `Trait0` is not implemented for `bounds::F`
23+
| |
24+
| required by a bound introduced by this call
25+
|
26+
help: this trait has no implementations, consider adding one
27+
--> $DIR/impl-to-trait-method.rs:5:5
28+
|
29+
LL | trait Trait0 {}
30+
| ^^^^^^^^^^^^
31+
note: required by a bound in `Trait1::foo`
32+
--> $DIR/impl-to-trait-method.rs:12:19
33+
|
34+
LL | fn foo<U>(&self)
35+
| --- required by a bound in this associated function
36+
...
37+
LL | Self: Trait0,
38+
| ^^^^^^ required by this bound in `Trait1::foo`
39+
40+
error[E0282]: type annotations needed
41+
--> $DIR/impl-to-trait-method.rs:39:22
42+
|
43+
LL | reuse Trait::foo { &self.0 }
44+
| ^^^ cannot infer type for type parameter `T` declared on the trait `Trait`
45+
46+
error: aborting due to 3 previous errors
47+
48+
Some errors have detailed explanations: E0277, E0282.
49+
For more information about an error, try `rustc --explain E0277`.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//@ run-pass
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features)]
5+
6+
use std::iter::{Iterator, Map};
7+
8+
pub mod same_trait {
9+
use super::*;
10+
11+
pub struct MapOuter<I, F> {
12+
pub inner: Map<I, F>
13+
}
14+
15+
impl<B, I: Iterator, F> Iterator for MapOuter<I, F>
16+
where
17+
F: FnMut(I::Item) -> B,
18+
{
19+
type Item = <Map<I, F> as Iterator>::Item;
20+
21+
reuse Iterator::{next, fold} { self.inner }
22+
}
23+
}
24+
use same_trait::MapOuter;
25+
26+
mod another_trait {
27+
use super::*;
28+
29+
trait ZipImpl<A, B> {
30+
type Item;
31+
32+
fn next(&mut self) -> Option<Self::Item>;
33+
}
34+
35+
pub struct Zip<A, B> {
36+
pub a: A,
37+
pub b: B,
38+
}
39+
40+
impl<A: Iterator, B: Iterator> ZipImpl<A, B> for Zip<A, B> {
41+
type Item = (A::Item, B::Item);
42+
43+
fn next(&mut self) -> Option<(A::Item, B::Item)> {
44+
let x = self.a.next()?;
45+
let y = self.b.next()?;
46+
Some((x, y))
47+
}
48+
}
49+
50+
impl<A: Iterator, B: Iterator> Iterator for Zip<A, B> {
51+
type Item = (A::Item, B::Item);
52+
53+
// Parameters are inherited from `Iterator::next`, not from `ZipImpl::next`.
54+
// Otherwise, there would be a compilation error due to an unconstrained parameter.
55+
reuse ZipImpl::next;
56+
}
57+
}
58+
use another_trait::Zip;
59+
60+
fn main() {
61+
{
62+
let x = vec![1, 2, 3];
63+
let iter = x.iter().map(|val| val * 2);
64+
let outer_iter = MapOuter { inner: iter };
65+
let val = outer_iter.fold(0, |acc, x| acc + x);
66+
assert_eq!(val, 12);
67+
}
68+
69+
{
70+
let x = vec![1, 2];
71+
let y = vec![4, 5];
72+
73+
let mut zip = Zip { a: x.iter(), b: y.iter() };
74+
assert_eq!(zip.next(), Some((&1, &4)));
75+
assert_eq!(zip.next(), Some((&2, &5)));
76+
}
77+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ run-pass
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features)]
5+
6+
trait Trait<T> {
7+
fn foo<U>(&self, x: T, y: U) -> (T, U) {
8+
(x, y)
9+
}
10+
}
11+
12+
impl<T> Trait<T> for () {}
13+
struct S<T>(T, ());
14+
15+
impl<T> S<T> {
16+
reuse Trait::foo { self.1 }
17+
}
18+
19+
20+
fn main() {
21+
let s = S((), ());
22+
assert_eq!(s.foo(1u32, 2i32), (1u32, 2i32));
23+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ run-pass
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features)]
5+
6+
mod to_reuse {
7+
pub fn foo<T>(x: T) -> T { x }
8+
}
9+
10+
trait Trait1<T, U> {
11+
fn foo(&self, _: T, x: U) -> U { x }
12+
}
13+
14+
#[derive(Default)]
15+
struct F;
16+
17+
impl<T, U> Trait1<T, U> for F {}
18+
19+
trait Trait2<T> {
20+
fn get_f(&self) -> &F { &F }
21+
reuse Trait1::foo as bar { self.get_f() }
22+
reuse to_reuse::foo as baz;
23+
}
24+
25+
impl Trait2<u64> for F {}
26+
27+
fn main() {
28+
assert_eq!(F.bar(1u8, 2u16), 2u16);
29+
assert_eq!(F::baz(1u8), 1u8);
30+
}

‎tests/ui/delegation/ice-issue-124347.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#![feature(fn_delegation)]
22
#![allow(incomplete_features)]
33

4+
// FIXME(fn_delegation): `recursive delegation` error should be emitted here
45
trait Trait {
56
reuse Trait::foo { &self.0 }
6-
//~^ ERROR recursive delegation is not supported yet
7+
//~^ ERROR cycle detected when computing generics of `Trait::foo`
78
}
89

9-
// FIXME(fn_delegation): `recursive delegation` error should be emitted here
1010
reuse foo;
1111
//~^ ERROR cycle detected when computing generics of `foo`
1212

‎tests/ui/delegation/ice-issue-124347.stderr

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
error: recursive delegation is not supported yet
2-
--> $DIR/ice-issue-124347.rs:5:18
1+
error[E0391]: cycle detected when computing generics of `Trait::foo`
2+
--> $DIR/ice-issue-124347.rs:6:18
33
|
44
LL | reuse Trait::foo { &self.0 }
5-
| ^^^ callee defined here
5+
| ^^^
6+
|
7+
= note: ...which immediately requires computing generics of `Trait::foo` again
8+
note: cycle used when inheriting delegation signature
9+
--> $DIR/ice-issue-124347.rs:6:18
10+
|
11+
LL | reuse Trait::foo { &self.0 }
12+
| ^^^
13+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
614

715
error[E0391]: cycle detected when computing generics of `foo`
816
--> $DIR/ice-issue-124347.rs:10:7

‎tests/ui/delegation/unsupported.rs

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,6 @@
44
#![feature(fn_delegation)]
55
#![allow(incomplete_features)]
66

7-
mod generics {
8-
trait GenericTrait<T> {
9-
fn bar(&self, x: T) -> T { x }
10-
fn bar1() {}
11-
}
12-
trait Trait {
13-
fn foo(&self, x: i32) -> i32 { x }
14-
fn foo1<'a>(&self, x: &'a i32) -> &'a i32 { x }
15-
fn foo2<T>(&self, x: T) -> T { x }
16-
fn foo3<'a: 'a>(_: &'a u32) {}
17-
18-
reuse GenericTrait::bar;
19-
//~^ ERROR early bound generics are not supported for associated delegation items
20-
reuse GenericTrait::bar1;
21-
//~^ ERROR early bound generics are not supported for associated delegation items
22-
}
23-
24-
struct F;
25-
impl Trait for F {}
26-
impl<T> GenericTrait<T> for F {}
27-
28-
struct S(F);
29-
30-
impl<T> GenericTrait<T> for S {
31-
reuse <F as GenericTrait<T>>::bar { &self.0 }
32-
//~^ ERROR early bound generics are not supported for associated delegation items
33-
reuse GenericTrait::<T>::bar1;
34-
//~^ ERROR early bound generics are not supported for associated delegation items
35-
}
36-
37-
impl GenericTrait<()> for () {
38-
reuse GenericTrait::bar { &F }
39-
//~^ ERROR early bound generics are not supported for associated delegation items
40-
reuse GenericTrait::bar1;
41-
//~^ ERROR early bound generics are not supported for associated delegation items
42-
}
43-
44-
impl Trait for &S {
45-
reuse Trait::foo;
46-
//~^ ERROR early bound generics are not supported for associated delegation items
47-
}
48-
49-
impl Trait for S {
50-
reuse Trait::foo1 { &self.0 }
51-
reuse Trait::foo2 { &self.0 }
52-
//~^ ERROR early bound generics are not supported for associated delegation items
53-
//~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
54-
reuse <F as Trait>::foo3;
55-
//~^ ERROR early bound generics are not supported for associated delegation items
56-
//~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
57-
}
58-
59-
struct GenericS<T>(T);
60-
impl<T> Trait for GenericS<T> {
61-
reuse Trait::foo { &self.0 }
62-
//~^ ERROR early bound generics are not supported for associated delegation items
63-
}
64-
}
65-
667
mod opaque {
678
trait Trait {}
689
impl Trait for () {}

‎tests/ui/delegation/unsupported.stderr

Lines changed: 28 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -3,125 +3,8 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
33
= note: the next trait solver must be enabled globally for the effects feature to work correctly
44
= help: use `-Znext-solver` to enable
55

6-
error: early bound generics are not supported for associated delegation items
7-
--> $DIR/unsupported.rs:18:29
8-
|
9-
LL | fn bar(&self, x: T) -> T { x }
10-
| ------------------------ callee defined here
11-
...
12-
LL | reuse GenericTrait::bar;
13-
| ^^^
14-
15-
error: early bound generics are not supported for associated delegation items
16-
--> $DIR/unsupported.rs:20:29
17-
|
18-
LL | fn bar1() {}
19-
| --------- callee defined here
20-
...
21-
LL | reuse GenericTrait::bar1;
22-
| ^^^^
23-
24-
error: early bound generics are not supported for associated delegation items
25-
--> $DIR/unsupported.rs:31:39
26-
|
27-
LL | fn bar(&self, x: T) -> T { x }
28-
| ------------------------ callee defined here
29-
...
30-
LL | reuse <F as GenericTrait<T>>::bar { &self.0 }
31-
| ^^^
32-
33-
error: early bound generics are not supported for associated delegation items
34-
--> $DIR/unsupported.rs:33:34
35-
|
36-
LL | fn bar1() {}
37-
| --------- callee defined here
38-
...
39-
LL | reuse GenericTrait::<T>::bar1;
40-
| ^^^^
41-
42-
error: early bound generics are not supported for associated delegation items
43-
--> $DIR/unsupported.rs:38:29
44-
|
45-
LL | fn bar(&self, x: T) -> T { x }
46-
| ------------------------ callee defined here
47-
...
48-
LL | reuse GenericTrait::bar { &F }
49-
| ^^^
50-
51-
error: early bound generics are not supported for associated delegation items
52-
--> $DIR/unsupported.rs:40:29
53-
|
54-
LL | fn bar1() {}
55-
| --------- callee defined here
56-
...
57-
LL | reuse GenericTrait::bar1;
58-
| ^^^^
59-
60-
error: early bound generics are not supported for associated delegation items
61-
--> $DIR/unsupported.rs:45:22
62-
|
63-
LL | fn foo(&self, x: i32) -> i32 { x }
64-
| ---------------------------- callee defined here
65-
...
66-
LL | reuse Trait::foo;
67-
| ^^^
68-
69-
error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
70-
--> $DIR/unsupported.rs:51:22
71-
|
72-
LL | fn foo2<T>(&self, x: T) -> T { x }
73-
| - expected 1 type parameter
74-
...
75-
LL | reuse Trait::foo2 { &self.0 }
76-
| ^^^^ found 0 type parameters
77-
78-
error: early bound generics are not supported for associated delegation items
79-
--> $DIR/unsupported.rs:54:29
80-
|
81-
LL | fn foo3<'a: 'a>(_: &'a u32) {}
82-
| --------------------------- callee defined here
83-
...
84-
LL | reuse <F as Trait>::foo3;
85-
| ^^^^
86-
87-
error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
88-
--> $DIR/unsupported.rs:54:29
89-
|
90-
LL | fn foo3<'a: 'a>(_: &'a u32) {}
91-
| -------- lifetimes in impl do not match this associated function in trait
92-
...
93-
LL | reuse <F as Trait>::foo3;
94-
| ^^^^ lifetimes do not match associated function in trait
95-
96-
error: delegation to a function with effect parameter is not supported yet
97-
--> $DIR/unsupported.rs:112:18
98-
|
99-
LL | fn foo();
100-
| --------- callee defined here
101-
...
102-
LL | reuse Trait::foo;
103-
| ^^^
104-
105-
error: early bound generics are not supported for associated delegation items
106-
--> $DIR/unsupported.rs:61:22
107-
|
108-
LL | fn foo(&self, x: i32) -> i32 { x }
109-
| ---------------------------- callee defined here
110-
...
111-
LL | reuse Trait::foo { &self.0 }
112-
| ^^^
113-
114-
error: early bound generics are not supported for associated delegation items
115-
--> $DIR/unsupported.rs:51:22
116-
|
117-
LL | fn foo2<T>(&self, x: T) -> T { x }
118-
| ---------------------------- callee defined here
119-
...
120-
LL | reuse Trait::foo2 { &self.0 }
121-
| ^^^^
122-
1236
warning: this function depends on never type fallback being `()`
124-
--> $DIR/unsupported.rs:79:9
7+
--> $DIR/unsupported.rs:20:9
1258
|
1269
LL | fn opaque_ret() -> impl Trait { unimplemented!() }
12710
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,33 +13,33 @@ LL | fn opaque_ret() -> impl Trait { unimplemented!() }
13013
= note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
13114
= help: specify the types explicitly
13215
note: in edition 2024, the requirement `!: opaque::Trait` will fail
133-
--> $DIR/unsupported.rs:79:28
16+
--> $DIR/unsupported.rs:20:28
13417
|
13518
LL | fn opaque_ret() -> impl Trait { unimplemented!() }
13619
| ^^^^^^^^^^
13720
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
13821

139-
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:85:5: 85:24>::{synthetic#0}`
140-
--> $DIR/unsupported.rs:86:25
22+
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`
23+
--> $DIR/unsupported.rs:27:25
14124
|
14225
LL | reuse to_reuse::opaque_ret;
14326
| ^^^^^^^^^^
14427
|
14528
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
146-
--> $DIR/unsupported.rs:86:25
29+
--> $DIR/unsupported.rs:27:25
14730
|
14831
LL | reuse to_reuse::opaque_ret;
14932
| ^^^^^^^^^^
150-
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:85:5: 85:24>::{synthetic#0}`, completing the cycle
151-
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:85:5: 85:24>` is well-formed
152-
--> $DIR/unsupported.rs:85:5
33+
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`, completing the cycle
34+
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>` is well-formed
35+
--> $DIR/unsupported.rs:26:5
15336
|
15437
LL | impl ToReuse for u8 {
15538
| ^^^^^^^^^^^^^^^^^^^
15639
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
15740

15841
warning: this function depends on never type fallback being `()`
159-
--> $DIR/unsupported.rs:73:9
42+
--> $DIR/unsupported.rs:14:9
16043
|
16144
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
16245
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -165,40 +48,48 @@ LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
16548
= note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
16649
= help: specify the types explicitly
16750
note: in edition 2024, the requirement `!: opaque::Trait` will fail
168-
--> $DIR/unsupported.rs:73:32
51+
--> $DIR/unsupported.rs:14:32
16952
|
17053
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
17154
| ^^^^^^^^^^
17255

173-
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:88:5: 88:25>::{synthetic#0}`
174-
--> $DIR/unsupported.rs:89:24
56+
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`
57+
--> $DIR/unsupported.rs:30:24
17558
|
17659
LL | reuse ToReuse::opaque_ret;
17760
| ^^^^^^^^^^
17861
|
17962
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
180-
--> $DIR/unsupported.rs:89:24
63+
--> $DIR/unsupported.rs:30:24
18164
|
18265
LL | reuse ToReuse::opaque_ret;
18366
| ^^^^^^^^^^
184-
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:88:5: 88:25>::{synthetic#0}`, completing the cycle
185-
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:88:5: 88:25>` is well-formed
186-
--> $DIR/unsupported.rs:88:5
67+
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`, completing the cycle
68+
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>` is well-formed
69+
--> $DIR/unsupported.rs:29:5
18770
|
18871
LL | impl ToReuse for u16 {
18972
| ^^^^^^^^^^^^^^^^^^^^
19073
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
19174

19275
error: recursive delegation is not supported yet
193-
--> $DIR/unsupported.rs:102:22
76+
--> $DIR/unsupported.rs:43:22
19477
|
19578
LL | pub reuse to_reuse2::foo;
19679
| --- callee defined here
19780
...
19881
LL | reuse to_reuse1::foo;
19982
| ^^^
20083

201-
error: aborting due to 17 previous errors; 2 warnings emitted
84+
error: delegation to a function with effect parameter is not supported yet
85+
--> $DIR/unsupported.rs:53:18
86+
|
87+
LL | fn foo();
88+
| --------- callee defined here
89+
...
90+
LL | reuse Trait::foo;
91+
| ^^^
92+
93+
error: aborting due to 5 previous errors; 2 warnings emitted
20294

203-
Some errors have detailed explanations: E0049, E0195, E0391.
204-
For more information about an error, try `rustc --explain E0049`.
95+
For more information about this error, try `rustc --explain E0391`.

0 commit comments

Comments
 (0)
This repository has been archived.