Skip to content
Merged
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
14 changes: 4 additions & 10 deletions compiler/rustc_error_codes/src/error_codes/E0719.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
An associated type value was specified more than once.
An associated item was specified more than once in a trait object.

Erroneous code example:

Expand All @@ -7,21 +7,15 @@ trait FooTrait {}
trait BarTrait {}

// error: associated type `Item` in trait `Iterator` is specified twice
struct Foo<T: Iterator<Item: FooTrait, Item: BarTrait>> { f: T }
type Foo = dyn Iterator<Item = u32, Item = u32>;
```

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

Corrected example:

```
trait FooTrait {}
trait BarTrait {}
trait FooBarTrait: FooTrait + BarTrait {}

struct Foo<T: Iterator<Item: FooBarTrait>> { f: T } // ok!
type Foo = dyn Iterator<Item = u32>; // ok!
```

For more information about associated types, see [the book][bk-at]. For more
Expand Down
20 changes: 17 additions & 3 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use tracing::{debug, instrument};

use super::ItemCtxt;
use super::predicates_of::assert_only_contains_predicates_from;
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
use crate::hir_ty_lowering::{HirTyLowerer, OverlappingAsssocItemConstraints, PredicateFilter};

/// For associated types we include both bounds written on the type
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
Expand All @@ -37,7 +37,14 @@ fn associated_type_bounds<'tcx>(

let icx = ItemCtxt::new(tcx, assoc_item_def_id);
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
icx.lowerer().lower_bounds(
item_ty,
hir_bounds,
&mut bounds,
ty::List::empty(),
filter,
OverlappingAsssocItemConstraints::Allowed,
);

match filter {
PredicateFilter::All
Expand Down Expand Up @@ -347,7 +354,14 @@ fn opaque_type_bounds<'tcx>(
ty::print::with_reduced_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
icx.lowerer().lower_bounds(
item_ty,
hir_bounds,
&mut bounds,
ty::List::empty(),
filter,
OverlappingAsssocItemConstraints::Allowed,
);
// Implicit bounds are added to opaque types unless a `?Trait` bound is found
match filter {
PredicateFilter::All
Expand Down
18 changes: 16 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use super::item_bounds::explicit_item_bounds_with_filter;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
use crate::delegation::inherit_predicates_for_delegation_item;
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason};
use crate::hir_ty_lowering::{
HirTyLowerer, OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
};

/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus
Expand Down Expand Up @@ -187,6 +189,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
&mut bounds,
ty::List::empty(),
PredicateFilter::All,
OverlappingAsssocItemConstraints::Allowed,
);
icx.lowerer().add_sizedness_bounds(
&mut bounds,
Expand Down Expand Up @@ -289,6 +292,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
&mut bounds,
bound_vars,
PredicateFilter::All,
OverlappingAsssocItemConstraints::Allowed,
);
predicates.extend(bounds);
}
Expand Down Expand Up @@ -659,7 +663,14 @@ pub(super) fn implied_predicates_with_filter<'tcx>(

let self_param_ty = tcx.types.self_param;
let mut bounds = Vec::new();
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
icx.lowerer().lower_bounds(
self_param_ty,
superbounds,
&mut bounds,
ty::List::empty(),
filter,
OverlappingAsssocItemConstraints::Allowed,
);
match filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
Expand Down Expand Up @@ -984,6 +995,7 @@ impl<'tcx> ItemCtxt<'tcx> {
&mut bounds,
bound_vars,
filter,
OverlappingAsssocItemConstraints::Allowed,
);
}

Expand Down Expand Up @@ -1063,6 +1075,7 @@ pub(super) fn const_conditions<'tcx>(
&mut bounds,
bound_vars,
PredicateFilter::ConstIfConst,
OverlappingAsssocItemConstraints::Allowed,
);
}
_ => {}
Expand All @@ -1083,6 +1096,7 @@ pub(super) fn const_conditions<'tcx>(
&mut bounds,
ty::List::empty(),
PredicateFilter::ConstIfConst,
OverlappingAsssocItemConstraints::Allowed,
);
}

Expand Down
32 changes: 19 additions & 13 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use tracing::{debug, instrument};
use super::errors::GenericsArgsErrExtend;
use crate::errors;
use crate::hir_ty_lowering::{
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
AssocItemQSelf, FeedConstTy, HirTyLowerer, OverlappingAsssocItemConstraints, PredicateFilter,
RegionInferReason,
};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -338,6 +339,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
predicate_filter: PredicateFilter,
overlapping_assoc_constraints: OverlappingAsssocItemConstraints,
) where
'tcx: 'hir,
{
Expand All @@ -362,6 +364,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
param_ty,
bounds,
predicate_filter,
overlapping_assoc_constraints,
);
}
hir::GenericBound::Outlives(lifetime) => {
Expand Down Expand Up @@ -402,7 +405,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
trait_ref: ty::PolyTraitRef<'tcx>,
constraint: &hir::AssocItemConstraint<'tcx>,
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
duplicates: &mut FxIndexMap<DefId, Span>,
duplicates: Option<&mut FxIndexMap<DefId, Span>>,
path_span: Span,
predicate_filter: PredicateFilter,
) -> Result<(), ErrorGuaranteed> {
Expand Down Expand Up @@ -458,17 +461,19 @@ 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);
if let Some(duplicates) = duplicates {
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);
Expand Down Expand Up @@ -600,6 +605,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bounds,
projection_ty.bound_vars(),
predicate_filter,
OverlappingAsssocItemConstraints::Allowed,
);
}
PredicateFilter::SelfOnly
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ use tracing::{debug, instrument};

use super::HirTyLowerer;
use crate::errors::SelfInTypeAlias;
use crate::hir_ty_lowering::{GenericArgCountMismatch, PredicateFilter, RegionInferReason};
use crate::hir_ty_lowering::{
GenericArgCountMismatch, OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
};

impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Lower a trait object type from the HIR to our internal notion of a type.
Expand Down Expand Up @@ -60,6 +62,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
dummy_self,
&mut user_written_bounds,
PredicateFilter::SelfOnly,
OverlappingAsssocItemConstraints::Forbidden,
);
if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
potential_assoc_types.extend(invalid_args);
Expand Down Expand Up @@ -157,10 +160,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
18 changes: 16 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,15 @@ pub(crate) enum GenericArgPosition {
MethodCall,
}

/// Whether to allow duplicate associated iten constraints in a trait ref, e.g.
/// `Trait<Assoc = Ty, Assoc = Ty>`. This is forbidden in `dyn Trait<...>`
/// but allowed everywhere else.
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) enum OverlappingAsssocItemConstraints {
Allowed,
Forbidden,
}

/// A marker denoting that the generic arguments that were
/// provided did not match the respective generic parameters.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -752,6 +761,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self_ty: Ty<'tcx>,
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
predicate_filter: PredicateFilter,
overlapping_assoc_item_constraints: OverlappingAsssocItemConstraints,
) -> GenericArgCountResult {
let tcx = self.tcx();

Expand Down Expand Up @@ -908,7 +918,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

let mut dup_constraints = FxIndexMap::default();
let mut dup_constraints = (overlapping_assoc_item_constraints
== OverlappingAsssocItemConstraints::Forbidden)
.then_some(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 @@ -927,7 +940,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
poly_trait_ref,
constraint,
bounds,
&mut dup_constraints,
dup_constraints.as_mut(),
constraint.span,
predicate_filter,
);
Expand Down Expand Up @@ -2484,6 +2497,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&mut bounds,
ty::List::empty(),
PredicateFilter::All,
OverlappingAsssocItemConstraints::Allowed,
);
self.add_sizedness_bounds(
&mut bounds,
Expand Down
Loading
Loading