Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0719.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.

An associated type value was specified more than once.

Erroneous code example:

```compile_fail,E0719
```
trait FooTrait {}
trait BarTrait {}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ E0716: 0716,
E0711: 0711,
E0717: 0717,
E0718: 0718,
E0719: 0719,
E0719: 0719, // REMOVED: no longer an error
E0720: 0720,
E0722: 0722,
E0724: 0724,
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,6 @@ hir_analysis_unused_generic_parameter_ty_alias_help =

hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type

hir_analysis_value_of_associated_struct_already_specified =
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
.label = re-bound here
.previous_bound_label = `{$item_name}` bound here first

hir_analysis_variadic_function_compatible_convention = C-variadic functions with the {$convention} calling convention are not supported
.label = C-variadic function must have a compatible calling convention

Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,18 +388,6 @@ pub(crate) struct TypeofReservedKeywordUsed<'tcx> {
pub opt_sugg: Option<(Span, Applicability)>,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)]
pub(crate) struct ValueOfAssociatedStructAlreadySpecified {
#[primary_span]
#[label]
pub span: Span,
#[label(hir_analysis_previous_bound_label)]
pub prev_span: Span,
pub item_name: Ident,
pub def_path: String,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_unconstrained_opaque_type)]
#[note]
Expand Down
17 changes: 2 additions & 15 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::ControlFlow;

use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
Expand Down Expand Up @@ -509,14 +509,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// the `trait_ref` here will be `for<'a> T: Iterator`.
/// The `constraint` data however is from *inside* the binder
/// (e.g., `&'a u32`) and hence may reference bound regions.
#[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
#[instrument(level = "debug", skip(self, bounds, path_span))]
pub(super) fn lower_assoc_item_constraint(
&self,
hir_ref_id: hir::HirId,
trait_ref: ty::PolyTraitRef<'tcx>,
constraint: &hir::AssocItemConstraint<'tcx>,
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
duplicates: &mut FxIndexMap<DefId, Span>,
path_span: Span,
predicate_filter: PredicateFilter,
) -> Result<(), ErrorGuaranteed> {
Expand Down Expand Up @@ -572,18 +571,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
)
.expect("failed to find associated item");

duplicates
.entry(assoc_item.def_id)
.and_modify(|prev_span| {
self.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
span: constraint.span,
prev_span: *prev_span,
item_name: constraint.ident,
def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
});
})
.or_insert(constraint.span);

let projection_term = if let ty::AssocTag::Fn = assoc_tag {
let bound_vars = tcx.late_bound_vars(constraint.hir_id);
ty::Binder::bind_with_vars(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self.dcx()
.struct_span_err(
span,
format!(
"conflicting associated type bounds for `{item}` when \
expanding trait alias"
),
format!("conflicting associated type bounds for `{item}`"),
)
.with_span_label(
old_proj_span,
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::assert_matches::assert_matches;
use std::slice;

use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
Expand Down Expand Up @@ -910,7 +910,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

let mut dup_constraints = FxIndexMap::default();
for constraint in trait_segment.args().constraints {
// Don't register any associated item constraints for negative bounds,
// since we should have emitted an error for them earlier, and they
Expand All @@ -929,7 +928,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
poly_trait_ref,
constraint,
bounds,
&mut dup_constraints,
constraint.span,
predicate_filter,
);
Expand Down
249 changes: 249 additions & 0 deletions tests/ui/associated-item/duplicate_bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
//@ edition: 2024
//@ run-pass

#![feature(associated_const_equality, return_type_notation)]
#![allow(dead_code, refining_impl_trait_internal, type_alias_bounds)]

use std::any::TypeId;
use std::iter;
use std::mem::ManuallyDrop;

struct SI1<T: Iterator<Item: Copy, Item: Send>> {
f: T,
}
struct SI2<T: Iterator<Item: Copy, Item: Copy>> {
f: T,
}
struct SI3<T: Iterator<Item: 'static, Item: 'static>> {
f: T,
}
struct SW1<T>
where
T: Iterator<Item: Copy, Item: Send>,
{
f: T,
}
struct SW2<T>
where
T: Iterator<Item: Copy, Item: Copy>,
{
f: T,
}
struct SW3<T>
where
T: Iterator<Item: 'static, Item: 'static>,
{
f: T,
}

enum EI1<T: Iterator<Item: Copy, Item: Send>> {
V(T),
}
enum EI2<T: Iterator<Item: Copy, Item: Copy>> {
V(T),
}
enum EI3<T: Iterator<Item: 'static, Item: 'static>> {
V(T),
}
enum EW1<T>
where
T: Iterator<Item: Copy, Item: Send>,
{
V(T),
}
enum EW2<T>
where
T: Iterator<Item: Copy, Item: Copy>,
{
V(T),
}
enum EW3<T>
where
T: Iterator<Item: 'static, Item: 'static>,
{
V(T),
}

union UI1<T: Iterator<Item: Copy, Item: Send>> {
f: ManuallyDrop<T>,
}
union UI2<T: Iterator<Item: Copy, Item: Copy>> {
f: ManuallyDrop<T>,
}
union UI3<T: Iterator<Item: 'static, Item: 'static>> {
f: ManuallyDrop<T>,
}
union UW1<T>
where
T: Iterator<Item: Copy, Item: Send>,
{
f: ManuallyDrop<T>,
}
union UW2<T>
where
T: Iterator<Item: Copy, Item: Copy>,
{
f: ManuallyDrop<T>,
}
union UW3<T>
where
T: Iterator<Item: 'static, Item: 'static>,
{
f: ManuallyDrop<T>,
}

fn fi1<T: Iterator<Item: Copy, Item: Send>>() {}
fn fi2<T: Iterator<Item: Copy, Item: Copy>>() {}
fn fi3<T: Iterator<Item: 'static, Item: 'static>>() {}
fn fw1<T>()
where
T: Iterator<Item: Copy, Item: Send>,
{
}
fn fw2<T>()
where
T: Iterator<Item: Copy, Item: Copy>,
{
}
fn fw3<T>()
where
T: Iterator<Item: 'static, Item: 'static>,
{
}

fn frpit1() -> impl Iterator<Item: Copy, Item: Send> {
iter::empty::<u32>()
}
fn frpit2() -> impl Iterator<Item: Copy, Item: Copy> {
iter::empty::<u32>()
}
fn frpit3() -> impl Iterator<Item: 'static, Item: 'static> {
iter::empty::<u32>()
}
fn fapit1(_: impl Iterator<Item: Copy, Item: Send>) {}
fn fapit2(_: impl Iterator<Item: Copy, Item: Copy>) {}
fn fapit3(_: impl Iterator<Item: 'static, Item: 'static>) {}

type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
type TAW1<T>
where
T: Iterator<Item: Copy, Item: Send>,
= T;
type TAW2<T>
where
T: Iterator<Item: Copy, Item: Copy>,
= T;
type TAW3<T>
where
T: Iterator<Item: 'static, Item: 'static>,
= T;

trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
trait TRS1: Iterator<Item: Copy, Item: Send> {}
trait TRS2: Iterator<Item: Copy, Item: Copy> {}
trait TRS3: Iterator<Item: 'static, Item: 'static> {}
trait TRW1<T>
where
T: Iterator<Item: Copy, Item: Send>,
{
}
trait TRW2<T>
where
T: Iterator<Item: Copy, Item: Copy>,
{
}
trait TRW3<T>
where
T: Iterator<Item: 'static, Item: 'static>,
{
}
trait TRSW1
where
Self: Iterator<Item: Copy, Item: Send>,
{
}
trait TRSW2
where
Self: Iterator<Item: Copy, Item: Copy>,
{
}
trait TRSW3
where
Self: Iterator<Item: 'static, Item: 'static>,
{
}
trait TRA1 {
type A: Iterator<Item: Copy, Item: Send>;
}
trait TRA2 {
type A: Iterator<Item: Copy, Item: Copy>;
}
trait TRA3 {
type A: Iterator<Item: 'static, Item: 'static>;
}

trait Trait {
type Gat<T>;

const ASSOC: i32;

fn foo() -> impl Sized;
}

impl Trait for () {
type Gat<T> = ();

const ASSOC: i32 = 3;

fn foo() {}
}

trait Subtrait: Trait<Gat<u32> = u32, Gat<u64> = u64> {}

fn f<T: Trait<Gat<i32> = (), Gat<i64> = ()>>() {
let _: T::Gat<i32> = ();
let _: T::Gat<i64> = ();
}

fn g<T: Trait<Gat<i32> = (), Gat<i64> = &'static str>>() {
let _: T::Gat<i32> = ();
let _: T::Gat<i64> = "";
}

fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}

fn callable(_: impl Iterator<Item = i32, Item = i32>) {}

fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}

fn callable_const(_: impl Trait<ASSOC = 3, ASSOC = 3>) {}

fn uncallable_rtn(_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>) {}

fn callable_rtn(_: impl Trait<foo(..): Send, foo(..): Send, foo(..): Eq>) {}

type Works = dyn Iterator<Item = i32, Item = i32>;

trait Trait2 {
const ASSOC: u32;
}

type AlsoWorks = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;

trait Trait3 {
fn foo() -> impl Iterator<Item = i32, Item = u32>;
}

fn main() {
callable(iter::empty::<i32>());
callable_const(());
callable_rtn(());
assert_eq!(
TypeId::of::<dyn Iterator<Item = u32>>(),
TypeId::of::<dyn Iterator<Item = u32, Item = u32>>()
);
}
Loading
Loading