mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Support RTN on associated methods from supertraits
This commit is contained in:
parent
82cd953c7c
commit
20a83144b2
@ -192,7 +192,7 @@ hir_analysis_return_type_notation_equality_bound =
|
||||
return type notation is not allowed to use type equality
|
||||
|
||||
hir_analysis_return_type_notation_missing_method =
|
||||
cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
|
||||
cannot find associated function `{$assoc_name}` for `{$ty_name}`
|
||||
|
||||
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
|
||||
.label = not allowed in type signatures
|
||||
|
@ -1118,11 +1118,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
) {
|
||||
trait_ref
|
||||
} else {
|
||||
return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
|
||||
span: binding.span,
|
||||
trait_name: tcx.item_name(trait_ref.def_id()),
|
||||
assoc_name: binding.item_name.name,
|
||||
}));
|
||||
self.one_bound_for_assoc_method(
|
||||
traits::supertraits(tcx, trait_ref),
|
||||
trait_ref.print_only_trait_path(),
|
||||
binding.item_name,
|
||||
path_span,
|
||||
)?
|
||||
}
|
||||
} else if self.trait_defines_associated_item_named(
|
||||
trait_ref.def_id(),
|
||||
@ -2057,6 +2058,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
Ok(bound)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)]
|
||||
fn one_bound_for_assoc_method(
|
||||
&self,
|
||||
all_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||
ty_name: impl Display,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
||||
let mut matching_candidates = all_candidates.filter(|r| {
|
||||
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
|
||||
});
|
||||
|
||||
let candidate = match matching_candidates.next() {
|
||||
Some(candidate) => candidate,
|
||||
None => {
|
||||
return Err(self.tcx().sess.emit_err(
|
||||
crate::errors::ReturnTypeNotationMissingMethod {
|
||||
span,
|
||||
ty_name: ty_name.to_string(),
|
||||
assoc_name: assoc_name.name,
|
||||
},
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(_conflicting_candidate) = matching_candidates.next() {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Ok(candidate)
|
||||
}
|
||||
|
||||
// Create a type from a path to an associated type or to an enum variant.
|
||||
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
|
||||
// and item_segment is the path segment for `D`. We return a type and a def for
|
||||
|
@ -1652,17 +1652,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
|
||||
let bound_vars = if let Some(type_def_id) = type_def_id
|
||||
&& self.tcx.def_kind(type_def_id) == DefKind::Trait
|
||||
// FIXME(return_type_notation): We could bound supertrait methods.
|
||||
&& let Some(assoc_fn) = self
|
||||
.tcx
|
||||
.associated_items(type_def_id)
|
||||
.find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
|
||||
&& let Some((mut bound_vars, assoc_fn)) =
|
||||
BoundVarContext::supertrait_hrtb_vars(
|
||||
self.tcx,
|
||||
type_def_id,
|
||||
binding.ident,
|
||||
ty::AssocKind::Fn,
|
||||
)
|
||||
{
|
||||
self.tcx
|
||||
.generics_of(assoc_fn.def_id)
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| match param.kind {
|
||||
bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).params.iter().map(
|
||||
|param| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
|
||||
ty::BoundRegionKind::BrNamed(param.def_id, param.name),
|
||||
),
|
||||
@ -1670,9 +1669,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
ty::BoundTyKind::Param(param.def_id, param.name),
|
||||
),
|
||||
ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
|
||||
})
|
||||
.chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars())
|
||||
.collect()
|
||||
},
|
||||
));
|
||||
bound_vars
|
||||
.extend(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars());
|
||||
bound_vars
|
||||
} else {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
binding.ident.span,
|
||||
@ -1689,8 +1690,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
});
|
||||
});
|
||||
} else if let Some(type_def_id) = type_def_id {
|
||||
let bound_vars =
|
||||
BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
|
||||
let bound_vars = BoundVarContext::supertrait_hrtb_vars(
|
||||
self.tcx,
|
||||
type_def_id,
|
||||
binding.ident,
|
||||
ty::AssocKind::Type,
|
||||
)
|
||||
.map(|(bound_vars, _)| bound_vars);
|
||||
self.with(scope, |this| {
|
||||
let scope = Scope::Supertrait {
|
||||
bound_vars: bound_vars.unwrap_or_default(),
|
||||
@ -1720,11 +1726,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
assoc_name: Ident,
|
||||
) -> Option<Vec<ty::BoundVariableKind>> {
|
||||
assoc_kind: ty::AssocKind,
|
||||
) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
|
||||
let trait_defines_associated_type_named = |trait_def_id: DefId| {
|
||||
tcx.associated_items(trait_def_id)
|
||||
.find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
|
||||
.is_some()
|
||||
tcx.associated_items(trait_def_id).find_by_name_and_kind(
|
||||
tcx,
|
||||
assoc_name,
|
||||
assoc_kind,
|
||||
trait_def_id,
|
||||
)
|
||||
};
|
||||
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
@ -1742,8 +1752,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||
_ => break None,
|
||||
}
|
||||
|
||||
if trait_defines_associated_type_named(def_id) {
|
||||
break Some(bound_vars.into_iter().collect());
|
||||
if let Some(assoc_item) = trait_defines_associated_type_named(def_id) {
|
||||
break Some((bound_vars.into_iter().collect(), assoc_item));
|
||||
}
|
||||
let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
|
||||
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
|
||||
|
@ -512,7 +512,7 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
|
||||
pub(crate) struct ReturnTypeNotationMissingMethod {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: Symbol,
|
||||
pub ty_name: String,
|
||||
pub assoc_name: Symbol,
|
||||
}
|
||||
|
||||
|
@ -1570,7 +1570,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
||||
self.super_traits_of(trait_def_id).any(|trait_did| {
|
||||
self.associated_items(trait_did)
|
||||
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
|
||||
.find_by_name_and_kinds(
|
||||
self,
|
||||
assoc_name,
|
||||
&[ty::AssocKind::Type, ty::AssocKind::Const, ty::AssocKind::Fn],
|
||||
trait_did,
|
||||
)
|
||||
.is_some()
|
||||
})
|
||||
}
|
||||
|
@ -8,6 +8,6 @@ trait Trait {
|
||||
}
|
||||
|
||||
fn bar<T: Trait<methid(): Send>>() {}
|
||||
//~^ ERROR cannot find associated function `methid` in trait `Trait`
|
||||
//~^ ERROR cannot find associated function `methid` for `Trait`
|
||||
|
||||
fn main() {}
|
||||
|
@ -7,7 +7,7 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: cannot find associated function `methid` in trait `Trait`
|
||||
error: cannot find associated function `methid` for `Trait`
|
||||
--> $DIR/missing.rs:10:17
|
||||
|
|
||||
LL | fn bar<T: Trait<methid(): Send>>() {}
|
||||
|
@ -0,0 +1,25 @@
|
||||
// edition:2021
|
||||
// check-pass
|
||||
|
||||
#![feature(async_fn_in_trait, return_type_notation)]
|
||||
//~^ WARN the feature `return_type_notation` is incomplete
|
||||
|
||||
trait Super<'a> {
|
||||
async fn test();
|
||||
}
|
||||
impl Super<'_> for () {
|
||||
async fn test() {}
|
||||
}
|
||||
|
||||
trait Foo: for<'a> Super<'a> {}
|
||||
impl Foo for () {}
|
||||
|
||||
fn test<T>()
|
||||
where
|
||||
T: Foo<test(): Send>,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test::<()>();
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/super-method-bound.rs:4:31
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait, return_type_notation)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
Loading…
Reference in New Issue
Block a user