Skip to content

Commit 20a8314

Browse files
Support RTN on associated methods from supertraits
1 parent 82cd953 commit 20a8314

File tree

9 files changed

+115
-31
lines changed

9 files changed

+115
-31
lines changed

compiler/rustc_hir_analysis/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ hir_analysis_return_type_notation_equality_bound =
192192
return type notation is not allowed to use type equality
193193
194194
hir_analysis_return_type_notation_missing_method =
195-
cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
195+
cannot find associated function `{$assoc_name}` for `{$ty_name}`
196196
197197
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
198198
.label = not allowed in type signatures

compiler/rustc_hir_analysis/src/astconv/mod.rs

+38-5
Original file line numberDiff line numberDiff line change
@@ -1118,11 +1118,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11181118
) {
11191119
trait_ref
11201120
} else {
1121-
return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
1122-
span: binding.span,
1123-
trait_name: tcx.item_name(trait_ref.def_id()),
1124-
assoc_name: binding.item_name.name,
1125-
}));
1121+
self.one_bound_for_assoc_method(
1122+
traits::supertraits(tcx, trait_ref),
1123+
trait_ref.print_only_trait_path(),
1124+
binding.item_name,
1125+
path_span,
1126+
)?
11261127
}
11271128
} else if self.trait_defines_associated_item_named(
11281129
trait_ref.def_id(),
@@ -2057,6 +2058,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20572058
Ok(bound)
20582059
}
20592060

2061+
#[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)]
2062+
fn one_bound_for_assoc_method(
2063+
&self,
2064+
all_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
2065+
ty_name: impl Display,
2066+
assoc_name: Ident,
2067+
span: Span,
2068+
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
2069+
let mut matching_candidates = all_candidates.filter(|r| {
2070+
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
2071+
});
2072+
2073+
let candidate = match matching_candidates.next() {
2074+
Some(candidate) => candidate,
2075+
None => {
2076+
return Err(self.tcx().sess.emit_err(
2077+
crate::errors::ReturnTypeNotationMissingMethod {
2078+
span,
2079+
ty_name: ty_name.to_string(),
2080+
assoc_name: assoc_name.name,
2081+
},
2082+
));
2083+
}
2084+
};
2085+
2086+
if let Some(_conflicting_candidate) = matching_candidates.next() {
2087+
todo!()
2088+
}
2089+
2090+
Ok(candidate)
2091+
}
2092+
20602093
// Create a type from a path to an associated type or to an enum variant.
20612094
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
20622095
// and item_segment is the path segment for `D`. We return a type and a def for

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+31-21
Original file line numberDiff line numberDiff line change
@@ -1652,27 +1652,28 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16521652
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
16531653
let bound_vars = if let Some(type_def_id) = type_def_id
16541654
&& self.tcx.def_kind(type_def_id) == DefKind::Trait
1655-
// FIXME(return_type_notation): We could bound supertrait methods.
1656-
&& let Some(assoc_fn) = self
1657-
.tcx
1658-
.associated_items(type_def_id)
1659-
.find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
1655+
&& let Some((mut bound_vars, assoc_fn)) =
1656+
BoundVarContext::supertrait_hrtb_vars(
1657+
self.tcx,
1658+
type_def_id,
1659+
binding.ident,
1660+
ty::AssocKind::Fn,
1661+
)
16601662
{
1661-
self.tcx
1662-
.generics_of(assoc_fn.def_id)
1663-
.params
1664-
.iter()
1665-
.map(|param| match param.kind {
1663+
bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).params.iter().map(
1664+
|param| match param.kind {
16661665
ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
16671666
ty::BoundRegionKind::BrNamed(param.def_id, param.name),
16681667
),
16691668
ty::GenericParamDefKind::Type { .. } => ty::BoundVariableKind::Ty(
16701669
ty::BoundTyKind::Param(param.def_id, param.name),
16711670
),
16721671
ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
1673-
})
1674-
.chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars())
1675-
.collect()
1672+
},
1673+
));
1674+
bound_vars
1675+
.extend(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars());
1676+
bound_vars
16761677
} else {
16771678
self.tcx.sess.delay_span_bug(
16781679
binding.ident.span,
@@ -1689,8 +1690,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
16891690
});
16901691
});
16911692
} else if let Some(type_def_id) = type_def_id {
1692-
let bound_vars =
1693-
BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
1693+
let bound_vars = BoundVarContext::supertrait_hrtb_vars(
1694+
self.tcx,
1695+
type_def_id,
1696+
binding.ident,
1697+
ty::AssocKind::Type,
1698+
)
1699+
.map(|(bound_vars, _)| bound_vars);
16941700
self.with(scope, |this| {
16951701
let scope = Scope::Supertrait {
16961702
bound_vars: bound_vars.unwrap_or_default(),
@@ -1720,11 +1726,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17201726
tcx: TyCtxt<'tcx>,
17211727
def_id: DefId,
17221728
assoc_name: Ident,
1723-
) -> Option<Vec<ty::BoundVariableKind>> {
1729+
assoc_kind: ty::AssocKind,
1730+
) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
17241731
let trait_defines_associated_type_named = |trait_def_id: DefId| {
1725-
tcx.associated_items(trait_def_id)
1726-
.find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
1727-
.is_some()
1732+
tcx.associated_items(trait_def_id).find_by_name_and_kind(
1733+
tcx,
1734+
assoc_name,
1735+
assoc_kind,
1736+
trait_def_id,
1737+
)
17281738
};
17291739

17301740
use smallvec::{smallvec, SmallVec};
@@ -1742,8 +1752,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17421752
_ => break None,
17431753
}
17441754

1745-
if trait_defines_associated_type_named(def_id) {
1746-
break Some(bound_vars.into_iter().collect());
1755+
if let Some(assoc_item) = trait_defines_associated_type_named(def_id) {
1756+
break Some((bound_vars.into_iter().collect(), assoc_item));
17471757
}
17481758
let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
17491759
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {

compiler/rustc_hir_analysis/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
512512
pub(crate) struct ReturnTypeNotationMissingMethod {
513513
#[primary_span]
514514
pub span: Span,
515-
pub trait_name: Symbol,
515+
pub ty_name: String,
516516
pub assoc_name: Symbol,
517517
}
518518

compiler/rustc_middle/src/ty/context.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1570,7 +1570,12 @@ impl<'tcx> TyCtxt<'tcx> {
15701570
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
15711571
self.super_traits_of(trait_def_id).any(|trait_did| {
15721572
self.associated_items(trait_did)
1573-
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
1573+
.find_by_name_and_kinds(
1574+
self,
1575+
assoc_name,
1576+
&[ty::AssocKind::Type, ty::AssocKind::Const, ty::AssocKind::Fn],
1577+
trait_did,
1578+
)
15741579
.is_some()
15751580
})
15761581
}

tests/ui/associated-type-bounds/return-type-notation/missing.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ trait Trait {
88
}
99

1010
fn bar<T: Trait<methid(): Send>>() {}
11-
//~^ ERROR cannot find associated function `methid` in trait `Trait`
11+
//~^ ERROR cannot find associated function `methid` for `Trait`
1212

1313
fn main() {}

tests/ui/associated-type-bounds/return-type-notation/missing.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
77
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
88
= note: `#[warn(incomplete_features)]` on by default
99

10-
error: cannot find associated function `methid` in trait `Trait`
10+
error: cannot find associated function `methid` for `Trait`
1111
--> $DIR/missing.rs:10:17
1212
|
1313
LL | fn bar<T: Trait<methid(): Send>>() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// edition:2021
2+
// check-pass
3+
4+
#![feature(async_fn_in_trait, return_type_notation)]
5+
//~^ WARN the feature `return_type_notation` is incomplete
6+
7+
trait Super<'a> {
8+
async fn test();
9+
}
10+
impl Super<'_> for () {
11+
async fn test() {}
12+
}
13+
14+
trait Foo: for<'a> Super<'a> {}
15+
impl Foo for () {}
16+
17+
fn test<T>()
18+
where
19+
T: Foo<test(): Send>,
20+
{
21+
}
22+
23+
fn main() {
24+
test::<()>();
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/super-method-bound.rs:4:31
3+
|
4+
LL | #![feature(async_fn_in_trait, return_type_notation)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

0 commit comments

Comments
 (0)