mirror of
https://github.com/rust-lang/rust.git
synced 2025-10-02 10:18:25 +00:00
Auto merge of #143783 - bvanjoi:issue-143697-2, r=compiler-errors
compute all rpitit of a trait Fixes rust-lang/rust#143697 r? `@compiler-errors`
This commit is contained in:
commit
288e94c4ba
@ -326,7 +326,9 @@ pub(crate) fn check_trait_item<'tcx>(
|
||||
let mut res = Ok(());
|
||||
|
||||
if matches!(tcx.def_kind(def_id), DefKind::AssocFn) {
|
||||
for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
|
||||
for &assoc_ty_def_id in
|
||||
tcx.associated_types_for_impl_traits_in_associated_fn(def_id.to_def_id())
|
||||
{
|
||||
res = res.and(check_associated_item(tcx, assoc_ty_def_id.expect_local()));
|
||||
}
|
||||
}
|
||||
|
@ -2602,7 +2602,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
// do a linear search to map this to the synthetic associated type that
|
||||
// it will be lowered to.
|
||||
let def_id = if let Some(parent_def_id) = in_trait {
|
||||
*tcx.associated_types_for_impl_traits_in_associated_fn(parent_def_id)
|
||||
*tcx.associated_types_for_impl_traits_in_associated_fn(parent_def_id.to_def_id())
|
||||
.iter()
|
||||
.find(|rpitit| match tcx.opt_rpitit_info(**rpitit) {
|
||||
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
|
||||
|
@ -326,7 +326,7 @@ provide! { tcx, def_id, other, cdata,
|
||||
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
|
||||
}
|
||||
|
||||
associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
|
||||
associated_types_for_impl_traits_in_trait_or_impl => { table }
|
||||
|
||||
visibility => { cdata.get_visibility(def_id.index) }
|
||||
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
|
||||
|
@ -1382,17 +1382,6 @@ fn should_encode_const(def_kind: DefKind) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
|
||||
if let Some(assoc_item) = tcx.opt_associated_item(def_id)
|
||||
&& assoc_item.container == ty::AssocItemContainer::Trait
|
||||
&& assoc_item.is_fn()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
fn encode_attrs(&mut self, def_id: LocalDefId) {
|
||||
let tcx = self.tcx;
|
||||
@ -1617,9 +1606,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
{
|
||||
record!(self.tables.trait_impl_trait_tys[def_id] <- table);
|
||||
}
|
||||
if should_encode_fn_impl_trait_in_trait(tcx, def_id) {
|
||||
let table = tcx.associated_types_for_impl_traits_in_associated_fn(def_id);
|
||||
record_defaulted_array!(self.tables.associated_types_for_impl_traits_in_associated_fn[def_id] <- table);
|
||||
if let DefKind::Impl { .. } | DefKind::Trait = def_kind {
|
||||
let table = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id);
|
||||
record!(self.tables.associated_types_for_impl_traits_in_trait_or_impl[def_id] <- table);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,7 +403,6 @@ define_tables! {
|
||||
explicit_implied_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
|
||||
explicit_implied_const_bounds: Table<DefIndex, LazyArray<(ty::PolyTraitRef<'static>, Span)>>,
|
||||
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
||||
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
|
||||
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
|
||||
// Reexported names are not associated with individual `DefId`s,
|
||||
// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
|
||||
@ -482,6 +481,7 @@ define_tables! {
|
||||
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
|
||||
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
|
||||
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
|
||||
associated_types_for_impl_traits_in_trait_or_impl: Table<DefIndex, LazyValue<DefIdMap<Vec<DefId>>>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
|
@ -1079,15 +1079,11 @@ rustc_queries! {
|
||||
desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
|
||||
}
|
||||
|
||||
/// Given `fn_def_id` of a trait or of an impl that implements a given trait:
|
||||
/// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
|
||||
/// the associated items that correspond to each impl trait in return position for that trait.
|
||||
/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
|
||||
/// creates and returns the associated items that correspond to each impl trait in return position
|
||||
/// of the implemented trait.
|
||||
query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] {
|
||||
desc { |tcx| "creating associated items for opaque types returned by `{}`", tcx.def_path_str(fn_def_id) }
|
||||
cache_on_disk_if { fn_def_id.is_local() }
|
||||
/// Given the `item_def_id` of a trait or impl, return a mapping from associated fn def id
|
||||
/// to its associated type items that correspond to the RPITITs in its signature.
|
||||
query associated_types_for_impl_traits_in_trait_or_impl(item_def_id: DefId) -> &'tcx DefIdMap<Vec<DefId>> {
|
||||
arena_cache
|
||||
desc { |tcx| "synthesizing RPITIT items for the opaque types for methods in `{}`", tcx.def_path_str(item_def_id) }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
|
@ -285,3 +285,22 @@ impl AssocItems {
|
||||
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Given an `fn_def_id` of a trait or a trait implementation:
|
||||
///
|
||||
/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
|
||||
/// a new def id corresponding to a new associated type for each return-
|
||||
/// position `impl Trait` in the signature.
|
||||
///
|
||||
/// if `fn_def_id` is a function inside of an impl, then for each synthetic
|
||||
/// associated type generated for the corresponding trait function described
|
||||
/// above, synthesize a corresponding associated type in the impl.
|
||||
pub fn associated_types_for_impl_traits_in_associated_fn(
|
||||
self,
|
||||
fn_def_id: DefId,
|
||||
) -> &'tcx [DefId] {
|
||||
let parent_def_id = self.parent(fn_def_id);
|
||||
&self.associated_types_for_impl_traits_in_trait_or_impl(parent_def_id)[&fn_def_id]
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,10 @@ impl<A: ParameterizedOverTcx, B: ParameterizedOverTcx> ParameterizedOverTcx for
|
||||
type Value<'tcx> = (A::Value<'tcx>, B::Value<'tcx>);
|
||||
}
|
||||
|
||||
impl<T: ParameterizedOverTcx> ParameterizedOverTcx for Vec<T> {
|
||||
type Value<'tcx> = Vec<T::Value<'tcx>>;
|
||||
}
|
||||
|
||||
impl<I: Idx + 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for IndexVec<I, T> {
|
||||
type Value<'tcx> = IndexVec<I, T::Value<'tcx>>;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{self as hir, ItemKind};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
@ -12,7 +12,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
associated_item,
|
||||
associated_item_def_ids,
|
||||
associated_items,
|
||||
associated_types_for_impl_traits_in_associated_fn,
|
||||
associated_types_for_impl_traits_in_trait_or_impl,
|
||||
impl_item_implementor_ids,
|
||||
..*providers
|
||||
};
|
||||
@ -22,54 +22,28 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
|
||||
let item = tcx.hir_expect_item(def_id);
|
||||
match item.kind {
|
||||
hir::ItemKind::Trait(.., trait_item_refs) => {
|
||||
// We collect RPITITs for each trait method's return type and create a
|
||||
// corresponding associated item using associated_types_for_impl_traits_in_associated_fn
|
||||
// We collect RPITITs for each trait method's return type and create a corresponding
|
||||
// associated item using the associated_types_for_impl_traits_in_trait_or_impl
|
||||
// query.
|
||||
tcx.arena.alloc_from_iter(
|
||||
trait_item_refs
|
||||
.iter()
|
||||
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
|
||||
.chain(
|
||||
trait_item_refs
|
||||
.iter()
|
||||
.filter(|trait_item_ref| {
|
||||
matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
|
||||
})
|
||||
.flat_map(|trait_item_ref| {
|
||||
let trait_fn_def_id = trait_item_ref.id.owner_id.def_id.to_def_id();
|
||||
tcx.associated_types_for_impl_traits_in_associated_fn(
|
||||
trait_fn_def_id,
|
||||
)
|
||||
})
|
||||
.copied(),
|
||||
),
|
||||
)
|
||||
let rpitit_items = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id);
|
||||
tcx.arena.alloc_from_iter(trait_item_refs.iter().flat_map(|trait_item_ref| {
|
||||
let item_def_id = trait_item_ref.id.owner_id.to_def_id();
|
||||
[item_def_id]
|
||||
.into_iter()
|
||||
.chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied())
|
||||
}))
|
||||
}
|
||||
hir::ItemKind::Impl(impl_) => {
|
||||
// We collect RPITITs for each trait method's return type, on the impl side too and
|
||||
// create a corresponding associated item using
|
||||
// associated_types_for_impl_traits_in_associated_fn query.
|
||||
tcx.arena.alloc_from_iter(
|
||||
impl_
|
||||
.items
|
||||
.iter()
|
||||
.map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
|
||||
.chain(impl_.of_trait.iter().flat_map(|_| {
|
||||
impl_
|
||||
.items
|
||||
.iter()
|
||||
.filter(|impl_item_ref| {
|
||||
matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
|
||||
})
|
||||
.flat_map(|impl_item_ref| {
|
||||
let impl_fn_def_id = impl_item_ref.id.owner_id.def_id.to_def_id();
|
||||
tcx.associated_types_for_impl_traits_in_associated_fn(
|
||||
impl_fn_def_id,
|
||||
)
|
||||
})
|
||||
.copied()
|
||||
})),
|
||||
)
|
||||
// associated_types_for_impl_traits_in_trait_or_impl query.
|
||||
let rpitit_items = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id);
|
||||
tcx.arena.alloc_from_iter(impl_.items.iter().flat_map(|impl_item_ref| {
|
||||
let item_def_id = impl_item_ref.id.owner_id.to_def_id();
|
||||
[item_def_id]
|
||||
.into_iter()
|
||||
.chain(rpitit_items.get(&item_def_id).into_iter().flatten().copied())
|
||||
}))
|
||||
}
|
||||
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
|
||||
}
|
||||
@ -158,15 +132,17 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
|
||||
container: ty::AssocItemContainer::Impl,
|
||||
}
|
||||
}
|
||||
struct RPITVisitor<'tcx> {
|
||||
struct RPITVisitor<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
synthetics: Vec<LocalDefId>,
|
||||
data: DefPathData,
|
||||
disambiguator: DisambiguatorState,
|
||||
disambiguator: &'a mut DisambiguatorState,
|
||||
depth: u32,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
|
||||
impl<'tcx> Visitor<'tcx> for RPITVisitor<'_, 'tcx> {
|
||||
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result {
|
||||
self.depth += 1;
|
||||
self.synthetics.push(associated_type_for_impl_trait_in_trait(
|
||||
self.tcx,
|
||||
opaque.def_id,
|
||||
@ -177,100 +153,75 @@ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
struct DisambiguatorIdxVisitor {
|
||||
depth: u32,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for DisambiguatorIdxVisitor {
|
||||
fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result {
|
||||
self.depth += 1;
|
||||
intravisit::walk_opaque_ty(self, opaque)
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an `fn_def_id` of a trait or a trait implementation:
|
||||
///
|
||||
/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
|
||||
/// a new def id corresponding to a new associated type for each return-
|
||||
/// position `impl Trait` in the signature.
|
||||
///
|
||||
/// if `fn_def_id` is a function inside of an impl, then for each synthetic
|
||||
/// associated type generated for the corresponding trait function described
|
||||
/// above, synthesize a corresponding associated type in the impl.
|
||||
fn associated_types_for_impl_traits_in_associated_fn(
|
||||
tcx: TyCtxt<'_>,
|
||||
fn_def_id: LocalDefId,
|
||||
) -> &'_ [DefId] {
|
||||
let parent_def_id = tcx.local_parent(fn_def_id);
|
||||
|
||||
match tcx.def_kind(parent_def_id) {
|
||||
DefKind::Trait => {
|
||||
if let Some(output) = tcx.hir_get_fn_output(fn_def_id) {
|
||||
let def_path_id = |def_id: LocalDefId| tcx.item_name(def_id.to_def_id());
|
||||
let def_path_data = def_path_id(fn_def_id);
|
||||
|
||||
let (.., trait_item_refs) = tcx.hir_expect_item(parent_def_id).expect_trait();
|
||||
// The purpose of `disambiguator_idx` is to ensure there are
|
||||
// no duplicate `def_id` in certain cases, such as:
|
||||
// ```
|
||||
// trait Foo {
|
||||
// fn bar() -> impl Trait;
|
||||
// fn bar() -> impl Trait;
|
||||
// // ~~~~~~~~~~ It will generate the same ID if we don’t disambiguate it.
|
||||
// }
|
||||
// ```
|
||||
let disambiguator_idx = trait_item_refs
|
||||
.iter()
|
||||
.take_while(|item| item.id.owner_id.def_id != fn_def_id)
|
||||
.filter(|item| {
|
||||
matches!(item.kind, hir::AssocItemKind::Fn { .. })
|
||||
&& def_path_id(item.id.owner_id.def_id) == def_path_data
|
||||
})
|
||||
.last()
|
||||
.map(|item| {
|
||||
let output = tcx.hir_get_fn_output(item.id.owner_id.def_id).unwrap();
|
||||
let mut visitor = DisambiguatorIdxVisitor { depth: 0 };
|
||||
visitor.visit_fn_ret_ty(output);
|
||||
tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator
|
||||
+ visitor.depth
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let data = DefPathData::AnonAssocTy(def_path_data);
|
||||
let mut visitor = RPITVisitor {
|
||||
tcx,
|
||||
synthetics: vec![],
|
||||
data,
|
||||
disambiguator: DisambiguatorState::with(parent_def_id, data, disambiguator_idx),
|
||||
fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> DefIdMap<Vec<DefId>> {
|
||||
let item = tcx.hir_expect_item(def_id);
|
||||
let disambiguator = &mut DisambiguatorState::new();
|
||||
match item.kind {
|
||||
ItemKind::Trait(.., trait_item_refs) => trait_item_refs
|
||||
.iter()
|
||||
.filter_map(move |item| {
|
||||
if !matches!(item.kind, hir::AssocItemKind::Fn { .. }) {
|
||||
return None;
|
||||
}
|
||||
let fn_def_id = item.id.owner_id.def_id;
|
||||
let Some(output) = tcx.hir_get_fn_output(fn_def_id) else {
|
||||
return Some((fn_def_id.to_def_id(), vec![]));
|
||||
};
|
||||
let def_name = tcx.item_name(fn_def_id.to_def_id());
|
||||
let data = DefPathData::AnonAssocTy(def_name);
|
||||
let mut visitor =
|
||||
RPITVisitor { tcx, synthetics: vec![], data, depth: 0, disambiguator };
|
||||
visitor.visit_fn_ret_ty(output);
|
||||
tcx.arena.alloc_from_iter(
|
||||
visitor.synthetics.into_iter().map(|def_id| def_id.to_def_id()),
|
||||
)
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
DefKind::Impl { .. } => {
|
||||
let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else {
|
||||
return &[];
|
||||
let defs = visitor
|
||||
.synthetics
|
||||
.into_iter()
|
||||
.map(|def_id| def_id.to_def_id())
|
||||
.collect::<Vec<_>>();
|
||||
Some((fn_def_id.to_def_id(), defs))
|
||||
})
|
||||
.collect(),
|
||||
ItemKind::Impl(impl_) => {
|
||||
let Some(trait_ref) = impl_.of_trait else {
|
||||
return Default::default();
|
||||
};
|
||||
tcx.arena.alloc_from_iter(
|
||||
tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
|
||||
move |&trait_assoc_def_id| {
|
||||
associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
|
||||
.to_def_id()
|
||||
},
|
||||
),
|
||||
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
||||
return Default::default();
|
||||
};
|
||||
let in_trait_def = tcx.associated_types_for_impl_traits_in_trait_or_impl(trait_def_id);
|
||||
impl_
|
||||
.items
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
if !matches!(item.kind, hir::AssocItemKind::Fn { .. }) {
|
||||
return None;
|
||||
}
|
||||
let did = item.id.owner_id.def_id.to_def_id();
|
||||
let Some(trait_item_def_id) = item.trait_item_def_id else {
|
||||
return Some((did, vec![]));
|
||||
};
|
||||
let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| {
|
||||
associated_type_for_impl_trait_in_impl(
|
||||
tcx,
|
||||
id,
|
||||
item.id.owner_id.def_id,
|
||||
disambiguator,
|
||||
)
|
||||
.to_def_id()
|
||||
});
|
||||
Some((did, iter.collect()))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
_ => {
|
||||
bug!(
|
||||
"associated_types_for_impl_traits_in_trait_or_impl: {:?} should be Trait or Impl but is {:?}",
|
||||
def_id,
|
||||
tcx.def_kind(def_id)
|
||||
)
|
||||
}
|
||||
|
||||
def_kind => bug!(
|
||||
"associated_types_for_impl_traits_in_associated_fn: {:?} should be Trait or Impl but is {:?}",
|
||||
parent_def_id,
|
||||
def_kind
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,6 +295,7 @@ fn associated_type_for_impl_trait_in_impl(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_assoc_def_id: DefId,
|
||||
impl_fn_def_id: LocalDefId,
|
||||
disambiguator: &mut DisambiguatorState,
|
||||
) -> LocalDefId {
|
||||
let impl_local_def_id = tcx.local_parent(impl_fn_def_id);
|
||||
|
||||
@ -366,7 +318,7 @@ fn associated_type_for_impl_trait_in_impl(
|
||||
None,
|
||||
DefKind::AssocTy,
|
||||
Some(data),
|
||||
&mut DisambiguatorState::with(impl_local_def_id, data, disambiguated_data.disambiguator),
|
||||
disambiguator,
|
||||
);
|
||||
|
||||
let local_def_id = impl_assoc_ty.def_id();
|
||||
|
@ -43,4 +43,17 @@ trait Qux {
|
||||
//~^^^^ ERROR: the name `foo` is defined multiple times
|
||||
}
|
||||
|
||||
trait T0<T> {
|
||||
type Target;
|
||||
}
|
||||
trait T1<T> {}
|
||||
|
||||
trait X {
|
||||
fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
//~^ ERROR the name `a` is defined multiple times
|
||||
fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
//~^ ERROR the name `a` is defined multiple times
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -44,6 +44,27 @@ LL | | >;
|
||||
|
|
||||
= note: `foo` must be defined only once in the value namespace of this trait
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0428]: the name `a` is defined multiple times
|
||||
--> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:53:5
|
||||
|
|
||||
LL | fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
| -------------------------------------------- previous definition of the value `a` here
|
||||
LL | fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `a` redefined here
|
||||
|
|
||||
= note: `a` must be defined only once in the value namespace of this trait
|
||||
|
||||
error[E0428]: the name `a` is defined multiple times
|
||||
--> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:55:5
|
||||
|
|
||||
LL | fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
| -------------------------------------------- previous definition of the value `a` here
|
||||
...
|
||||
LL | fn a() -> impl T0<(), Target = impl T1<()>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `a` redefined here
|
||||
|
|
||||
= note: `a` must be defined only once in the value namespace of this trait
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0428`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user