Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1e5a473

Browse files
committedJun 24, 2024·
Delegation: support coercion for target expression
1 parent 894f7a4 commit 1e5a473

File tree

16 files changed

+313
-102
lines changed

16 files changed

+313
-102
lines changed
 

‎compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 117 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
3939
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
4040

41-
use super::{ImplTraitContext, LoweringContext, ParamMode};
41+
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
4242

4343
use ast::visit::Visitor;
4444
use hir::def::{DefKind, PartialRes, Res};
@@ -66,17 +66,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
6666
let Ok(sig_id) = sig_id else {
6767
return false;
6868
};
69-
if let Some(local_sig_id) = sig_id.as_local() {
70-
// The value may be missing due to recursive delegation.
71-
// Error will be emmited later during HIR ty lowering.
72-
self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self)
73-
} else {
74-
match self.tcx.def_kind(sig_id) {
75-
DefKind::Fn => false,
76-
DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter,
77-
_ => span_bug!(span, "unexpected DefKind for delegation item"),
78-
}
79-
}
69+
self.has_self(sig_id, span)
8070
}
8171

8272
pub(crate) fn lower_delegation(
@@ -107,12 +97,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
10797
span: Span,
10898
) -> Result<DefId, ErrorGuaranteed> {
10999
let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
110-
let sig_id =
111-
self.resolver.get_partial_res(sig_id).and_then(|r| r.expect_full_res().opt_def_id());
112-
sig_id.ok_or_else(|| {
113-
self.tcx
114-
.dcx()
115-
.span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item")
100+
self.get_resolution_id(sig_id, span)
101+
}
102+
103+
fn has_self(&self, def_id: DefId, span: Span) -> bool {
104+
if let Some(local_sig_id) = def_id.as_local() {
105+
self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self)
106+
} else {
107+
match self.tcx.def_kind(def_id) {
108+
DefKind::Fn => false,
109+
DefKind::AssocFn => self.tcx.associated_item(def_id).fn_has_self_parameter,
110+
_ => span_bug!(span, "unexpected DefKind for delegation item"),
111+
}
112+
}
113+
}
114+
115+
fn get_resolution_id(&self, node_id: NodeId, span: Span) -> Result<DefId, ErrorGuaranteed> {
116+
let def_id =
117+
self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id());
118+
def_id.ok_or_else(|| {
119+
self.tcx.dcx().span_delayed_bug(
120+
span,
121+
format!("LoweringContext: couldn't resolve node {:?} in delegation item", node_id),
122+
)
116123
})
117124
}
118125

@@ -122,7 +129,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
122129
predicates: &[],
123130
has_where_clause_predicates: false,
124131
where_clause_span: span,
125-
span: span,
132+
span,
126133
})
127134
}
128135

@@ -222,12 +229,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
222229
}));
223230

224231
let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments });
225-
226-
hir::Expr {
227-
hir_id: self.next_id(),
228-
kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
229-
span,
230-
}
232+
self.mk_expr(hir::ExprKind::Path(hir::QPath::Resolved(None, path)), span)
231233
}
232234

233235
fn lower_delegation_body(
@@ -236,25 +238,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
236238
param_count: usize,
237239
span: Span,
238240
) -> BodyId {
239-
let path = self.lower_qpath(
240-
delegation.id,
241-
&delegation.qself,
242-
&delegation.path,
243-
ParamMode::Optional,
244-
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
245-
None,
246-
);
247241
let block = delegation.body.as_deref();
248242

249243
self.lower_body(|this| {
250-
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
251-
let mut args: Vec<hir::Expr<'hir>> = Vec::new();
244+
let mut parameters: Vec<hir::Param<'_>> = Vec::with_capacity(param_count);
245+
let mut args: Vec<hir::Expr<'_>> = Vec::with_capacity(param_count);
246+
let mut target_expr = None;
252247

253248
for idx in 0..param_count {
254249
let (param, pat_node_id) = this.generate_param(span);
255250
parameters.push(param);
256251

257-
let arg = if let Some(block) = block
252+
if let Some(block) = block
258253
&& idx == 0
259254
{
260255
let mut self_resolver = SelfResolver {
@@ -263,56 +258,103 @@ impl<'hir> LoweringContext<'_, 'hir> {
263258
self_param_id: pat_node_id,
264259
};
265260
self_resolver.visit_block(block);
266-
let block = this.lower_block(block, false);
267-
hir::Expr {
268-
hir_id: this.next_id(),
269-
kind: hir::ExprKind::Block(block, None),
270-
span: block.span,
271-
}
261+
target_expr = Some(this.lower_block_noalloc(block, false));
272262
} else {
273263
let pat_hir_id = this.lower_node_id(pat_node_id);
274-
this.generate_arg(pat_hir_id, span)
264+
let arg = this.generate_arg(pat_hir_id, span);
265+
args.push(arg);
275266
};
276-
args.push(arg);
277267
}
278268

279-
let args = self.arena.alloc_from_iter(args);
280-
let final_expr = this.generate_call(path, args);
269+
let final_expr = this.finalize_body_lowering(delegation, target_expr, args, span);
281270
(this.arena.alloc_from_iter(parameters), final_expr)
282271
})
283272
}
284273

285-
fn generate_call(
274+
// Generates expression for the resulting body. If possible, `MethodCall` is used
275+
// instead of fully qualified call for the self type coercion. See `consider_candidates`
276+
// for more information.
277+
fn finalize_body_lowering(
286278
&mut self,
287-
path: hir::QPath<'hir>,
288-
args: &'hir [hir::Expr<'hir>],
279+
delegation: &Delegation,
280+
target_expr: Option<hir::Block<'hir>>,
281+
mut args: Vec<hir::Expr<'hir>>,
282+
span: Span,
289283
) -> hir::Expr<'hir> {
290-
let callee = self.arena.alloc(hir::Expr {
291-
hir_id: self.next_id(),
292-
kind: hir::ExprKind::Path(path),
293-
span: path.span(),
294-
});
284+
let (stmts, call, block_id) = if self
285+
.get_resolution_id(delegation.id, span)
286+
.and_then(|def_id| Ok(self.has_self(def_id, span)))
287+
.unwrap_or_default()
288+
&& delegation.qself.is_none()
289+
{
290+
let ast_segment = delegation.path.segments.last().unwrap();
291+
let segment = self.lower_path_segment(
292+
delegation.path.span,
293+
ast_segment,
294+
ParamMode::Optional,
295+
ParenthesizedGenericArgs::Err,
296+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
297+
None,
298+
None,
299+
);
300+
let segment = self.arena.alloc(segment);
301+
302+
let args = &*self.arena.alloc_from_iter(args);
303+
let (stmts, receiver, args, block_id) = if let Some(target_expr) = target_expr {
304+
// Use unit type as a receiver if no expression is provided.
305+
let receiver = target_expr.expr.unwrap_or_else(|| {
306+
self.arena.alloc(self.mk_expr(hir::ExprKind::Tup(&[]), span))
307+
});
308+
(target_expr.stmts, receiver, args, target_expr.hir_id)
309+
} else {
310+
(&*self.arena.alloc_from_iter([]), &args[0], &args[1..], self.next_id())
311+
};
295312

296-
let expr = self.arena.alloc(hir::Expr {
297-
hir_id: self.next_id(),
298-
kind: hir::ExprKind::Call(callee, args),
299-
span: path.span(),
300-
});
313+
let method_call_id = self.next_id();
314+
if let Some(traits) = self.resolver.delegation_trait_map.remove(&delegation.id) {
315+
self.trait_map.insert(method_call_id.local_id, traits.into_boxed_slice());
316+
}
317+
318+
let method_call = self.arena.alloc(hir::Expr {
319+
hir_id: method_call_id,
320+
kind: hir::ExprKind::MethodCall(segment, receiver, args, span),
321+
span,
322+
});
323+
324+
(stmts, method_call, block_id)
325+
} else {
326+
let path = self.lower_qpath(
327+
delegation.id,
328+
&delegation.qself,
329+
&delegation.path,
330+
ParamMode::Optional,
331+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
332+
None,
333+
);
334+
335+
if let Some(target_expr) = target_expr {
336+
let target_expr = self.arena.alloc(target_expr);
337+
let fst_arg =
338+
self.mk_expr(hir::ExprKind::Block(target_expr, None), target_expr.span);
339+
args.insert(0, fst_arg);
340+
}
301341

342+
let args = self.arena.alloc_from_iter(args);
343+
let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span));
344+
345+
let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span));
346+
347+
(&*self.arena.alloc_from_iter([]), call, self.next_id())
348+
};
302349
let block = self.arena.alloc(hir::Block {
303-
stmts: &[],
304-
expr: Some(expr),
305-
hir_id: self.next_id(),
350+
stmts,
351+
expr: Some(call),
352+
hir_id: block_id,
306353
rules: hir::BlockCheckMode::DefaultBlock,
307-
span: path.span(),
354+
span,
308355
targeted_by_break: false,
309356
});
310-
311-
hir::Expr {
312-
hir_id: self.next_id(),
313-
kind: hir::ExprKind::Block(block, None),
314-
span: path.span(),
315-
}
357+
self.mk_expr(hir::ExprKind::Block(block, None), span)
316358
}
317359

318360
fn generate_delegation_error(
@@ -333,11 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
333375
let header = self.generate_header_error();
334376
let sig = hir::FnSig { decl, header, span };
335377

336-
let body_id = self.lower_body(|this| {
337-
let expr =
338-
hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span };
339-
(&[], expr)
340-
});
378+
let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span)));
341379
DelegationResults { generics, body_id, sig }
342380
}
343381

@@ -349,6 +387,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
349387
abi: abi::Abi::Rust,
350388
}
351389
}
390+
391+
#[inline]
392+
fn mk_expr(&mut self, kind: hir::ExprKind<'hir>, span: Span) -> hir::Expr<'hir> {
393+
hir::Expr { hir_id: self.next_id(), kind, span }
394+
}
352395
}
353396

354397
struct SelfResolver<'a> {

‎compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,8 +1218,54 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12181218
)>,
12191219
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
12201220
) -> Option<PickResult<'tcx>> {
1221+
// Delegation item can be expanded into method calls or fully qualified calls
1222+
// depending on the callee's signature. Method calls are used to allow
1223+
// autoref/autoderef for target expression. For example in:
1224+
//
1225+
// trait Trait : Sized {
1226+
// fn by_value(self) -> i32 { 1 }
1227+
// fn by_mut_ref(&mut self) -> i32 { 2 }
1228+
// fn by_ref(&self) -> i32 { 3 }
1229+
// }
1230+
//
1231+
// struct NewType(SomeType);
1232+
// impl Trait for NewType {
1233+
// reuse Trait::* { self.0 }
1234+
// }
1235+
//
1236+
// `self.0` will automatically coerce. The difference with existing method lookup
1237+
// is that methods in delegation items are pre-resolved by callee path (`Trait::*`).
1238+
// Therefore, we are only forced to consider the pre-resolved method here.
1239+
let delegation_res = if self.fcx.tcx.hir().opt_delegation_sig_id(self.body_id).is_some() {
1240+
let body = self.tcx.hir().body_owned_by(self.body_id);
1241+
let block = match body.value.kind {
1242+
hir::ExprKind::Block(block, _) => block,
1243+
_ => unreachable!(),
1244+
};
1245+
let expr = block.expr.unwrap();
1246+
let res_id = match expr.kind {
1247+
hir::ExprKind::MethodCall(segment, ..) => segment.res.def_id(),
1248+
hir::ExprKind::Call(
1249+
hir::Expr { kind: hir::ExprKind::Path(hir::QPath::Resolved(_, path)), .. },
1250+
_,
1251+
) => path.res.def_id(),
1252+
_ => unreachable!(),
1253+
};
1254+
Some((expr.hir_id, res_id))
1255+
} else {
1256+
None
1257+
};
12211258
let mut applicable_candidates: Vec<_> = candidates
12221259
.iter()
1260+
.filter(|candidate| {
1261+
if let Some((expr_id, res_id)) = delegation_res
1262+
&& self.scope_expr_id == expr_id
1263+
&& candidate.item.def_id != res_id
1264+
{
1265+
return false;
1266+
}
1267+
true
1268+
})
12231269
.map(|probe| {
12241270
(probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
12251271
})

‎compiler/rustc_middle/src/hir/map/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,21 @@ impl<'hir> Map<'hir> {
728728
}
729729
}
730730

731+
pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
732+
if let Some(ret) = self.get_fn_output(def_id)
733+
&& let FnRetTy::Return(ty) = ret
734+
&& let TyKind::InferDelegation(sig_id, _) = ty.kind
735+
{
736+
return Some(sig_id);
737+
}
738+
None
739+
}
740+
741+
#[inline]
742+
pub fn delegation_sig_id(self, def_id: LocalDefId) -> DefId {
743+
self.opt_delegation_sig_id(def_id).unwrap()
744+
}
745+
731746
#[inline]
732747
fn opt_ident(self, id: HirId) -> Option<Ident> {
733748
match self.tcx.hir_node(id) {

‎compiler/rustc_middle/src/ty/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,10 @@ pub struct ResolverAstLowering {
224224
/// Lints that were emitted by the resolver and early lints.
225225
pub lint_buffer: Steal<LintBuffer>,
226226

227-
/// Information about functions signatures for delegation items expansion
227+
/// Information about functions signatures for delegation items expansion.
228228
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
229+
/// Separate `trait_map` for delegation items only.
230+
pub delegation_trait_map: NodeMap<Vec<hir::TraitCandidate>>,
229231
}
230232

231233
#[derive(Debug)]

‎compiler/rustc_resolve/src/late.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,15 +3315,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
33153315
if let Some(qself) = &delegation.qself {
33163316
self.visit_ty(&qself.ty);
33173317
}
3318+
let last_segment = delegation.path.segments.last().unwrap();
3319+
let traits = self.traits_in_scope(last_segment.ident, ValueNS);
3320+
// Saving traits for a `MethodCall` that has not yet been generated.
3321+
self.r.delegation_trait_map.insert(delegation.id, traits);
3322+
33183323
self.visit_path(&delegation.path, delegation.id);
33193324
if let Some(body) = &delegation.body {
33203325
self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
33213326
// `PatBoundCtx` is not necessary in this context
33223327
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
33233328

3324-
let span = delegation.path.segments.last().unwrap().ident.span;
33253329
this.fresh_binding(
3326-
Ident::new(kw::SelfLower, span),
3330+
Ident::new(kw::SelfLower, last_segment.ident.span),
33273331
delegation.id,
33283332
PatternSource::FnParam,
33293333
&mut bindings,

‎compiler/rustc_resolve/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,7 @@ pub struct Resolver<'a, 'tcx> {
11461146
/// Amount of lifetime parameters for each item in the crate.
11471147
item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
11481148
delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
1149+
delegation_trait_map: NodeMap<Vec<TraitCandidate>>,
11491150

11501151
main_def: Option<MainDefinition>,
11511152
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -1513,6 +1514,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15131514
doc_link_traits_in_scope: Default::default(),
15141515
all_macro_rules: Default::default(),
15151516
delegation_fn_sigs: Default::default(),
1517+
delegation_trait_map: NodeMap::default(),
15161518
glob_delegation_invoc_ids: Default::default(),
15171519
impl_unexpanded_invocations: Default::default(),
15181520
impl_binding_keys: Default::default(),
@@ -1629,6 +1631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16291631
lifetime_elision_allowed: self.lifetime_elision_allowed,
16301632
lint_buffer: Steal::new(self.lint_buffer),
16311633
delegation_fn_sigs: self.delegation_fn_sigs,
1634+
delegation_trait_map: self.delegation_trait_map,
16321635
};
16331636
ResolverOutputs { global_ctxt, ast_lowering }
16341637
}

‎tests/ui/delegation/bad-resolve.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ impl Trait for S {
3434

3535
reuse foo { &self.0 }
3636
//~^ ERROR cannot find function `foo` in this scope
37+
reuse Trait::foo2 { self.0 }
38+
//~^ ERROR cannot find function `foo2` in trait `Trait`
39+
//~| ERROR method `foo2` is not a member of trait `Trait`
3740
}
3841

3942
mod prefix {}

‎tests/ui/delegation/bad-resolve.stderr

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ LL | reuse <F as Trait>::baz;
2525
| | help: there is an associated function with a similar name: `bar`
2626
| not a member of trait `Trait`
2727

28+
error[E0407]: method `foo2` is not a member of trait `Trait`
29+
--> $DIR/bad-resolve.rs:37:5
30+
|
31+
LL | reuse Trait::foo2 { self.0 }
32+
| ^^^^^^^^^^^^^----^^^^^^^^^^^
33+
| | |
34+
| | help: there is an associated function with a similar name: `foo`
35+
| not a member of trait `Trait`
36+
2837
error[E0423]: expected function, found associated constant `Trait::C`
2938
--> $DIR/bad-resolve.rs:24:11
3039
|
@@ -54,6 +63,15 @@ error[E0425]: cannot find function `foo` in this scope
5463
LL | reuse foo { &self.0 }
5564
| ^^^ not found in this scope
5665

66+
error[E0425]: cannot find function `foo2` in trait `Trait`
67+
--> $DIR/bad-resolve.rs:37:18
68+
|
69+
LL | fn foo(&self, x: i32) -> i32 { x }
70+
| ---------------------------- similarly named associated function `foo` defined here
71+
...
72+
LL | reuse Trait::foo2 { self.0 }
73+
| ^^^^ help: an associated function with a similar name exists: `foo`
74+
5775
error[E0046]: not all trait items implemented, missing: `Type`
5876
--> $DIR/bad-resolve.rs:22:1
5977
|
@@ -64,18 +82,18 @@ LL | impl Trait for S {
6482
| ^^^^^^^^^^^^^^^^ missing `Type` in implementation
6583

6684
error[E0433]: failed to resolve: use of undeclared crate or module `unresolved_prefix`
67-
--> $DIR/bad-resolve.rs:40:7
85+
--> $DIR/bad-resolve.rs:43:7
6886
|
6987
LL | reuse unresolved_prefix::{a, b, c};
7088
| ^^^^^^^^^^^^^^^^^ use of undeclared crate or module `unresolved_prefix`
7189

7290
error[E0433]: failed to resolve: `crate` in paths can only be used in start position
73-
--> $DIR/bad-resolve.rs:41:29
91+
--> $DIR/bad-resolve.rs:44:29
7492
|
7593
LL | reuse prefix::{self, super, crate};
7694
| ^^^^^ `crate` in paths can only be used in start position
7795

78-
error: aborting due to 10 previous errors
96+
error: aborting due to 12 previous errors
7997

8098
Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576.
8199
For more information about an error, try `rustc --explain E0046`.

‎tests/ui/delegation/explicit-paths-pass.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ reuse to_reuse::zero_args { self }
2424

2525
struct S(F);
2626
impl Trait for S {
27-
reuse Trait::bar { &self.0 }
28-
reuse Trait::description { &self.0 }
27+
reuse Trait::bar { self.0 }
28+
reuse Trait::description { self.0 }
2929
reuse <F as Trait>::static_method;
3030
reuse <F as Trait>::static_method2 { S::static_method(self) }
3131
}

‎tests/ui/delegation/explicit-paths.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ mod inherent_impl_assoc_fn_to_other {
3434
use crate::*;
3535

3636
impl S {
37-
reuse Trait::foo1 { &self.0 }
37+
reuse Trait::foo1 { self.0 }
3838
reuse <S as Trait>::foo2;
3939
reuse to_reuse::foo3;
4040
reuse F::foo4 { &self.0 }
@@ -46,7 +46,7 @@ mod trait_impl_assoc_fn_to_other {
4646
use crate::*;
4747

4848
impl Trait for S {
49-
reuse Trait::foo1 { &self.0 }
49+
reuse Trait::foo1 { self.0 }
5050
reuse <F as Trait>::foo2;
5151
reuse to_reuse::foo3;
5252
//~^ ERROR method `foo3` is not a member of trait `Trait`

‎tests/ui/delegation/explicit-paths.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ error[E0308]: mismatched types
110110
--> $DIR/explicit-paths.rs:78:30
111111
|
112112
LL | reuse <S2 as Trait>::foo1;
113-
| ---------------^^^^
114-
| | |
115-
| | expected `&S2`, found `&S`
116-
| arguments to this function are incorrect
113+
| ^^^^
114+
| |
115+
| expected `&S2`, found `&S`
116+
| arguments to this function are incorrect
117117
|
118118
= note: expected reference `&S2`
119119
found reference `&S`

‎tests/ui/delegation/glob-glob.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ mod inner {
1919
}
2020
}
2121

22+
use inner::*;
23+
2224
trait Trait {
2325
fn foo(&self) -> u8;
2426
fn bar(&self) -> u8;
@@ -31,6 +33,6 @@ impl Trait for u8 {
3133

3234
fn main() {
3335
let u = 0u8;
34-
u.foo();
35-
u.bar();
36+
<u8 as Trait>::foo(&u);
37+
<u8 as Trait>::bar(&u);
3638
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ run-pass
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features)]
5+
#![allow(dead_code)]
6+
7+
trait Trait1 {
8+
fn foo(&self) -> i32 { 1 }
9+
}
10+
11+
trait Trait2 {
12+
fn foo(&self) -> i32 { 2 }
13+
}
14+
15+
struct F;
16+
impl Trait1 for F {}
17+
impl Trait2 for F {}
18+
19+
impl F {
20+
fn foo(&self) -> i32 { 3 }
21+
}
22+
23+
struct S(F);
24+
25+
impl Trait1 for S {
26+
reuse Trait1::foo { self.0 }
27+
}
28+
29+
fn main() {
30+
let s = S(F);
31+
assert_eq!(s.foo(), 1);
32+
}

‎tests/ui/delegation/self-coercion.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//@ run-pass
2+
3+
#![feature(fn_delegation)]
4+
#![allow(incomplete_features)]
5+
6+
trait Trait : Sized {
7+
fn by_value(self) -> i32 { 1 }
8+
fn by_mut_ref(&mut self) -> i32 { 2 }
9+
fn by_ref(&self) -> i32 { 3 }
10+
}
11+
12+
struct F;
13+
impl Trait for F {}
14+
15+
struct S(F);
16+
17+
impl Trait for S {
18+
reuse Trait::{by_value, by_mut_ref, by_ref} { self.0 }
19+
}
20+
21+
fn main() {
22+
let mut s = S(F);
23+
assert_eq!(s.by_ref(), 3);
24+
assert_eq!(s.by_mut_ref(), 2);
25+
assert_eq!(s.by_value(), 1);
26+
}

‎tests/ui/delegation/target-expr.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33

44
trait Trait {
55
fn static_method(x: i32) -> i32 { x }
6+
fn foo(&self) {}
67
}
78

89
struct F;
910

1011
struct S(F);
11-
impl Trait for S {}
12+
impl Trait for S {
13+
reuse Trait::foo { self.0; }
14+
//~^ ERROR no method named `foo` found for unit type `()` in the current scope
15+
}
1216

1317
fn foo(x: i32) -> i32 { x }
1418

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0401]: can't use generic parameters from outer item
2-
--> $DIR/target-expr.rs:20:17
2+
--> $DIR/target-expr.rs:24:17
33
|
44
LL | fn bar<T: Default>(_: T) {
55
| - type parameter from outer item
@@ -10,15 +10,15 @@ LL | let _ = T::Default();
1010
| ^^^^^^^^^^ use of generic parameter from outer item
1111

1212
error[E0434]: can't capture dynamic environment in a fn item
13-
--> $DIR/target-expr.rs:29:17
13+
--> $DIR/target-expr.rs:33:17
1414
|
1515
LL | let x = y;
1616
| ^
1717
|
1818
= help: use the `|| { ... }` closure form instead
1919

2020
error[E0424]: expected value, found module `self`
21-
--> $DIR/target-expr.rs:36:5
21+
--> $DIR/target-expr.rs:40:5
2222
|
2323
LL | fn main() {
2424
| ---- this function can't have a `self` parameter
@@ -27,19 +27,19 @@ LL | self.0;
2727
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
2828

2929
error[E0425]: cannot find value `x` in this scope
30-
--> $DIR/target-expr.rs:38:13
30+
--> $DIR/target-expr.rs:42:13
3131
|
3232
LL | let z = x;
3333
| ^
3434
|
3535
help: the binding `x` is available in a different scope in the same function
36-
--> $DIR/target-expr.rs:29:13
36+
--> $DIR/target-expr.rs:33:13
3737
|
3838
LL | let x = y;
3939
| ^
4040

4141
error: delegation with early bound generics is not supported yet
42-
--> $DIR/target-expr.rs:16:18
42+
--> $DIR/target-expr.rs:20:18
4343
|
4444
LL | fn static_method(x: i32) -> i32 { x }
4545
| ------------------------------- callee defined here
@@ -48,7 +48,7 @@ LL | reuse Trait::static_method {
4848
| ^^^^^^^^^^^^^
4949

5050
error: delegation to a trait method from a free function is not supported yet
51-
--> $DIR/target-expr.rs:16:18
51+
--> $DIR/target-expr.rs:20:18
5252
|
5353
LL | fn static_method(x: i32) -> i32 { x }
5454
| ------------------------------- callee defined here
@@ -57,16 +57,29 @@ LL | reuse Trait::static_method {
5757
| ^^^^^^^^^^^^^
5858

5959
error: delegation to a trait method from a free function is not supported yet
60-
--> $DIR/target-expr.rs:27:25
60+
--> $DIR/target-expr.rs:31:25
6161
|
6262
LL | fn static_method(x: i32) -> i32 { x }
6363
| ------------------------------- callee defined here
6464
...
6565
LL | reuse <S as Trait>::static_method {
6666
| ^^^^^^^^^^^^^
6767

68+
error[E0599]: no method named `foo` found for unit type `()` in the current scope
69+
--> $DIR/target-expr.rs:13:18
70+
|
71+
LL | reuse Trait::foo { self.0; }
72+
| ^^^ method not found in `()`
73+
|
74+
= help: items from traits can only be used if the trait is implemented and in scope
75+
note: `Trait` defines an item `foo`, perhaps you need to implement it
76+
--> $DIR/target-expr.rs:4:1
77+
|
78+
LL | trait Trait {
79+
| ^^^^^^^^^^^
80+
6881
error[E0308]: mismatched types
69-
--> $DIR/target-expr.rs:16:32
82+
--> $DIR/target-expr.rs:20:32
7083
|
7184
LL | reuse Trait::static_method {
7285
| ________________________________^
@@ -78,7 +91,7 @@ LL | |
7891
LL | | }
7992
| |_____^ expected `i32`, found `()`
8093

81-
error: aborting due to 8 previous errors
94+
error: aborting due to 9 previous errors
8295

83-
Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434.
96+
Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434, E0599.
8497
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)
Please sign in to comment.