Auto merge of #111161 - compiler-errors:rtn-super, r=cjgillot
Support return-type bounds on associated methods from supertraits Support `T: Trait<method(): Bound>` when `method` comes from a supertrait, aligning it with the behavior of associated type bounds (both equality and trait bounds). The only wrinkle is that I have to extend `super_predicates_that_define_assoc_type` to look for *all* items, not just `AssocKind::Ty`. This will also be needed to support `feature(associated_const_equality)` as well, which is subtly broken when it comes to supertraits, though this PR does not fix those yet. There's a slight chance there's a perf regression here, in which case I guess I could split it out into a separate query.
This commit is contained in:
commit
0dddad0dc5
17 changed files with 210 additions and 50 deletions
|
@ -192,7 +192,11 @@ hir_analysis_return_type_notation_equality_bound =
|
||||||
return type notation is not allowed to use type equality
|
return type notation is not allowed to use type equality
|
||||||
|
|
||||||
hir_analysis_return_type_notation_missing_method =
|
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_return_type_notation_conflicting_bound =
|
||||||
|
ambiguous associated function `{$assoc_name}` for `{$ty_name}`
|
||||||
|
.note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
|
||||||
|
|
||||||
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
|
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
|
.label = not allowed in type signatures
|
||||||
|
|
|
@ -1062,7 +1062,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
|
|
||||||
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
|
||||||
/// named `assoc_name` into ty::Bounds. Ignore the rest.
|
/// named `assoc_name` into ty::Bounds. Ignore the rest.
|
||||||
pub(crate) fn compute_bounds_that_match_assoc_type(
|
pub(crate) fn compute_bounds_that_match_assoc_item(
|
||||||
&self,
|
&self,
|
||||||
param_ty: Ty<'tcx>,
|
param_ty: Ty<'tcx>,
|
||||||
ast_bounds: &[hir::GenericBound<'_>],
|
ast_bounds: &[hir::GenericBound<'_>],
|
||||||
|
@ -1073,7 +1073,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
for ast_bound in ast_bounds {
|
for ast_bound in ast_bounds {
|
||||||
if let Some(trait_ref) = ast_bound.trait_ref()
|
if let Some(trait_ref) = ast_bound.trait_ref()
|
||||||
&& let Some(trait_did) = trait_ref.trait_def_id()
|
&& let Some(trait_did) = trait_ref.trait_def_id()
|
||||||
&& self.tcx().trait_may_define_assoc_type(trait_did, assoc_name)
|
&& self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
|
||||||
{
|
{
|
||||||
result.push(ast_bound.clone());
|
result.push(ast_bound.clone());
|
||||||
}
|
}
|
||||||
|
@ -1141,11 +1141,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
) {
|
) {
|
||||||
trait_ref
|
trait_ref
|
||||||
} else {
|
} else {
|
||||||
return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
|
self.one_bound_for_assoc_method(
|
||||||
span: binding.span,
|
traits::supertraits(tcx, trait_ref),
|
||||||
trait_name: tcx.item_name(trait_ref.def_id()),
|
trait_ref.print_only_trait_path(),
|
||||||
assoc_name: binding.item_name.name,
|
binding.item_name,
|
||||||
}));
|
path_span,
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
} else if self.trait_defines_associated_item_named(
|
} else if self.trait_defines_associated_item_named(
|
||||||
trait_ref.def_id(),
|
trait_ref.def_id(),
|
||||||
|
@ -1946,7 +1947,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
|
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
|
||||||
self.one_bound_for_assoc_type(
|
self.one_bound_for_assoc_type(
|
||||||
|| {
|
|| {
|
||||||
traits::transitive_bounds_that_define_assoc_type(
|
traits::transitive_bounds_that_define_assoc_item(
|
||||||
tcx,
|
tcx,
|
||||||
predicates.iter().filter_map(|(p, _)| {
|
predicates.iter().filter_map(|(p, _)| {
|
||||||
Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
|
Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
|
||||||
|
@ -2081,6 +2082,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
Ok(bound)
|
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() {
|
||||||
|
return Err(self.tcx().sess.emit_err(
|
||||||
|
crate::errors::ReturnTypeNotationConflictingBound {
|
||||||
|
span,
|
||||||
|
ty_name: ty_name.to_string(),
|
||||||
|
assoc_name: assoc_name.name,
|
||||||
|
first_bound: candidate.print_only_trait_path(),
|
||||||
|
second_bound: conflicting_candidate.print_only_trait_path(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(candidate)
|
||||||
|
}
|
||||||
|
|
||||||
// Create a type from a path to an associated type or to an enum variant.
|
// 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`
|
// 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
|
// and item_segment is the path segment for `D`. We return a type and a def for
|
||||||
|
|
|
@ -64,8 +64,8 @@ pub fn provide(providers: &mut Providers) {
|
||||||
explicit_predicates_of: predicates_of::explicit_predicates_of,
|
explicit_predicates_of: predicates_of::explicit_predicates_of,
|
||||||
super_predicates_of: predicates_of::super_predicates_of,
|
super_predicates_of: predicates_of::super_predicates_of,
|
||||||
implied_predicates_of: predicates_of::implied_predicates_of,
|
implied_predicates_of: predicates_of::implied_predicates_of,
|
||||||
super_predicates_that_define_assoc_type:
|
super_predicates_that_define_assoc_item:
|
||||||
predicates_of::super_predicates_that_define_assoc_type,
|
predicates_of::super_predicates_that_define_assoc_item,
|
||||||
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
|
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
|
||||||
type_param_predicates: predicates_of::type_param_predicates,
|
type_param_predicates: predicates_of::type_param_predicates,
|
||||||
trait_def,
|
trait_def,
|
||||||
|
|
|
@ -565,7 +565,7 @@ pub(super) fn super_predicates_of(
|
||||||
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
|
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn super_predicates_that_define_assoc_type(
|
pub(super) fn super_predicates_that_define_assoc_item(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
(trait_def_id, assoc_name): (DefId, Ident),
|
(trait_def_id, assoc_name): (DefId, Ident),
|
||||||
) -> ty::GenericPredicates<'_> {
|
) -> ty::GenericPredicates<'_> {
|
||||||
|
@ -640,7 +640,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||||
),
|
),
|
||||||
PredicateFilter::SelfThatDefines(assoc_name) => (
|
PredicateFilter::SelfThatDefines(assoc_name) => (
|
||||||
// Convert the bounds that follow the colon (or equal) that reference the associated name
|
// Convert the bounds that follow the colon (or equal) that reference the associated name
|
||||||
icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
|
icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name),
|
||||||
// Include where clause bounds for `Self` that reference the associated name
|
// Include where clause bounds for `Self` that reference the associated name
|
||||||
icx.type_parameter_bounds_in_generics(
|
icx.type_parameter_bounds_in_generics(
|
||||||
generics,
|
generics,
|
||||||
|
@ -819,7 +819,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||||
hir::GenericBound::Trait(poly_trait_ref, _) => {
|
hir::GenericBound::Trait(poly_trait_ref, _) => {
|
||||||
let trait_ref = &poly_trait_ref.trait_ref;
|
let trait_ref = &poly_trait_ref.trait_ref;
|
||||||
if let Some(trait_did) = trait_ref.trait_def_id() {
|
if let Some(trait_did) = trait_ref.trait_def_id() {
|
||||||
self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
|
self.tcx.trait_may_define_assoc_item(trait_did, assoc_name)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1652,17 +1652,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
|
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
|
||||||
let bound_vars = if let Some(type_def_id) = type_def_id
|
let bound_vars = if let Some(type_def_id) = type_def_id
|
||||||
&& self.tcx.def_kind(type_def_id) == DefKind::Trait
|
&& self.tcx.def_kind(type_def_id) == DefKind::Trait
|
||||||
// FIXME(return_type_notation): We could bound supertrait methods.
|
&& let Some((mut bound_vars, assoc_fn)) =
|
||||||
&& let Some(assoc_fn) = self
|
BoundVarContext::supertrait_hrtb_vars(
|
||||||
.tcx
|
self.tcx,
|
||||||
.associated_items(type_def_id)
|
type_def_id,
|
||||||
.find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
|
binding.ident,
|
||||||
|
ty::AssocKind::Fn,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
self.tcx
|
bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).params.iter().map(
|
||||||
.generics_of(assoc_fn.def_id)
|
|param| match param.kind {
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.map(|param| match param.kind {
|
|
||||||
ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
|
ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
|
||||||
ty::BoundRegionKind::BrNamed(param.def_id, param.name),
|
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::BoundTyKind::Param(param.def_id, param.name),
|
||||||
),
|
),
|
||||||
ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
|
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 {
|
} else {
|
||||||
self.tcx.sess.delay_span_bug(
|
self.tcx.sess.delay_span_bug(
|
||||||
binding.ident.span,
|
binding.ident.span,
|
||||||
|
@ -1689,8 +1690,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if let Some(type_def_id) = type_def_id {
|
} else if let Some(type_def_id) = type_def_id {
|
||||||
let bound_vars =
|
let bound_vars = BoundVarContext::supertrait_hrtb_vars(
|
||||||
BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
|
self.tcx,
|
||||||
|
type_def_id,
|
||||||
|
binding.ident,
|
||||||
|
ty::AssocKind::Type,
|
||||||
|
)
|
||||||
|
.map(|(bound_vars, _)| bound_vars);
|
||||||
self.with(scope, |this| {
|
self.with(scope, |this| {
|
||||||
let scope = Scope::Supertrait {
|
let scope = Scope::Supertrait {
|
||||||
bound_vars: bound_vars.unwrap_or_default(),
|
bound_vars: bound_vars.unwrap_or_default(),
|
||||||
|
@ -1720,11 +1726,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
assoc_name: Ident,
|
assoc_name: Ident,
|
||||||
) -> Option<Vec<ty::BoundVariableKind>> {
|
assoc_kind: ty::AssocKind,
|
||||||
let trait_defines_associated_type_named = |trait_def_id: DefId| {
|
) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
|
||||||
tcx.associated_items(trait_def_id)
|
let trait_defines_associated_item_named = |trait_def_id: DefId| {
|
||||||
.find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
|
tcx.associated_items(trait_def_id).find_by_name_and_kind(
|
||||||
.is_some()
|
tcx,
|
||||||
|
assoc_name,
|
||||||
|
assoc_kind,
|
||||||
|
trait_def_id,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
@ -1742,10 +1752,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
_ => break None,
|
_ => break None,
|
||||||
}
|
}
|
||||||
|
|
||||||
if trait_defines_associated_type_named(def_id) {
|
if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
|
||||||
break Some(bound_vars.into_iter().collect());
|
break Some((bound_vars.into_iter().collect(), assoc_item));
|
||||||
}
|
}
|
||||||
let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
|
let predicates = tcx.super_predicates_that_define_assoc_item((def_id, assoc_name));
|
||||||
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
|
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
|
||||||
let bound_predicate = pred.kind();
|
let bound_predicate = pred.kind();
|
||||||
match bound_predicate.skip_binder() {
|
match bound_predicate.skip_binder() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustc_errors::{
|
||||||
MultiSpan,
|
MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -512,10 +512,22 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
|
||||||
pub(crate) struct ReturnTypeNotationMissingMethod {
|
pub(crate) struct ReturnTypeNotationMissingMethod {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub trait_name: Symbol,
|
pub ty_name: String,
|
||||||
pub assoc_name: Symbol,
|
pub assoc_name: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(hir_analysis_return_type_notation_conflicting_bound)]
|
||||||
|
#[note]
|
||||||
|
pub(crate) struct ReturnTypeNotationConflictingBound<'tcx> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub ty_name: String,
|
||||||
|
pub assoc_name: Symbol,
|
||||||
|
pub first_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
pub second_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
|
#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
|
||||||
pub(crate) struct PlaceholderNotAllowedItemSignatures {
|
pub(crate) struct PlaceholderNotAllowedItemSignatures {
|
||||||
|
|
|
@ -380,11 +380,11 @@ pub fn transitive_bounds<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A specialized variant of `elaborate` that only elaborates trait references that may
|
/// A specialized variant of `elaborate` that only elaborates trait references that may
|
||||||
/// define the given associated type `assoc_name`. It uses the
|
/// define the given associated item with the name `assoc_name`. It uses the
|
||||||
/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
|
/// `super_predicates_that_define_assoc_item` query to avoid enumerating super-predicates that
|
||||||
/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
|
/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
|
||||||
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
|
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
|
||||||
pub fn transitive_bounds_that_define_assoc_type<'tcx>(
|
pub fn transitive_bounds_that_define_assoc_item<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||||
assoc_name: Ident,
|
assoc_name: Ident,
|
||||||
|
@ -397,7 +397,7 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
|
||||||
let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref);
|
let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref);
|
||||||
if visited.insert(anon_trait_ref) {
|
if visited.insert(anon_trait_ref) {
|
||||||
let super_predicates =
|
let super_predicates =
|
||||||
tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), assoc_name));
|
tcx.super_predicates_that_define_assoc_item((trait_ref.def_id(), assoc_name));
|
||||||
for (super_predicate, _) in super_predicates.predicates {
|
for (super_predicate, _) in super_predicates.predicates {
|
||||||
let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
|
let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
|
||||||
if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
|
if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
|
||||||
|
|
|
@ -569,7 +569,7 @@ rustc_queries! {
|
||||||
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
|
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
|
||||||
/// subset of super-predicates that reference traits that define the given associated type.
|
/// subset of super-predicates that reference traits that define the given associated type.
|
||||||
/// This is used to avoid cycles in resolving types like `T::Item`.
|
/// This is used to avoid cycles in resolving types like `T::Item`.
|
||||||
query super_predicates_that_define_assoc_type(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
|
query super_predicates_that_define_assoc_item(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
|
||||||
desc { |tcx| "computing the super traits of `{}` with associated type name `{}`",
|
desc { |tcx| "computing the super traits of `{}` with associated type name `{}`",
|
||||||
tcx.def_path_str(key.0),
|
tcx.def_path_str(key.0),
|
||||||
key.1
|
key.1
|
||||||
|
|
|
@ -1567,11 +1567,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
|
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
|
||||||
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
|
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
|
||||||
pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
||||||
self.super_traits_of(trait_def_id).any(|trait_did| {
|
self.super_traits_of(trait_def_id).any(|trait_did| {
|
||||||
self.associated_items(trait_did)
|
self.associated_items(trait_did)
|
||||||
.find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
|
.filter_by_name_unhygienic(assoc_name.name)
|
||||||
.is_some()
|
.any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2633,6 +2633,12 @@ macro_rules! define_print_and_forward_display {
|
||||||
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
||||||
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
|
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
|
||||||
|
|
||||||
|
impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintOnlyTraitPath<'tcx> {
|
||||||
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||||
|
self.to_string().into_diagnostic_arg()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
|
impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt::Display::fmt(self, f)
|
fmt::Display::fmt(self, f)
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub use self::util::elaborate;
|
||||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||||
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
||||||
pub use self::util::{
|
pub use self::util::{
|
||||||
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
|
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
|
||||||
SupertraitDefIds,
|
SupertraitDefIds,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,6 @@ trait Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar<T: Trait<methid(): Send>>() {}
|
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() {}
|
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: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= 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
|
--> $DIR/missing.rs:10:17
|
||||||
|
|
|
|
||||||
LL | fn bar<T: Trait<methid(): Send>>() {}
|
LL | fn bar<T: Trait<methid(): Send>>() {}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
#![feature(async_fn_in_trait, return_type_notation)]
|
||||||
|
//~^ WARN the feature `return_type_notation` is incomplete
|
||||||
|
|
||||||
|
trait Super1<'a> {
|
||||||
|
async fn test();
|
||||||
|
}
|
||||||
|
impl Super1<'_> for () {
|
||||||
|
async fn test() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Super2 {
|
||||||
|
async fn test();
|
||||||
|
}
|
||||||
|
impl Super2 for () {
|
||||||
|
async fn test() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Foo: for<'a> Super1<'a> + Super2 {}
|
||||||
|
impl Foo for () {}
|
||||||
|
|
||||||
|
fn test<T>()
|
||||||
|
where
|
||||||
|
T: Foo<test(): Send>,
|
||||||
|
//~^ ERROR ambiguous associated function `test` for `Foo`
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test::<()>();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/super-method-bound-ambig.rs:3: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
|
||||||
|
|
||||||
|
error: ambiguous associated function `test` for `Foo`
|
||||||
|
--> $DIR/super-method-bound-ambig.rs:25:12
|
||||||
|
|
|
||||||
|
LL | T: Foo<test(): Send>,
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `test` is declared in two supertraits: `Super2` and `Super1<'a>`
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue