Skip to content

Commit 389907a

Browse files
Enforce E0719 only for trait aliases
1 parent 97a987f commit 389907a

File tree

13 files changed

+650
-1094
lines changed

13 files changed

+650
-1094
lines changed

compiler/rustc_error_codes/src/error_codes/E0719.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
An associated type value was specified more than once.
1+
An associated item value was specified more than once in a trait object.
22

33
Erroneous code example:
44

@@ -7,21 +7,15 @@ trait FooTrait {}
77
trait BarTrait {}
88
99
// error: associated type `Item` in trait `Iterator` is specified twice
10-
struct Foo<T: Iterator<Item: FooTrait, Item: BarTrait>> { f: T }
10+
type Foo = dyn Iterator<Item = u32, Item = u32>;
1111
```
1212

13-
`Item` in trait `Iterator` cannot be specified multiple times for struct `Foo`.
14-
To fix this, create a new trait that is a combination of the desired traits and
15-
specify the associated type with the new trait.
13+
To fix this, remove the duplicate specifier:
1614

1715
Corrected example:
1816

1917
```
20-
trait FooTrait {}
21-
trait BarTrait {}
22-
trait FooBarTrait: FooTrait + BarTrait {}
23-
24-
struct Foo<T: Iterator<Item: FooBarTrait>> { f: T } // ok!
18+
type Foo = dyn Iterator<Item = u32>; // ok!
2519
```
2620

2721
For more information about associated types, see [the book][bk-at]. For more

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
362362
param_ty,
363363
bounds,
364364
predicate_filter,
365+
false,
365366
);
366367
}
367368
hir::GenericBound::Outlives(lifetime) => {
@@ -402,7 +403,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
402403
trait_ref: ty::PolyTraitRef<'tcx>,
403404
constraint: &hir::AssocItemConstraint<'tcx>,
404405
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
405-
duplicates: &mut FxIndexMap<DefId, Span>,
406+
duplicates: Option<&mut FxIndexMap<DefId, Span>>,
406407
path_span: Span,
407408
predicate_filter: PredicateFilter,
408409
) -> Result<(), ErrorGuaranteed> {
@@ -458,17 +459,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
458459
)
459460
.expect("failed to find associated item");
460461

461-
duplicates
462-
.entry(assoc_item.def_id)
463-
.and_modify(|prev_span| {
464-
self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
465-
span: constraint.span,
466-
prev_span: *prev_span,
467-
item_name: constraint.ident,
468-
def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
469-
});
470-
})
471-
.or_insert(constraint.span);
462+
if let Some(duplicates) = duplicates {
463+
duplicates
464+
.entry(assoc_item.def_id)
465+
.and_modify(|prev_span| {
466+
self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
467+
span: constraint.span,
468+
prev_span: *prev_span,
469+
item_name: constraint.ident,
470+
def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
471+
});
472+
})
473+
.or_insert(constraint.span);
474+
}
472475

473476
let projection_term = if let ty::AssocTag::Fn = assoc_tag {
474477
let bound_vars = tcx.late_bound_vars(constraint.hir_id);

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6060
dummy_self,
6161
&mut user_written_bounds,
6262
PredicateFilter::SelfOnly,
63+
true,
6364
);
6465
if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
6566
potential_assoc_types.extend(invalid_args);
@@ -157,10 +158,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
157158
self.dcx()
158159
.struct_span_err(
159160
span,
160-
format!(
161-
"conflicting associated type bounds for `{item}` when \
162-
expanding trait alias"
163-
),
161+
format!("conflicting associated type bounds for `{item}`"),
164162
)
165163
.with_span_label(
166164
old_proj_span,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
752752
self_ty: Ty<'tcx>,
753753
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
754754
predicate_filter: PredicateFilter,
755+
for_dyn: bool,
755756
) -> GenericArgCountResult {
756757
let tcx = self.tcx();
757758

@@ -927,7 +928,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
927928
poly_trait_ref,
928929
constraint,
929930
bounds,
930-
&mut dup_constraints,
931+
for_dyn.then_some(&mut dup_constraints),
931932
constraint.span,
932933
predicate_filter,
933934
);
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//@ edition: 2024
2+
3+
#![feature(associated_const_equality, type_alias_impl_trait, return_type_notation)]
4+
#![allow(refining_impl_trait_internal)]
5+
6+
use std::iter;
7+
8+
fn frpit1() -> impl Iterator<Item: Copy, Item: Send> {
9+
iter::empty()
10+
//~^ ERROR type annotations needed
11+
}
12+
fn frpit2() -> impl Iterator<Item: Copy, Item: Copy> {
13+
iter::empty()
14+
//~^ ERROR type annotations needed
15+
}
16+
fn frpit3() -> impl Iterator<Item: 'static, Item: 'static> {
17+
iter::empty()
18+
//~^ ERROR type annotations needed
19+
}
20+
21+
type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
22+
//~^ ERROR unconstrained opaque type
23+
type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
24+
//~^ ERROR unconstrained opaque type
25+
type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
26+
//~^ ERROR unconstrained opaque type
27+
28+
type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
29+
//~^ ERROR unconstrained opaque type
30+
type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
31+
//~^ ERROR unconstrained opaque type
32+
type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
33+
//~^ ERROR unconstrained opaque type
34+
35+
fn mismatch() -> impl Iterator<Item: Copy, Item: Send> {
36+
//~^ ERROR [E0277]
37+
iter::empty::<*const ()>()
38+
}
39+
40+
fn mismatch_2() -> impl Iterator<Item: Copy, Item: Send> {
41+
//~^ ERROR [E0277]
42+
iter::empty::<String>()
43+
}
44+
45+
trait Trait {
46+
type Gat<T>;
47+
48+
const ASSOC: i32;
49+
50+
fn foo() -> impl Sized;
51+
}
52+
53+
impl Trait for () {
54+
type Gat<T> = ();
55+
56+
const ASSOC: i32 = 3;
57+
58+
fn foo() {}
59+
}
60+
61+
impl Trait for u32 {
62+
type Gat<T> = ();
63+
64+
const ASSOC: i32 = 4;
65+
66+
fn foo() -> u32 {
67+
42
68+
}
69+
}
70+
71+
fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
72+
73+
fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
74+
75+
fn uncallable_rtn(_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>) {}
76+
77+
type MustFail = dyn Iterator<Item = i32, Item = u32>;
78+
//~^ ERROR [E0719]
79+
//~| ERROR conflicting associated type bounds
80+
81+
trait Trait2 {
82+
const ASSOC: u32;
83+
}
84+
85+
type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
86+
//~^ ERROR [E0719]
87+
//~| ERROR conflicting associated type bounds
88+
89+
type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
90+
//~^ ERROR [E0719]
91+
92+
type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
93+
//~^ ERROR [E0719]
94+
95+
trait Trait3 {
96+
fn foo() -> impl Iterator<Item = i32, Item = u32>;
97+
}
98+
99+
impl Trait3 for () {
100+
fn foo() -> impl Iterator<Item = i32, Item = u32> {
101+
//~^ ERROR[E0271]
102+
//~| ERROR[E0271]
103+
[2u32].into_iter()
104+
}
105+
}
106+
107+
fn main() {
108+
uncallable(iter::empty::<u32>()); //~ ERROR [E0271]
109+
uncallable(iter::empty::<i32>()); //~ ERROR [E0271]
110+
uncallable_const(()); //~ ERROR [E0271]
111+
uncallable_const(4u32); //~ ERROR [E0271]
112+
uncallable_rtn(()); //~ ERROR [E0271]
113+
uncallable_rtn(17u32); //~ ERROR [E0271]
114+
}

0 commit comments

Comments
 (0)