Rollup merge of #125635 - fmease:mv-type-binding-assoc-item-constraint, r=compiler-errors

Rename HIR `TypeBinding` to `AssocItemConstraint` and related cleanup

Rename `hir::TypeBinding` and `ast::AssocConstraint` to `AssocItemConstraint` and update all items and locals using the old terminology.

Motivation: The terminology *type binding* is extremely outdated. "Type bindings" not only include constraints on associated *types* but also on associated *constants* (feature `associated_const_equality`) and on RPITITs of associated *functions* (feature `return_type_notation`). Hence the word *item* in the new name. Furthermore, the word *binding* commonly refers to a mapping from a binder/identifier to a "value" for some definition of "value". Its use in "type binding" made sense when equality constraints (e.g., `AssocTy = Ty`) were the only kind of associated item constraint. Nowadays however, we also have *associated type bounds* (e.g., `AssocTy: Bound`) for which the term *binding* doesn't make sense.

---

Old terminology (HIR, rustdoc):

```
`TypeBinding`: (associated) type binding
├── `Constraint`: associated type bound
└── `Equality`: (associated) equality constraint (?)
    ├── `Ty`: (associated) type binding
    └── `Const`: associated const equality (constraint)
```

Old terminology (AST, abbrev.):

```
`AssocConstraint`
├── `Bound`
└── `Equality`
    ├── `Ty`
    └── `Const`
```

New terminology (AST, HIR, rustdoc):

```
`AssocItemConstraint`: associated item constraint
├── `Bound`: associated type bound
└── `Equality`: associated item equality constraint OR associated item binding (for short)
    ├── `Ty`: associated type equality constraint OR associated type binding (for short)
    └── `Const`: associated const equality constraint OR associated const binding (for short)
```

r? compiler-errors
This commit is contained in:
Matthias Krüger 2024-05-31 08:50:22 +02:00 committed by GitHub
commit 379233242b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
108 changed files with 878 additions and 818 deletions

View File

@ -167,7 +167,7 @@ impl PathSegment {
} }
} }
/// The arguments of a path segment. /// The generic arguments and associated item constraints of a path segment.
/// ///
/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`. /// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
@ -221,14 +221,13 @@ pub struct AngleBracketedArgs {
pub args: ThinVec<AngleBracketedArg>, pub args: ThinVec<AngleBracketedArg>,
} }
/// Either an argument for a parameter e.g., `'a`, `Vec<u8>`, `0`, /// Either an argument for a generic parameter or a constraint on an associated item.
/// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`.
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum AngleBracketedArg { pub enum AngleBracketedArg {
/// Argument for a generic parameter. /// A generic argument for a generic parameter.
Arg(GenericArg), Arg(GenericArg),
/// Constraint for an associated item. /// A constraint on an associated item.
Constraint(AssocConstraint), Constraint(AssocItemConstraint),
} }
impl AngleBracketedArg { impl AngleBracketedArg {
@ -418,7 +417,7 @@ impl Default for WhereClause {
/// A single predicate in a where-clause. /// A single predicate in a where-clause.
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum WherePredicate { pub enum WherePredicate {
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
BoundPredicate(WhereBoundPredicate), BoundPredicate(WhereBoundPredicate),
/// A lifetime predicate (e.g., `'a: 'b + 'c`). /// A lifetime predicate (e.g., `'a: 'b + 'c`).
RegionPredicate(WhereRegionPredicate), RegionPredicate(WhereRegionPredicate),
@ -2034,18 +2033,25 @@ impl UintTy {
} }
} }
/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or /// A constraint on an associated item.
/// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`). ///
/// ### Examples
///
/// * the `A = Ty` and `B = Ty` in `Trait<A = Ty, B = Ty>`
/// * the `G<Ty> = Ty` in `Trait<G<Ty> = Ty>`
/// * the `A: Bound` in `Trait<A: Bound>`
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub struct AssocConstraint { pub struct AssocItemConstraint {
pub id: NodeId, pub id: NodeId,
pub ident: Ident, pub ident: Ident,
pub gen_args: Option<GenericArgs>, pub gen_args: Option<GenericArgs>,
pub kind: AssocConstraintKind, pub kind: AssocItemConstraintKind,
pub span: Span, pub span: Span,
} }
/// The kinds of an `AssocConstraint`.
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum Term { pub enum Term {
Ty(P<Ty>), Ty(P<Ty>),
@ -2064,12 +2070,17 @@ impl From<AnonConst> for Term {
} }
} }
/// The kinds of an `AssocConstraint`. /// The kind of [associated item constraint][AssocItemConstraint].
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum AssocConstraintKind { pub enum AssocItemConstraintKind {
/// E.g., `A = Bar`, `A = 3` in `Foo<A = Bar>` where A is an associated type. /// An equality constraint for an associated item (e.g., `AssocTy = Ty` in `Trait<AssocTy = Ty>`).
///
/// Also known as an *associated item binding* (we *bind* an associated item to a term).
///
/// Furthermore, associated type equality constraints can also be referred to as *associated type
/// bindings*. Similarly with associated const equality constraints and *associated const bindings*.
Equality { term: Term }, Equality { term: Term },
/// E.g. `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`. /// A bound on an associated type (e.g., `AssocTy: Bound` in `Trait<AssocTy: Bound>`).
Bound { bounds: GenericBounds }, Bound { bounds: GenericBounds },
} }

View File

@ -175,8 +175,8 @@ pub trait MutVisitor: Sized {
noop_visit_lifetime(l, self); noop_visit_lifetime(l, self);
} }
fn visit_constraint(&mut self, t: &mut AssocConstraint) { fn visit_assoc_item_constraint(&mut self, c: &mut AssocItemConstraint) {
noop_visit_constraint(t, self); noop_visit_assoc_item_constraint(c, self);
} }
fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) {
@ -463,8 +463,8 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
smallvec![arm] smallvec![arm]
} }
fn noop_visit_constraint<T: MutVisitor>( fn noop_visit_assoc_item_constraint<T: MutVisitor>(
AssocConstraint { id, ident, gen_args, kind, span }: &mut AssocConstraint, AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint,
vis: &mut T, vis: &mut T,
) { ) {
vis.visit_id(id); vis.visit_id(id);
@ -473,11 +473,11 @@ fn noop_visit_constraint<T: MutVisitor>(
vis.visit_generic_args(gen_args); vis.visit_generic_args(gen_args);
} }
match kind { match kind {
AssocConstraintKind::Equality { term } => match term { AssocItemConstraintKind::Equality { term } => match term {
Term::Ty(ty) => vis.visit_ty(ty), Term::Ty(ty) => vis.visit_ty(ty),
Term::Const(c) => vis.visit_anon_const(c), Term::Const(c) => vis.visit_anon_const(c),
}, },
AssocConstraintKind::Bound { bounds } => visit_bounds(bounds, vis), AssocItemConstraintKind::Bound { bounds } => visit_bounds(bounds, vis),
} }
vis.visit_span(span); vis.visit_span(span);
} }
@ -607,7 +607,7 @@ fn noop_visit_angle_bracketed_parameter_data<T: MutVisitor>(
let AngleBracketedArgs { args, span } = data; let AngleBracketedArgs { args, span } = data;
visit_thin_vec(args, |arg| match arg { visit_thin_vec(args, |arg| match arg {
AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg), AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
AngleBracketedArg::Constraint(constraint) => vis.visit_constraint(constraint), AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint),
}); });
vis.visit_span(span); vis.visit_span(span);
} }

View File

@ -246,8 +246,11 @@ pub trait Visitor<'ast>: Sized {
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result { fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result {
walk_generic_arg(self, generic_arg) walk_generic_arg(self, generic_arg)
} }
fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) -> Self::Result { fn visit_assoc_item_constraint(
walk_assoc_constraint(self, constraint) &mut self,
constraint: &'ast AssocItemConstraint,
) -> Self::Result {
walk_assoc_item_constraint(self, constraint)
} }
fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result { fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result {
walk_attribute(self, attr) walk_attribute(self, attr)
@ -558,7 +561,7 @@ where
match arg { match arg {
AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)), AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
AngleBracketedArg::Constraint(c) => { AngleBracketedArg::Constraint(c) => {
try_visit!(visitor.visit_assoc_constraint(c)) try_visit!(visitor.visit_assoc_item_constraint(c))
} }
} }
} }
@ -582,18 +585,18 @@ where
} }
} }
pub fn walk_assoc_constraint<'a, V: Visitor<'a>>( pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
visitor: &mut V, visitor: &mut V,
constraint: &'a AssocConstraint, constraint: &'a AssocItemConstraint,
) -> V::Result { ) -> V::Result {
try_visit!(visitor.visit_ident(constraint.ident)); try_visit!(visitor.visit_ident(constraint.ident));
visit_opt!(visitor, visit_generic_args, &constraint.gen_args); visit_opt!(visitor, visit_generic_args, &constraint.gen_args);
match &constraint.kind { match &constraint.kind {
AssocConstraintKind::Equality { term } => match term { AssocItemConstraintKind::Equality { term } => match term {
Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)), Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
Term::Const(c) => try_visit!(visitor.visit_anon_const(c)), Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
}, },
AssocConstraintKind::Bound { bounds } => { AssocItemConstraintKind::Bound { bounds } => {
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
} }
} }

View File

@ -325,10 +325,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}); });
} }
fn visit_assoc_type_binding(&mut self, type_binding: &'hir TypeBinding<'hir>) { fn visit_assoc_item_constraint(&mut self, constraint: &'hir AssocItemConstraint<'hir>) {
self.insert(type_binding.span, type_binding.hir_id, Node::TypeBinding(type_binding)); self.insert(constraint.span, constraint.hir_id, Node::AssocItemConstraint(constraint));
self.with_parent(type_binding.hir_id, |this| { self.with_parent(constraint.hir_id, |this| {
intravisit::walk_assoc_type_binding(this, type_binding) intravisit::walk_assoc_item_constraint(this, constraint)
}) })
} }

View File

@ -967,24 +967,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() } DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() }
} }
/// Given an associated type constraint like one of these: /// Lower an associated item constraint.
/// #[instrument(level = "debug", skip_all)]
/// ```ignore (illustrative) fn lower_assoc_item_constraint(
/// T: Iterator<Item: Debug>
/// ^^^^^^^^^^^
/// T: Iterator<Item = Debug>
/// ^^^^^^^^^^^^
/// ```
///
/// returns a `hir::TypeBinding` representing `Item`.
#[instrument(level = "debug", skip(self))]
fn lower_assoc_ty_constraint(
&mut self, &mut self,
constraint: &AssocConstraint, constraint: &AssocItemConstraint,
itctx: ImplTraitContext, itctx: ImplTraitContext,
) -> hir::TypeBinding<'hir> { ) -> hir::AssocItemConstraint<'hir> {
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); debug!(?constraint, ?itctx);
// lower generic arguments of identifier in constraint // Lower the generic arguments for the associated item.
let gen_args = if let Some(gen_args) = &constraint.gen_args { let gen_args = if let Some(gen_args) = &constraint.gen_args {
let gen_args_ctor = match gen_args { let gen_args_ctor = match gen_args {
GenericArgs::AngleBracketed(data) => { GenericArgs::AngleBracketed(data) => {
@ -1000,7 +991,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}; };
GenericArgsCtor { GenericArgsCtor {
args: Default::default(), args: Default::default(),
bindings: &[], constraints: &[],
parenthesized, parenthesized,
span: data.inputs_span, span: data.inputs_span,
} }
@ -1030,7 +1021,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
err.emit(); err.emit();
GenericArgsCtor { GenericArgsCtor {
args: Default::default(), args: Default::default(),
bindings: &[], constraints: &[],
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation, parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
span: data.span, span: data.span,
} }
@ -1052,14 +1043,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.arena.alloc(hir::GenericArgs::none()) self.arena.alloc(hir::GenericArgs::none())
}; };
let kind = match &constraint.kind { let kind = match &constraint.kind {
AssocConstraintKind::Equality { term } => { AssocItemConstraintKind::Equality { term } => {
let term = match term { let term = match term {
Term::Ty(ty) => self.lower_ty(ty, itctx).into(), Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
Term::Const(c) => self.lower_anon_const(c).into(), Term::Const(c) => self.lower_anon_const(c).into(),
}; };
hir::TypeBindingKind::Equality { term } hir::AssocItemConstraintKind::Equality { term }
} }
AssocConstraintKind::Bound { bounds } => { AssocItemConstraintKind::Bound { bounds } => {
// Disallow ATB in dyn types // Disallow ATB in dyn types
if self.is_in_dyn_type { if self.is_in_dyn_type {
let suggestion = match itctx { let suggestion = match itctx {
@ -1083,18 +1074,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}); });
let err_ty = let err_ty =
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
hir::TypeBindingKind::Equality { term: err_ty.into() } hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
} else { } else {
// Desugar `AssocTy: Bounds` into a type binding where the // Desugar `AssocTy: Bounds` into an assoc type binding where the
// later desugars into a trait predicate. // later desugars into a trait predicate.
let bounds = self.lower_param_bounds(bounds, itctx); let bounds = self.lower_param_bounds(bounds, itctx);
hir::TypeBindingKind::Constraint { bounds } hir::AssocItemConstraintKind::Bound { bounds }
} }
} }
}; };
hir::TypeBinding { hir::AssocItemConstraint {
hir_id: self.lower_node_id(constraint.id), hir_id: self.lower_node_id(constraint.id),
ident: self.lower_ident(constraint.ident), ident: self.lower_ident(constraint.ident),
gen_args, gen_args,
@ -2014,7 +2005,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let bound_args = self.arena.alloc(hir::GenericArgs { let bound_args = self.arena.alloc(hir::GenericArgs {
args: &[], args: &[],
bindings: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)], constraints: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)],
parenthesized: hir::GenericArgsParentheses::No, parenthesized: hir::GenericArgsParentheses::No,
span_ext: DUMMY_SP, span_ext: DUMMY_SP,
}); });
@ -2587,10 +2578,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
/// Helper struct for delayed construction of GenericArgs. /// Helper struct for the delayed construction of [`hir::GenericArgs`].
struct GenericArgsCtor<'hir> { struct GenericArgsCtor<'hir> {
args: SmallVec<[hir::GenericArg<'hir>; 4]>, args: SmallVec<[hir::GenericArg<'hir>; 4]>,
bindings: &'hir [hir::TypeBinding<'hir>], constraints: &'hir [hir::AssocItemConstraint<'hir>],
parenthesized: hir::GenericArgsParentheses, parenthesized: hir::GenericArgsParentheses,
span: Span, span: Span,
} }
@ -2670,14 +2661,14 @@ impl<'hir> GenericArgsCtor<'hir> {
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
self.args.is_empty() self.args.is_empty()
&& self.bindings.is_empty() && self.constraints.is_empty()
&& self.parenthesized == hir::GenericArgsParentheses::No && self.parenthesized == hir::GenericArgsParentheses::No
} }
fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> { fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
let ga = hir::GenericArgs { let ga = hir::GenericArgs {
args: this.arena.alloc_from_iter(self.args), args: this.arena.alloc_from_iter(self.args),
bindings: self.bindings, constraints: self.constraints,
parenthesized: self.parenthesized, parenthesized: self.parenthesized,
span_ext: this.lower_span(self.span), span_ext: this.lower_span(self.span),
}; };

View File

@ -281,7 +281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
( (
GenericArgsCtor { GenericArgsCtor {
args: Default::default(), args: Default::default(),
bindings: &[], constraints: &[],
parenthesized: hir::GenericArgsParentheses::No, parenthesized: hir::GenericArgsParentheses::No,
span: path_span.shrink_to_hi(), span: path_span.shrink_to_hi(),
}, },
@ -390,13 +390,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
AngleBracketedArg::Constraint(_) => None, AngleBracketedArg::Constraint(_) => None,
}) })
.collect(); .collect();
let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { let constraints =
AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)), self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
AngleBracketedArg::Arg(_) => None, AngleBracketedArg::Constraint(c) => {
})); Some(self.lower_assoc_item_constraint(c, itctx))
}
AngleBracketedArg::Arg(_) => None,
}));
let ctor = GenericArgsCtor { let ctor = GenericArgsCtor {
args, args,
bindings, constraints,
parenthesized: hir::GenericArgsParentheses::No, parenthesized: hir::GenericArgsParentheses::No,
span: data.span, span: data.span,
}; };
@ -454,12 +457,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Some(bound_modifier_allowed_features), Some(bound_modifier_allowed_features),
); );
} }
let binding = self.assoc_ty_binding(sym::Output, output_span, output_ty); let constraint = self.assoc_ty_binding(sym::Output, output_span, output_ty);
( (
GenericArgsCtor { GenericArgsCtor {
args, args,
bindings: arena_vec![self; binding], constraints: arena_vec![self; constraint],
parenthesized: hir::GenericArgsParentheses::ParenSugar, parenthesized: hir::GenericArgsParentheses::ParenSugar,
span: data.inputs_span, span: data.inputs_span,
}, },
@ -467,24 +470,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) )
} }
/// An associated type binding `$assoc_ty_name = $ty`. /// An associated type binding (i.e., associated type equality constraint).
pub(crate) fn assoc_ty_binding( pub(crate) fn assoc_ty_binding(
&mut self, &mut self,
assoc_ty_name: rustc_span::Symbol, assoc_ty_name: rustc_span::Symbol,
span: Span, span: Span,
ty: &'hir hir::Ty<'hir>, ty: &'hir hir::Ty<'hir>,
) -> hir::TypeBinding<'hir> { ) -> hir::AssocItemConstraint<'hir> {
let ident = Ident::with_dummy_span(assoc_ty_name); let ident = Ident::with_dummy_span(assoc_ty_name);
let kind = hir::TypeBindingKind::Equality { term: ty.into() }; let kind = hir::AssocItemConstraintKind::Equality { term: ty.into() };
let args = arena_vec![self;]; let args = arena_vec![self;];
let bindings = arena_vec![self;]; let constraints = arena_vec![self;];
let gen_args = self.arena.alloc(hir::GenericArgs { let gen_args = self.arena.alloc(hir::GenericArgs {
args, args,
bindings, constraints,
parenthesized: hir::GenericArgsParentheses::No, parenthesized: hir::GenericArgsParentheses::No,
span_ext: DUMMY_SP, span_ext: DUMMY_SP,
}); });
hir::TypeBinding { hir::AssocItemConstraint {
hir_id: self.next_id(), hir_id: self.next_id(),
gen_args, gen_args,
span: self.lower_span(span), span: self.lower_span(span),

View File

@ -671,7 +671,7 @@ impl<'a> AstValidator<'a> {
let constraint_sugg = data.args.iter().filter_map(|a| match a { let constraint_sugg = data.args.iter().filter_map(|a| match a {
AngleBracketedArg::Arg(_) => None, AngleBracketedArg::Arg(_) => None,
AngleBracketedArg::Constraint(c) => { AngleBracketedArg::Constraint(c) => {
Some(pprust::to_string(|s| s.print_assoc_constraint(c))) Some(pprust::to_string(|s| s.print_assoc_item_constraint(c)))
} }
}); });
format!( format!(
@ -1199,11 +1199,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
for arg in &data.args { for arg in &data.args {
match arg { match arg {
AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg), AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
// Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>` // Associated type bindings such as `Item = impl Debug` in
// are allowed to contain nested `impl Trait`. // `Iterator<Item = Debug>` are allowed to contain nested `impl Trait`.
AngleBracketedArg::Constraint(constraint) => { AngleBracketedArg::Constraint(constraint) => {
self.with_impl_trait(None, |this| { self.with_impl_trait(None, |this| {
this.visit_assoc_constraint(constraint); this.visit_assoc_item_constraint(constraint);
}); });
} }
} }
@ -1363,7 +1363,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
} }
} }
// The lowered form of parenthesized generic args contains a type binding. // The lowered form of parenthesized generic args contains an associated type binding.
Some(ast::GenericArgs::Parenthesized(args)) => { Some(ast::GenericArgs::Parenthesized(args)) => {
self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation { self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation {
span: args.span, span: args.span,
@ -1589,11 +1589,13 @@ fn deny_equality_constraints(
let len = assoc_path.segments.len() - 1; let len = assoc_path.segments.len() - 1;
let gen_args = args.as_deref().cloned(); let gen_args = args.as_deref().cloned();
// Build `<Bar = RhsTy>`. // Build `<Bar = RhsTy>`.
let arg = AngleBracketedArg::Constraint(AssocConstraint { let arg = AngleBracketedArg::Constraint(AssocItemConstraint {
id: rustc_ast::node_id::DUMMY_NODE_ID, id: rustc_ast::node_id::DUMMY_NODE_ID,
ident: *ident, ident: *ident,
gen_args, gen_args,
kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() }, kind: AssocItemConstraintKind::Equality {
term: predicate.rhs_ty.clone().into(),
},
span: ident.span, span: ident.span,
}); });
// Add `<Bar = RhsTy>` to `Foo`. // Add `<Bar = RhsTy>` to `Foo`.

View File

@ -1,6 +1,6 @@
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId}; use rustc_ast::{attr, AssocItemConstraint, AssocItemConstraintKind, NodeId};
use rustc_ast::{token, PatKind}; use rustc_ast::{token, PatKind};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP}; use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
@ -344,7 +344,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
for predicate in &g.where_clause.predicates { for predicate in &g.where_clause.predicates {
match predicate { match predicate {
ast::WherePredicate::BoundPredicate(bound_pred) => { ast::WherePredicate::BoundPredicate(bound_pred) => {
// A type binding, eg `for<'c> Foo: Send+Clone+'c` // A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
} }
_ => {} _ => {}
@ -445,21 +445,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_fn(self, fn_kind) visit::walk_fn(self, fn_kind)
} }
fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) { fn visit_assoc_item_constraint(&mut self, constraint: &'a AssocItemConstraint) {
if let AssocConstraintKind::Bound { .. } = constraint.kind { if let AssocItemConstraintKind::Bound { .. } = constraint.kind
if let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref() && let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
&& args.inputs.is_empty() && args.inputs.is_empty()
&& matches!(args.output, ast::FnRetTy::Default(..)) && let ast::FnRetTy::Default(..) = args.output
{ {
gate!( gate!(
&self, &self,
return_type_notation, return_type_notation,
constraint.span, constraint.span,
"return type notation is experimental" "return type notation is experimental"
); );
}
} }
visit::walk_assoc_constraint(self, constraint)
visit::walk_assoc_item_constraint(self, constraint)
} }
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {

View File

@ -119,9 +119,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
self.count += 1; self.count += 1;
walk_generic_args(self, generic_args) walk_generic_args(self, generic_args)
} }
fn visit_assoc_constraint(&mut self, constraint: &AssocConstraint) { fn visit_assoc_item_constraint(&mut self, constraint: &AssocItemConstraint) {
self.count += 1; self.count += 1;
walk_assoc_constraint(self, constraint) walk_assoc_item_constraint(self, constraint)
} }
fn visit_attribute(&mut self, _attr: &Attribute) { fn visit_attribute(&mut self, _attr: &Attribute) {
self.count += 1; self.count += 1;

View File

@ -1045,7 +1045,7 @@ impl<'a> PrintState<'a> for State<'a> {
self.word("<"); self.word("<");
self.commasep(Inconsistent, &data.args, |s, arg| match arg { self.commasep(Inconsistent, &data.args, |s, arg| match arg {
ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a), ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a),
ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c), ast::AngleBracketedArg::Constraint(c) => s.print_assoc_item_constraint(c),
}); });
self.word(">") self.word(">")
} }
@ -1097,21 +1097,21 @@ impl<'a> State<'a> {
} }
} }
pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) { pub fn print_assoc_item_constraint(&mut self, constraint: &ast::AssocItemConstraint) {
self.print_ident(constraint.ident); self.print_ident(constraint.ident);
if let Some(args) = constraint.gen_args.as_ref() { if let Some(args) = constraint.gen_args.as_ref() {
self.print_generic_args(args, false) self.print_generic_args(args, false)
} }
self.space(); self.space();
match &constraint.kind { match &constraint.kind {
ast::AssocConstraintKind::Equality { term } => { ast::AssocItemConstraintKind::Equality { term } => {
self.word_space("="); self.word_space("=");
match term { match term {
Term::Ty(ty) => self.print_type(ty), Term::Ty(ty) => self.print_type(ty),
Term::Const(c) => self.print_expr_anon_const(c, &[]), Term::Const(c) => self.print_expr_anon_const(c, &[]),
} }
} }
ast::AssocConstraintKind::Bound { bounds } => { ast::AssocItemConstraintKind::Bound { bounds } => {
if !bounds.is_empty() { if !bounds.is_empty() {
self.word_nbsp(":"); self.word_nbsp(":");
self.print_type_bounds(bounds); self.print_type_bounds(bounds);

View File

@ -12,7 +12,7 @@ use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
@ -843,13 +843,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
}) = opaque_ty.kind }) = opaque_ty.kind
&& let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(segment) = trait_ref.trait_ref.path.segments.last()
&& let Some(args) = segment.args && let Some(args) = segment.args
&& let [ && let [constraint] = args.constraints
hir::TypeBinding { && constraint.ident.name == sym::Output
ident: Ident { name: sym::Output, .. }, && let Some(ty) = constraint.ty()
kind: hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) },
..
},
] = args.bindings
{ {
ty ty
} else { } else {

View File

@ -1,5 +1,4 @@
An associated type binding was done outside of the type parameter declaration An associated item constraint was written in an unexpected context.
and `where` clause.
Erroneous code example: Erroneous code example:
@ -16,12 +15,12 @@ impl Foo for isize {
fn boo(&self) -> usize { 42 } fn boo(&self) -> usize { 42 }
} }
fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
// error: associated type bindings are not allowed here // error: associated item constraint are not allowed here
``` ```
To solve this error, please move the type bindings in the type parameter To solve this error, please move the associated item constraints to the type
declaration: parameter declaration:
``` ```
# struct Bar; # struct Bar;
@ -29,7 +28,7 @@ declaration:
fn baz<I: Foo<A=Bar>>(x: &<I as Foo>::A) {} // ok! fn baz<I: Foo<A=Bar>>(x: &<I as Foo>::A) {} // ok!
``` ```
Or in the `where` clause: Or into the where-clause:
``` ```
# struct Bar; # struct Bar;

View File

@ -300,23 +300,30 @@ impl GenericArg<'_> {
} }
} }
/// The generic arguments and associated item constraints of a path segment.
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct GenericArgs<'hir> { pub struct GenericArgs<'hir> {
/// The generic arguments for this path segment. /// The generic arguments for this path segment.
pub args: &'hir [GenericArg<'hir>], pub args: &'hir [GenericArg<'hir>],
/// Bindings (equality constraints) on associated types, if present. /// The associated item constraints for this path segment.
/// E.g., `Foo<A = Bar>`. pub constraints: &'hir [AssocItemConstraint<'hir>],
pub bindings: &'hir [TypeBinding<'hir>], /// Whether the arguments were written in parenthesized form (e.g., `Fn(T) -> U`).
/// Were arguments written in parenthesized form `Fn(T) -> U`? ///
/// This is required mostly for pretty-printing and diagnostics, /// This is required mostly for pretty-printing and diagnostics,
/// but also for changing lifetime elision rules to be "function-like". /// but also for changing lifetime elision rules to be "function-like".
pub parenthesized: GenericArgsParentheses, pub parenthesized: GenericArgsParentheses,
/// The span encompassing arguments and the surrounding brackets `<>` or `()` /// The span encompassing the arguments, constraints and the surrounding brackets (`<>` or `()`).
///
/// For example:
///
/// ```ignore (illustrative)
/// Foo<A, B, AssocTy = D> Fn(T, U, V) -> W /// Foo<A, B, AssocTy = D> Fn(T, U, V) -> W
/// ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ /// ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
/// ```
///
/// Note that this may be: /// Note that this may be:
/// - empty, if there are no generic brackets (but there may be hidden lifetimes) /// - empty, if there are no generic brackets (but there may be hidden lifetimes)
/// - dummy, if this was generated while desugaring /// - dummy, if this was generated during desugaring
pub span_ext: Span, pub span_ext: Span,
} }
@ -324,39 +331,63 @@ impl<'hir> GenericArgs<'hir> {
pub const fn none() -> Self { pub const fn none() -> Self {
Self { Self {
args: &[], args: &[],
bindings: &[], constraints: &[],
parenthesized: GenericArgsParentheses::No, parenthesized: GenericArgsParentheses::No,
span_ext: DUMMY_SP, span_ext: DUMMY_SP,
} }
} }
pub fn inputs(&self) -> &[Ty<'hir>] { /// Obtain the list of input types and the output type if the generic arguments are parenthesized.
if self.parenthesized == GenericArgsParentheses::ParenSugar { ///
for arg in self.args { /// Returns the `Ty0, Ty1, ...` and the `RetTy` in `Trait(Ty0, Ty1, ...) -> RetTy`.
match arg { /// Panics if the parenthesized arguments have an incorrect form (this shouldn't happen).
GenericArg::Lifetime(_) => {} pub fn paren_sugar_inputs_output(&self) -> Option<(&[Ty<'hir>], &Ty<'hir>)> {
GenericArg::Type(ref ty) => { if self.parenthesized != GenericArgsParentheses::ParenSugar {
if let TyKind::Tup(ref tys) = ty.kind { return None;
return tys;
}
break;
}
GenericArg::Const(_) => {}
GenericArg::Infer(_) => {}
}
}
} }
panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
let inputs = self
.args
.iter()
.find_map(|arg| {
let GenericArg::Type(ty) = arg else { return None };
let TyKind::Tup(tys) = &ty.kind else { return None };
Some(tys)
})
.unwrap();
Some((inputs, self.paren_sugar_output_inner()))
} }
pub fn has_err(&self) -> bool { /// Obtain the output type if the generic arguments are parenthesized.
self.args.iter().any(|arg| match arg { ///
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)), /// Returns the `RetTy` in `Trait(Ty0, Ty1, ...) -> RetTy`.
_ => false, /// Panics if the parenthesized arguments have an incorrect form (this shouldn't happen).
}) || self.bindings.iter().any(|arg| match arg.kind { pub fn paren_sugar_output(&self) -> Option<&Ty<'hir>> {
TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err(_)), (self.parenthesized == GenericArgsParentheses::ParenSugar)
_ => false, .then(|| self.paren_sugar_output_inner())
}) }
fn paren_sugar_output_inner(&self) -> &Ty<'hir> {
let [constraint] = self.constraints.try_into().unwrap();
debug_assert_eq!(constraint.ident.name, sym::Output);
constraint.ty().unwrap()
}
pub fn has_err(&self) -> Option<ErrorGuaranteed> {
self.args
.iter()
.find_map(|arg| {
let GenericArg::Type(ty) = arg else { return None };
let TyKind::Err(guar) = ty.kind else { return None };
Some(guar)
})
.or_else(|| {
self.constraints.iter().find_map(|constraint| {
let TyKind::Err(guar) = constraint.ty()?.kind else { return None };
Some(guar)
})
})
} }
#[inline] #[inline]
@ -383,9 +414,11 @@ impl<'hir> GenericArgs<'hir> {
.count() .count()
} }
/// The span encompassing the text inside the surrounding brackets. /// The span encompassing the arguments and constraints[^1] inside the surrounding brackets.
/// It will also include bindings if they aren't in the form `-> Ret` ///
/// Returns `None` if the span is empty (e.g. no brackets) or dummy /// Returns `None` if the span is empty (i.e., no brackets) or dummy.
///
/// [^1]: Unless of the form `-> Ty` (see [`GenericArgsParentheses`]).
pub fn span(&self) -> Option<Span> { pub fn span(&self) -> Option<Span> {
let span_ext = self.span_ext()?; let span_ext = self.span_ext()?;
Some(span_ext.with_lo(span_ext.lo() + BytePos(1)).with_hi(span_ext.hi() - BytePos(1))) Some(span_ext.with_lo(span_ext.lo() + BytePos(1)).with_hi(span_ext.hi() - BytePos(1)))
@ -660,9 +693,7 @@ impl<'hir> Generics<'hir> {
|bound| { |bound| {
let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref() let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref()
&& let [.., segment] = trait_ref.path.segments && let [.., segment] = trait_ref.path.segments
&& segment.args().parenthesized == GenericArgsParentheses::ParenSugar && let Some(ret_ty) = segment.args().paren_sugar_output()
&& let [binding] = segment.args().bindings
&& let TypeBindingKind::Equality { term: Term::Ty(ret_ty) } = binding.kind
&& let ret_ty = ret_ty.peel_refs() && let ret_ty = ret_ty.peel_refs()
&& let TyKind::TraitObject( && let TyKind::TraitObject(
_, _,
@ -748,7 +779,7 @@ impl<'hir> Generics<'hir> {
/// A single predicate in a where-clause. /// A single predicate in a where-clause.
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum WherePredicate<'hir> { pub enum WherePredicate<'hir> {
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
BoundPredicate(WhereBoundPredicate<'hir>), BoundPredicate(WhereBoundPredicate<'hir>),
/// A lifetime predicate (e.g., `'a: 'b + 'c`). /// A lifetime predicate (e.g., `'a: 'b + 'c`).
RegionPredicate(WhereRegionPredicate<'hir>), RegionPredicate(WhereRegionPredicate<'hir>),
@ -2356,24 +2387,43 @@ pub enum ImplItemKind<'hir> {
Type(&'hir Ty<'hir>), Type(&'hir Ty<'hir>),
} }
/// An associated item binding. /// A constraint on an associated item.
/// ///
/// ### Examples /// ### Examples
/// ///
/// * `Trait<A = Ty, B = Ty>` /// * the `A = Ty` and `B = Ty` in `Trait<A = Ty, B = Ty>`
/// * `Trait<G<Ty> = Ty>` /// * the `G<Ty> = Ty` in `Trait<G<Ty> = Ty>`
/// * `Trait<A: Bound>` /// * the `A: Bound` in `Trait<A: Bound>`
/// * `Trait<C = { Ct }>` (under feature `associated_const_equality`) /// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
/// * `Trait<f(): Bound>` (under feature `return_type_notation`) /// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct TypeBinding<'hir> { pub struct AssocItemConstraint<'hir> {
pub hir_id: HirId, pub hir_id: HirId,
pub ident: Ident, pub ident: Ident,
pub gen_args: &'hir GenericArgs<'hir>, pub gen_args: &'hir GenericArgs<'hir>,
pub kind: TypeBindingKind<'hir>, pub kind: AssocItemConstraintKind<'hir>,
pub span: Span, pub span: Span,
} }
impl<'hir> AssocItemConstraint<'hir> {
/// Obtain the type on the RHS of an assoc ty equality constraint if applicable.
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
match self.kind {
AssocItemConstraintKind::Equality { term: Term::Ty(ty) } => Some(ty),
_ => None,
}
}
/// Obtain the const on the RHS of an assoc const equality constraint if applicable.
pub fn ct(self) -> Option<&'hir AnonConst> {
match self.kind {
AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum Term<'hir> { pub enum Term<'hir> {
Ty(&'hir Ty<'hir>), Ty(&'hir Ty<'hir>),
@ -2392,28 +2442,18 @@ impl<'hir> From<&'hir AnonConst> for Term<'hir> {
} }
} }
// Represents the two kinds of type bindings. /// The kind of [associated item constraint][AssocItemConstraint].
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TypeBindingKind<'hir> { pub enum AssocItemConstraintKind<'hir> {
/// E.g., `Foo<Bar: Send>`. /// An equality constraint for an associated item (e.g., `AssocTy = Ty` in `Trait<AssocTy = Ty>`).
Constraint { bounds: &'hir [GenericBound<'hir>] }, ///
/// E.g., `Foo<Bar = ()>`. /// Also known as an *associated item binding* (we *bind* an associated item to a term).
///
/// Furthermore, associated type equality constraints can also be referred to as *associated type
/// bindings*. Similarly with associated const equality constraints and *associated const bindings*.
Equality { term: Term<'hir> }, Equality { term: Term<'hir> },
} /// A bound on an associated type (e.g., `AssocTy: Bound` in `Trait<AssocTy: Bound>`).
Bound { bounds: &'hir [GenericBound<'hir>] },
impl TypeBinding<'_> {
pub fn ty(&self) -> &Ty<'_> {
match self.kind {
TypeBindingKind::Equality { term: Term::Ty(ref ty) } => ty,
_ => panic!("expected equality type binding for parenthesized generic args"),
}
}
pub fn opt_const(&self) -> Option<&'_ AnonConst> {
match self.kind {
TypeBindingKind::Equality { term: Term::Const(ref c) } => Some(c),
_ => None,
}
}
} }
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
@ -3609,7 +3649,7 @@ pub enum Node<'hir> {
Stmt(&'hir Stmt<'hir>), Stmt(&'hir Stmt<'hir>),
PathSegment(&'hir PathSegment<'hir>), PathSegment(&'hir PathSegment<'hir>),
Ty(&'hir Ty<'hir>), Ty(&'hir Ty<'hir>),
TypeBinding(&'hir TypeBinding<'hir>), AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
TraitRef(&'hir TraitRef<'hir>), TraitRef(&'hir TraitRef<'hir>),
Pat(&'hir Pat<'hir>), Pat(&'hir Pat<'hir>),
PatField(&'hir PatField<'hir>), PatField(&'hir PatField<'hir>),
@ -3658,7 +3698,7 @@ impl<'hir> Node<'hir> {
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
Node::Lifetime(lt) => Some(lt.ident), Node::Lifetime(lt) => Some(lt.ident),
Node::GenericParam(p) => Some(p.name.ident()), Node::GenericParam(p) => Some(p.name.ident()),
Node::TypeBinding(b) => Some(b.ident), Node::AssocItemConstraint(c) => Some(c.ident),
Node::PatField(f) => Some(f.ident), Node::PatField(f) => Some(f.ident),
Node::ExprField(f) => Some(f.ident), Node::ExprField(f) => Some(f.ident),
Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident), Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
@ -3834,7 +3874,7 @@ impl<'hir> Node<'hir> {
expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n; expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n;
expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n; expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n;
expect_ty, &'hir Ty<'hir>, Node::Ty(n), n; expect_ty, &'hir Ty<'hir>, Node::Ty(n), n;
expect_type_binding, &'hir TypeBinding<'hir>, Node::TypeBinding(n), n; expect_assoc_item_constraint, &'hir AssocItemConstraint<'hir>, Node::AssocItemConstraint(n), n;
expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n; expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n;
expect_pat, &'hir Pat<'hir>, Node::Pat(n), n; expect_pat, &'hir Pat<'hir>, Node::Pat(n), n;
expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n; expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n;

View File

@ -453,8 +453,11 @@ pub trait Visitor<'v>: Sized {
fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result { fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result {
walk_generic_args(self, generic_args) walk_generic_args(self, generic_args)
} }
fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) -> Self::Result { fn visit_assoc_item_constraint(
walk_assoc_type_binding(self, type_binding) &mut self,
constraint: &'v AssocItemConstraint<'v>,
) -> Self::Result {
walk_assoc_item_constraint(self, constraint)
} }
fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result { fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result {
Self::Result::output() Self::Result::output()
@ -1248,23 +1251,25 @@ pub fn walk_generic_args<'v, V: Visitor<'v>>(
generic_args: &'v GenericArgs<'v>, generic_args: &'v GenericArgs<'v>,
) -> V::Result { ) -> V::Result {
walk_list!(visitor, visit_generic_arg, generic_args.args); walk_list!(visitor, visit_generic_arg, generic_args.args);
walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings); walk_list!(visitor, visit_assoc_item_constraint, generic_args.constraints);
V::Result::output() V::Result::output()
} }
pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
visitor: &mut V, visitor: &mut V,
type_binding: &'v TypeBinding<'v>, constraint: &'v AssocItemConstraint<'v>,
) -> V::Result { ) -> V::Result {
try_visit!(visitor.visit_id(type_binding.hir_id)); try_visit!(visitor.visit_id(constraint.hir_id));
try_visit!(visitor.visit_ident(type_binding.ident)); try_visit!(visitor.visit_ident(constraint.ident));
try_visit!(visitor.visit_generic_args(type_binding.gen_args)); try_visit!(visitor.visit_generic_args(constraint.gen_args));
match type_binding.kind { match constraint.kind {
TypeBindingKind::Equality { ref term } => match term { AssocItemConstraintKind::Equality { ref term } => match term {
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)), Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)), Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)),
}, },
TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds), AssocItemConstraintKind::Bound { bounds } => {
walk_list!(visitor, visit_param_bound, bounds)
}
} }
V::Result::output() V::Result::output()
} }

View File

@ -4,6 +4,10 @@ hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_
hir_analysis_ambiguous_lifetime_bound = hir_analysis_ambiguous_lifetime_bound =
ambiguous lifetime bound, explicit lifetime bound required ambiguous lifetime bound, explicit lifetime bound required
hir_analysis_assoc_item_constraints_not_allowed_here =
associated item constraints are not allowed here
.label = associated item constraint not allowed here
hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}` hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}`
hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named ->
@ -24,10 +28,6 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here
hir_analysis_assoc_type_binding_not_allowed =
associated type bindings are not allowed here
.label = associated type not allowed here
hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
.suggestion = use a fully qualified path with inferred lifetimes .suggestion = use a fully qualified path with inferred lifetimes

View File

@ -1468,12 +1468,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
depth: usize, depth: usize,
generic_args: &'tcx hir::GenericArgs<'tcx>, generic_args: &'tcx hir::GenericArgs<'tcx>,
) { ) {
if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
self.visit_fn_like_elision( self.visit_fn_like_elision(inputs, Some(output), false);
generic_args.inputs(),
Some(generic_args.bindings[0].ty()),
false,
);
return; return;
} }
@ -1608,8 +1604,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
} }
} }
// Hack: when resolving the type `XX` in binding like `dyn // Hack: When resolving the type `XX` in an assoc ty binding like
// Foo<'b, Item = XX>`, the current object-lifetime default // `dyn Foo<'b, Item = XX>`, the current object-lifetime default
// would be to examine the trait `Foo` to check whether it has // would be to examine the trait `Foo` to check whether it has
// a lifetime bound declared on `Item`. e.g., if `Foo` is // a lifetime bound declared on `Item`. e.g., if `Foo` is
// declared like so, then the default object lifetime bound in // declared like so, then the default object lifetime bound in
@ -1637,7 +1633,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
// in the trait ref `YY<...>` in `Item: YY<...>`. // in the trait ref `YY<...>` in `Item: YY<...>`.
for binding in generic_args.bindings { for constraint in generic_args.constraints {
let scope = Scope::ObjectLifetimeDefault { let scope = Scope::ObjectLifetimeDefault {
lifetime: if has_lifetime_parameter { lifetime: if has_lifetime_parameter {
None None
@ -1646,7 +1642,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
}, },
s: self.scope, s: self.scope,
}; };
// If the binding is parenthesized, then this must be `feature(return_type_notation)`. // If the args are parenthesized, then this must be `feature(return_type_notation)`.
// In that case, introduce a binder over all of the function's early and late bound vars. // In that case, introduce a binder over all of the function's early and late bound vars.
// //
// For example, given // For example, given
@ -1659,13 +1655,14 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>` // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
// this is going to expand to something like: // this is going to expand to something like:
// `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`. // `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { if constraint.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
&& let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars( && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars(
self.tcx, self.tcx,
type_def_id, type_def_id,
binding.ident, constraint.ident,
ty::AssocKind::Fn, ty::AssocKind::Fn,
) { ) {
bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).own_params.iter().map( bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).own_params.iter().map(
@ -1686,22 +1683,22 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
} else { } else {
self.tcx self.tcx
.dcx() .dcx()
.span_delayed_bug(binding.ident.span, "bad return type notation here"); .span_delayed_bug(constraint.ident.span, "bad return type notation here");
vec![] vec![]
}; };
self.with(scope, |this| { self.with(scope, |this| {
let scope = Scope::Supertrait { bound_vars, s: this.scope }; let scope = Scope::Supertrait { bound_vars, s: this.scope };
this.with(scope, |this| { this.with(scope, |this| {
let (bound_vars, _) = this.poly_trait_ref_binder_info(); let (bound_vars, _) = this.poly_trait_ref_binder_info();
this.record_late_bound_vars(binding.hir_id, bound_vars); this.record_late_bound_vars(constraint.hir_id, bound_vars);
this.visit_assoc_type_binding(binding) this.visit_assoc_item_constraint(constraint)
}); });
}); });
} else if let Some(type_def_id) = type_def_id { } else if let Some(type_def_id) = type_def_id {
let bound_vars = BoundVarContext::supertrait_hrtb_vars( let bound_vars = BoundVarContext::supertrait_hrtb_vars(
self.tcx, self.tcx,
type_def_id, type_def_id,
binding.ident, constraint.ident,
ty::AssocKind::Type, ty::AssocKind::Type,
) )
.map(|(bound_vars, _)| bound_vars); .map(|(bound_vars, _)| bound_vars);
@ -1710,10 +1707,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
bound_vars: bound_vars.unwrap_or_default(), bound_vars: bound_vars.unwrap_or_default(),
s: this.scope, s: this.scope,
}; };
this.with(scope, |this| this.visit_assoc_type_binding(binding)); this.with(scope, |this| this.visit_assoc_item_constraint(constraint));
}); });
} else { } else {
self.with(scope, |this| this.visit_assoc_type_binding(binding)); self.with(scope, |this| this.visit_assoc_item_constraint(constraint));
} }
} }
} }

View File

@ -220,9 +220,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
.position(|arg| arg.hir_id() == hir_id) .position(|arg| arg.hir_id() == hir_id)
.map(|index| (index, seg)) .map(|index| (index, seg))
.or_else(|| { .or_else(|| {
args.bindings args.constraints
.iter() .iter()
.filter_map(TypeBinding::opt_const) .copied()
.filter_map(AssocItemConstraint::ct)
.position(|ct| ct.hir_id == hir_id) .position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg)) .map(|idx| (idx, seg))
}) })

View File

@ -290,8 +290,8 @@ pub struct AmbiguousLifetimeBound {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_assoc_type_binding_not_allowed, code = E0229)] #[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)]
pub struct AssocTypeBindingNotAllowed { pub struct AssocItemConstraintsNotAllowedHere {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,

View File

@ -230,32 +230,34 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bounds bounds
} }
/// Lower an associated item binding from HIR into `bounds`. /// Lower an associated item constraint from the HIR into `bounds`.
/// ///
/// ### A Note on Binders /// ### A Note on Binders
/// ///
/// Given something like `T: for<'a> Iterator<Item = &'a u32>`, /// Given something like `T: for<'a> Iterator<Item = &'a u32>`,
/// the `trait_ref` here will be `for<'a> T: Iterator`. /// the `trait_ref` here will be `for<'a> T: Iterator`.
/// The `binding` data however is from *inside* the binder /// The `constraint` data however is from *inside* the binder
/// (e.g., `&'a u32`) and hence may reference bound regions. /// (e.g., `&'a u32`) and hence may reference bound regions.
#[instrument(level = "debug", skip(self, bounds, dup_bindings, path_span))] #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))]
pub(super) fn lower_assoc_item_binding( pub(super) fn lower_assoc_item_constraint(
&self, &self,
hir_ref_id: hir::HirId, hir_ref_id: hir::HirId,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
binding: &hir::TypeBinding<'tcx>, constraint: &hir::AssocItemConstraint<'tcx>,
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
dup_bindings: &mut FxIndexMap<DefId, Span>, duplicates: &mut FxIndexMap<DefId, Span>,
path_span: Span, path_span: Span,
only_self_bounds: OnlySelfBounds, only_self_bounds: OnlySelfBounds,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx(); let tcx = self.tcx();
let assoc_kind = if binding.gen_args.parenthesized let assoc_kind = if constraint.gen_args.parenthesized
== hir::GenericArgsParentheses::ReturnTypeNotation == hir::GenericArgsParentheses::ReturnTypeNotation
{ {
ty::AssocKind::Fn ty::AssocKind::Fn
} else if let hir::TypeBindingKind::Equality { term: hir::Term::Const(_) } = binding.kind { } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } =
constraint.kind
{
ty::AssocKind::Const ty::AssocKind::Const
} else { } else {
ty::AssocKind::Type ty::AssocKind::Type
@ -272,7 +274,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let candidate = if self.probe_trait_that_defines_assoc_item( let candidate = if self.probe_trait_that_defines_assoc_item(
trait_ref.def_id(), trait_ref.def_id(),
assoc_kind, assoc_kind,
binding.ident, constraint.ident,
) { ) {
// Simple case: The assoc item is defined in the current trait. // Simple case: The assoc item is defined in the current trait.
trait_ref trait_ref
@ -284,14 +286,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
trait_ref.skip_binder().print_only_trait_name(), trait_ref.skip_binder().print_only_trait_name(),
None, None,
assoc_kind, assoc_kind,
binding.ident, constraint.ident,
path_span, path_span,
Some(binding), Some(constraint),
)? )?
}; };
let (assoc_ident, def_scope) = let (assoc_ident, def_scope) =
tcx.adjust_ident_and_get_scope(binding.ident, candidate.def_id(), hir_ref_id); tcx.adjust_ident_and_get_scope(constraint.ident, candidate.def_id(), hir_ref_id);
// We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()`
// instead of calling `filter_by_name_and_kind` which would needlessly normalize the // instead of calling `filter_by_name_and_kind` which would needlessly normalize the
@ -306,26 +308,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let reported = tcx let reported = tcx
.dcx() .dcx()
.struct_span_err( .struct_span_err(
binding.span, constraint.span,
format!("{} `{}` is private", assoc_item.kind, binding.ident), format!("{} `{}` is private", assoc_item.kind, constraint.ident),
) )
.with_span_label(binding.span, format!("private {}", assoc_item.kind)) .with_span_label(constraint.span, format!("private {}", assoc_item.kind))
.emit(); .emit();
self.set_tainted_by_errors(reported); self.set_tainted_by_errors(reported);
} }
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), constraint.span, None);
dup_bindings duplicates
.entry(assoc_item.def_id) .entry(assoc_item.def_id)
.and_modify(|prev_span| { .and_modify(|prev_span| {
tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified { tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
span: binding.span, span: constraint.span,
prev_span: *prev_span, prev_span: *prev_span,
item_name: binding.ident, item_name: constraint.ident,
def_path: tcx.def_path_str(assoc_item.container_id(tcx)), def_path: tcx.def_path_str(assoc_item.container_id(tcx)),
}); });
}) })
.or_insert(binding.span); .or_insert(constraint.span);
let projection_term = if let ty::AssocKind::Fn = assoc_kind { let projection_term = if let ty::AssocKind::Fn = assoc_kind {
let mut emitted_bad_param_err = None; let mut emitted_bad_param_err = None;
@ -384,7 +386,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
alias_ty.into() alias_ty.into()
} else { } else {
return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
span: binding.span, span: constraint.span,
ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
fn_span: tcx.hir().span_if_local(assoc_item.def_id), fn_span: tcx.hir().span_if_local(assoc_item.def_id),
note: (), note: (),
@ -398,19 +400,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args); let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
let bound_vars = tcx.late_bound_vars(binding.hir_id); let bound_vars = tcx.late_bound_vars(constraint.hir_id);
ty::Binder::bind_with_vars(instantiation_output, bound_vars) ty::Binder::bind_with_vars(instantiation_output, bound_vars)
} else { } else {
// Create the generic arguments for the associated type or constant by joining the // Create the generic arguments for the associated type or constant by joining the
// parent arguments (the arguments of the trait) and the own arguments (the ones of // parent arguments (the arguments of the trait) and the own arguments (the ones of
// the associated item itself) and construct an alias type using them. // the associated item itself) and construct an alias type using them.
let alias_ty = candidate.map_bound(|trait_ref| { let alias_ty = candidate.map_bound(|trait_ref| {
let ident = Ident::new(assoc_item.name, binding.ident.span); let ident = Ident::new(assoc_item.name, constraint.ident.span);
let item_segment = hir::PathSegment { let item_segment = hir::PathSegment {
ident, ident,
hir_id: binding.hir_id, hir_id: constraint.hir_id,
res: Res::Err, res: Res::Err,
args: Some(binding.gen_args), args: Some(constraint.gen_args),
infer_args: false, infer_args: false,
}; };
@ -426,26 +428,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}); });
// Provide the resolved type of the associated constant to `type_of(AnonConst)`. // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
if let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } = if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(anon_const) } =
binding.kind constraint.kind
{ {
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args)); let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, binding.hir_id); let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, constraint.hir_id);
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty)); tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
} }
alias_ty alias_ty
}; };
match binding.kind { match constraint.kind {
hir::TypeBindingKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => { hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => {
return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound { return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound {
span: binding.span, span: constraint.span,
})); }));
} }
// Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>` // Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator<Item = u32>`
// to a projection predicate: `<T as Iterator>::Item = u32`. // to a projection predicate: `<T as Iterator>::Item = u32`.
hir::TypeBindingKind::Equality { term } => { hir::AssocItemConstraintKind::Equality { term } => {
let term = match term { let term = match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(), hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(),
@ -469,18 +471,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
// ---- ---- ^^^^^^^ // ---- ---- ^^^^^^^
// NOTE(associated_const_equality): This error should be impossible to trigger // NOTE(associated_const_equality): This error should be impossible to trigger
// with associated const equality bounds. // with associated const equality constraints.
self.validate_late_bound_regions( self.validate_late_bound_regions(
late_bound_in_projection_ty, late_bound_in_projection_ty,
late_bound_in_term, late_bound_in_term,
|br_name| { |br_name| {
struct_span_code_err!( struct_span_code_err!(
tcx.dcx(), tcx.dcx(),
binding.span, constraint.span,
E0582, E0582,
"binding for associated type `{}` references {}, \ "binding for associated type `{}` references {}, \
which does not appear in the trait input types", which does not appear in the trait input types",
binding.ident, constraint.ident,
br_name br_name
) )
}, },
@ -492,12 +494,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
projection_term, projection_term,
term, term,
}), }),
binding.span, constraint.span,
); );
} }
// Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>` // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
// to a bound involving a projection: `<T as Iterator>::Item: Debug`. // to a bound involving a projection: `<T as Iterator>::Item: Debug`.
hir::TypeBindingKind::Constraint { bounds: hir_bounds } => { hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
// NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into // NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into
// a trait predicate, since we only want to add predicates for the `Self` type. // a trait predicate, since we only want to add predicates for the `Self` type.
if !only_self_bounds.0 { if !only_self_bounds.0 {

View File

@ -1,5 +1,5 @@
use crate::errors::{ use crate::errors::{
self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
}; };
use crate::fluent_generated as fluent; use crate::fluent_generated as fluent;
@ -121,7 +121,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
assoc_kind: ty::AssocKind, assoc_kind: ty::AssocKind,
assoc_name: Ident, assoc_name: Ident,
span: Span, span: Span,
binding: Option<&hir::TypeBinding<'tcx>>, constraint: Option<&hir::AssocItemConstraint<'tcx>>,
) -> ErrorGuaranteed ) -> ErrorGuaranteed
where where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>, I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@ -135,7 +135,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id())) .find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id()))
}) { }) {
return self.complain_about_assoc_kind_mismatch( return self.complain_about_assoc_kind_mismatch(
assoc_item, assoc_kind, assoc_name, span, binding, assoc_item, assoc_kind, assoc_name, span, constraint,
); );
} }
@ -300,18 +300,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
assoc_kind: ty::AssocKind, assoc_kind: ty::AssocKind,
ident: Ident, ident: Ident,
span: Span, span: Span,
binding: Option<&hir::TypeBinding<'tcx>>, constraint: Option<&hir::AssocItemConstraint<'tcx>>,
) -> ErrorGuaranteed { ) -> ErrorGuaranteed {
let tcx = self.tcx(); let tcx = self.tcx();
let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind
&& let Some(binding) = binding && let Some(constraint) = constraint
&& let hir::TypeBindingKind::Constraint { .. } = binding.kind && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind
{ {
let lo = if binding.gen_args.span_ext.is_dummy() { let lo = if constraint.gen_args.span_ext.is_dummy() {
ident.span ident.span
} else { } else {
binding.gen_args.span_ext constraint.gen_args.span_ext
}; };
Some(lo.between(span.shrink_to_hi())) Some(lo.between(span.shrink_to_hi()))
} else { } else {
@ -319,8 +319,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}; };
// FIXME(associated_const_equality): This has quite a few false positives and negatives. // FIXME(associated_const_equality): This has quite a few false positives and negatives.
let wrap_in_braces_sugg = if let Some(binding) = binding let wrap_in_braces_sugg = if let Some(constraint) = constraint
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(hir_ty) } = binding.kind && let Some(hir_ty) = constraint.ty()
&& let ty = self.lower_ty(hir_ty) && let ty = self.lower_ty(hir_ty)
&& (ty.is_enum() || ty.references_error()) && (ty.is_enum() || ty.references_error())
&& tcx.features().associated_const_equality && tcx.features().associated_const_equality
@ -333,10 +333,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
None None
}; };
// For equality bounds, we want to blame the term (RHS) instead of the item (LHS) since // For equality constraints, we want to blame the term (RHS) instead of the item (LHS) since
// one can argue that that's more “intuitive” to the user. // one can argue that that's more “intuitive” to the user.
let (span, expected_because_label, expected, got) = if let Some(binding) = binding let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint
&& let hir::TypeBindingKind::Equality { term } = binding.kind && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
{ {
let span = match term { let span = match term {
hir::Term::Ty(ty) => ty.span, hir::Term::Ty(ty) => ty.span,
@ -791,8 +791,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let path = poly_trait_ref.trait_ref.path.segments.last()?; let path = poly_trait_ref.trait_ref.path.segments.last()?;
let args = path.args?; let args = path.args?;
Some(args.bindings.iter().filter_map(|binding| { Some(args.constraints.iter().filter_map(|constraint| {
let ident = binding.ident; let ident = constraint.ident;
let trait_def = path.res.def_id(); let trait_def = path.res.def_id();
let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind( let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind(
tcx, tcx,
@ -1192,14 +1192,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} }
} }
/// Emits an error regarding forbidden type binding associations /// Emit an error for the given associated item constraint.
pub fn prohibit_assoc_item_binding( pub fn prohibit_assoc_item_constraint(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
binding: &hir::TypeBinding<'_>, constraint: &hir::AssocItemConstraint<'_>,
segment: Option<(DefId, &hir::PathSegment<'_>, Span)>, segment: Option<(DefId, &hir::PathSegment<'_>, Span)>,
) -> ErrorGuaranteed { ) -> ErrorGuaranteed {
let mut err = tcx.dcx().create_err(AssocTypeBindingNotAllowed { let mut err = tcx.dcx().create_err(AssocItemConstraintsNotAllowedHere {
span: binding.span, span: constraint.span,
fn_trait_expansion: if let Some((_, segment, span)) = segment fn_trait_expansion: if let Some((_, segment, span)) = segment
&& segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
{ {
@ -1217,13 +1217,12 @@ pub fn prohibit_assoc_item_binding(
// otherwise suggest the removal of the binding. // otherwise suggest the removal of the binding.
if let Some((def_id, segment, _)) = segment if let Some((def_id, segment, _)) = segment
&& segment.args().parenthesized == hir::GenericArgsParentheses::No && segment.args().parenthesized == hir::GenericArgsParentheses::No
&& let hir::TypeBindingKind::Equality { term } = binding.kind && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
{ {
// Suggests removal of the offending binding // Suggests removal of the offending binding
let suggest_removal = |e: &mut Diag<'_>| { let suggest_removal = |e: &mut Diag<'_>| {
let bindings = segment.args().bindings; let constraints = segment.args().constraints;
let args = segment.args().args; let args = segment.args().args;
let binding_span = binding.span;
// Compute the span to remove based on the position // Compute the span to remove based on the position
// of the binding. We do that as follows: // of the binding. We do that as follows:
@ -1236,26 +1235,21 @@ pub fn prohibit_assoc_item_binding(
// the start of the next span or will simply be the // the start of the next span or will simply be the
// span encomassing everything within the generics brackets // span encomassing everything within the generics brackets
let Some(binding_index) = bindings.iter().position(|b| b.hir_id == binding.hir_id) let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else {
else {
bug!("a type binding exists but its HIR ID not found in generics"); bug!("a type binding exists but its HIR ID not found in generics");
}; };
let preceding_span = if binding_index > 0 { let preceding_span = if index > 0 {
Some(bindings[binding_index - 1].span) Some(constraints[index - 1].span)
} else { } else {
args.last().map(|a| a.span()) args.last().map(|a| a.span())
}; };
let next_span = if binding_index < bindings.len() - 1 { let next_span = constraints.get(index + 1).map(|constraint| constraint.span);
Some(bindings[binding_index + 1].span)
} else {
None
};
let removal_span = match (preceding_span, next_span) { let removal_span = match (preceding_span, next_span) {
(Some(prec), _) => binding_span.with_lo(prec.hi()), (Some(prec), _) => constraint.span.with_lo(prec.hi()),
(None, Some(next)) => binding_span.with_hi(next.lo()), (None, Some(next)) => constraint.span.with_hi(next.lo()),
(None, None) => { (None, None) => {
let Some(generics_span) = segment.args().span_ext() else { let Some(generics_span) = segment.args().span_ext() else {
bug!("a type binding exists but generic span is empty"); bug!("a type binding exists but generic span is empty");
@ -1269,7 +1263,7 @@ pub fn prohibit_assoc_item_binding(
if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) { if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
e.span_suggestion_verbose( e.span_suggestion_verbose(
removal_span, removal_span,
"consider removing this type binding", "consider removing this associated item binding",
suggestion, suggestion,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
@ -1281,7 +1275,7 @@ pub fn prohibit_assoc_item_binding(
let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| { let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| {
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) {
e.span_suggestion_verbose( e.span_suggestion_verbose(
binding.span, constraint.span,
format!("to use `{snippet}` as a generic argument specify it directly"), format!("to use `{snippet}` as a generic argument specify it directly"),
snippet, snippet,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
@ -1289,11 +1283,11 @@ pub fn prohibit_assoc_item_binding(
} }
}; };
// Check if the type has a generic param with the // Check if the type has a generic param with the same name
// same name as the assoc type name in type binding // as the assoc type name in the associated item binding.
let generics = tcx.generics_of(def_id); let generics = tcx.generics_of(def_id);
let matching_param = let matching_param =
generics.own_params.iter().find(|p| p.name.as_str() == binding.ident.as_str()); generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str());
// Now emit the appropriate suggestion // Now emit the appropriate suggestion
if let Some(matching_param) = matching_param { if let Some(matching_param) = matching_param {
@ -1322,8 +1316,7 @@ pub(crate) fn fn_trait_to_string(
) -> String { ) -> String {
let args = trait_segment let args = trait_segment
.args .args
.as_ref() .and_then(|args| args.args.first())
.and_then(|args| args.args.get(0))
.and_then(|arg| match arg { .and_then(|arg| match arg {
hir::GenericArg::Type(ty) => match ty.kind { hir::GenericArg::Type(ty) => match ty.kind {
hir::TyKind::Tup(t) => t hir::TyKind::Tup(t) => t
@ -1334,7 +1327,7 @@ pub(crate) fn fn_trait_to_string(
_ => tcx.sess.source_map().span_to_snippet(ty.span), _ => tcx.sess.source_map().span_to_snippet(ty.span),
} }
.map(|s| { .map(|s| {
// `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma // `is_empty()` checks to see if the type is the unit tuple, if so we don't want a comma
if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") } if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") }
}) })
.ok(), .ok(),
@ -1344,20 +1337,17 @@ pub(crate) fn fn_trait_to_string(
let ret = trait_segment let ret = trait_segment
.args() .args()
.bindings .constraints
.iter() .iter()
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) { .find_map(|c| {
(true, hir::TypeBindingKind::Equality { term }) => { if c.ident.name == sym::Output
let span = match term { && let Some(ty) = c.ty()
hir::Term::Ty(ty) => ty.span, && ty.span != tcx.hir().span(trait_segment.hir_id)
hir::Term::Const(c) => tcx.hir().span(c.hir_id), {
}; tcx.sess.source_map().span_to_snippet(ty.span).ok()
} else {
(span != tcx.hir().span(trait_segment.hir_id)) None
.then_some(tcx.sess.source_map().span_to_snippet(span).ok())
.flatten()
} }
_ => None,
}) })
.unwrap_or_else(|| "()".to_string()); .unwrap_or_else(|| "()".to_string());

View File

@ -1,6 +1,6 @@
use super::IsMethodCall; use super::IsMethodCall;
use crate::hir_ty_lowering::{ use crate::hir_ty_lowering::{
errors::prohibit_assoc_item_binding, ExplicitLateBound, GenericArgCountMismatch, errors::prohibit_assoc_item_constraint, ExplicitLateBound, GenericArgCountMismatch,
GenericArgCountResult, GenericArgPosition, GenericArgsLowerer, GenericArgCountResult, GenericArgPosition, GenericArgsLowerer,
}; };
use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs}; use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs};
@ -452,9 +452,9 @@ pub(crate) fn check_generic_arg_count(
(gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params(); (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params();
if gen_pos != GenericArgPosition::Type if gen_pos != GenericArgPosition::Type
&& let Some(b) = gen_args.bindings.first() && let Some(c) = gen_args.constraints.first()
{ {
prohibit_assoc_item_binding(tcx, b, None); prohibit_assoc_item_constraint(tcx, c, None);
} }
let explicit_late_bound = let explicit_late_bound =
@ -566,17 +566,19 @@ pub(crate) fn check_generic_arg_count(
debug!(?gen_args_info); debug!(?gen_args_info);
let reported = WrongNumberOfGenericArgs::new( let reported = gen_args.has_err().unwrap_or_else(|| {
tcx, WrongNumberOfGenericArgs::new(
gen_args_info, tcx,
seg, gen_args_info,
gen_params, seg,
params_offset, gen_params,
gen_args, params_offset,
def_id, gen_args,
) def_id,
.diagnostic() )
.emit_unless(gen_args.has_err()); .diagnostic()
.emit()
});
Err(reported) Err(reported)
}; };

View File

@ -268,8 +268,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) {
let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id); let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id);
if let Some((_, hir::Node::TypeBinding(binding))) = parents.next() if let Some((_, hir::Node::AssocItemConstraint(constraint))) = parents.next()
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(obj_ty) } = binding.kind && let Some(obj_ty) = constraint.ty()
{ {
if let Some((_, hir::Node::TraitRef(..))) = parents.next() if let Some((_, hir::Node::TraitRef(..))) = parents.next()
&& let Some((_, hir::Node::Ty(ty))) = parents.next() && let Some((_, hir::Node::Ty(ty))) = parents.next()
@ -279,10 +279,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
return; return;
} }
let lo = if binding.gen_args.span_ext.is_dummy() { let lo = if constraint.gen_args.span_ext.is_dummy() {
binding.ident.span constraint.ident.span
} else { } else {
binding.gen_args.span_ext constraint.gen_args.span_ext
}; };
let hi = obj_ty.span; let hi = obj_ty.span;

View File

@ -22,7 +22,7 @@ mod object_safety;
use crate::bounds::Bounds; use crate::bounds::Bounds;
use crate::collect::HirPlaceholderCollector; use crate::collect::HirPlaceholderCollector;
use crate::errors::{AmbiguousLifetimeBound, WildPatTy}; use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
use crate::hir_ty_lowering::errors::{prohibit_assoc_item_binding, GenericsArgsErrExtend}; use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
use crate::middle::resolve_bound_vars as rbv; use crate::middle::resolve_bound_vars as rbv;
use crate::require_c_abi_if_c_variadic; use crate::require_c_abi_if_c_variadic;
@ -324,8 +324,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
None, None,
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,
); );
if let Some(b) = item_segment.args().bindings.first() { if let Some(c) = item_segment.args().constraints.first() {
prohibit_assoc_item_binding(self.tcx(), b, Some((def_id, item_segment, span))); prohibit_assoc_item_constraint(self.tcx(), c, Some((def_id, item_segment, span)));
} }
args args
} }
@ -335,7 +335,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// If this is a trait reference, you also need to pass the self type `self_ty`. /// If this is a trait reference, you also need to pass the self type `self_ty`.
/// The lowering process may involve applying defaulted type parameters. /// The lowering process may involve applying defaulted type parameters.
/// ///
/// Associated item bindings are not handled here! /// Associated item constraints are not handled here! They are either lowered via
/// `lower_assoc_item_constraint` or rejected via `prohibit_assoc_item_constraint`.
/// ///
/// ### Example /// ### Example
/// ///
@ -349,7 +350,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// which will have been resolved to a `def_id` /// which will have been resolved to a `def_id`
/// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type
/// parameters are returned in the `GenericArgsRef` /// parameters are returned in the `GenericArgsRef`
/// 4. Associated type bindings like `Output = u32` are contained in `generic_args.bindings`. /// 4. Associated item constraints like `Output = u32` are contained in `generic_args.constraints`.
/// ///
/// Note that the type listing given here is *exactly* what the user provided. /// Note that the type listing given here is *exactly* what the user provided.
/// ///
@ -411,8 +412,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Skip processing if type has no generic parameters. // Skip processing if type has no generic parameters.
// Traits always have `Self` as a generic parameter, which means they will not return early // Traits always have `Self` as a generic parameter, which means they will not return early
// here and so associated type bindings will be handled regardless of whether there are any // here and so associated item constraints will be handled regardless of whether there are
// non-`Self` generic parameters. // any non-`Self` generic parameters.
if generics.is_own_empty() { if generics.is_own_empty() {
return (tcx.mk_args(parent_args), arg_count); return (tcx.mk_args(parent_args), arg_count);
} }
@ -621,8 +622,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
None, None,
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,
); );
if let Some(b) = item_segment.args().bindings.first() { if let Some(c) = item_segment.args().constraints.first() {
prohibit_assoc_item_binding(self.tcx(), b, Some((item_def_id, item_segment, span))); prohibit_assoc_item_constraint(self.tcx(), c, Some((item_def_id, item_segment, span)));
} }
args args
} }
@ -654,13 +655,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// ///
/// *Polymorphic* in the sense that it may bind late-bound vars. /// *Polymorphic* in the sense that it may bind late-bound vars.
/// ///
/// This may generate auxiliary bounds if the trait reference contains associated item bindings. /// This may generate auxiliary bounds iff the trait reference contains associated item constraints.
/// ///
/// ### Example /// ### Example
/// ///
/// Given the trait ref `Iterator<Item = u32>` and the self type `Ty`, this will add the /// Given the trait ref `Iterator<Item = u32>` and the self type `Ty`, this will add the
/// ///
/// 1. *trait predicate* `<Ty as Iterator>` (known as `Foo: Iterator` in surface syntax) and the /// 1. *trait predicate* `<Ty as Iterator>` (known as `Ty: Iterator` in the surface syntax) and the
/// 2. *projection predicate* `<Ty as Iterator>::Item = u32` /// 2. *projection predicate* `<Ty as Iterator>::Item = u32`
/// ///
/// to `bounds`. /// to `bounds`.
@ -714,27 +715,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
debug!(?poly_trait_ref); debug!(?poly_trait_ref);
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
let mut dup_bindings = FxIndexMap::default(); let mut dup_constraints = FxIndexMap::default();
for binding in trait_segment.args().bindings { for constraint in trait_segment.args().constraints {
// Don't register additional associated type bounds for negative bounds, // Don't register any associated item constraints for negative bounds,
// since we should have emitten an error for them earlier, and they will // since we should have emitted an error for them earlier, and they
// not be well-formed! // would not be well-formed!
if polarity != ty::PredicatePolarity::Positive { if polarity != ty::PredicatePolarity::Positive {
assert!( assert!(
self.tcx().dcx().has_errors().is_some(), self.tcx().dcx().has_errors().is_some(),
"negative trait bounds should not have bindings", "negative trait bounds should not have assoc item constraints",
); );
continue; continue;
} }
// Specify type to assert that error was already reported in `Err` case. // Specify type to assert that error was already reported in `Err` case.
let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_binding( let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_constraint(
trait_ref.hir_ref_id, trait_ref.hir_ref_id,
poly_trait_ref, poly_trait_ref,
binding, constraint,
bounds, bounds,
&mut dup_bindings, &mut dup_constraints,
binding.span, constraint.span,
only_self_bounds, only_self_bounds,
); );
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above). // Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
@ -766,8 +767,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some(self_ty), Some(self_ty),
constness, constness,
); );
if let Some(b) = trait_segment.args().bindings.first() { if let Some(c) = trait_segment.args().constraints.first() {
prohibit_assoc_item_binding(self.tcx(), b, Some((trait_def_id, trait_segment, span))); prohibit_assoc_item_constraint(
self.tcx(),
c,
Some((trait_def_id, trait_segment, span)),
);
} }
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args) ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
} }
@ -849,7 +854,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// ///
/// This fails if there is no such bound in the list of candidates or if there are multiple /// This fails if there is no such bound in the list of candidates or if there are multiple
/// candidates in which case it reports ambiguity. /// candidates in which case it reports ambiguity.
#[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)] #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)]
fn probe_single_bound_for_assoc_item<I>( fn probe_single_bound_for_assoc_item<I>(
&self, &self,
all_candidates: impl Fn() -> I, all_candidates: impl Fn() -> I,
@ -858,7 +863,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
assoc_kind: ty::AssocKind, assoc_kind: ty::AssocKind,
assoc_name: Ident, assoc_name: Ident,
span: Span, span: Span,
binding: Option<&hir::TypeBinding<'tcx>>, constraint: Option<&hir::AssocItemConstraint<'tcx>>,
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
where where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>, I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@ -877,7 +882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
assoc_kind, assoc_kind,
assoc_name, assoc_name,
span, span,
binding, constraint,
); );
self.set_tainted_by_errors(reported); self.set_tainted_by_errors(reported);
return Err(reported); return Err(reported);
@ -897,8 +902,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}); });
// Provide a more specific error code index entry for equality bindings. // Provide a more specific error code index entry for equality bindings.
err.code( err.code(
if let Some(binding) = binding if let Some(constraint) = constraint
&& let hir::TypeBindingKind::Equality { .. } = binding.kind && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind
{ {
E0222 E0222
} else { } else {
@ -906,7 +911,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}, },
); );
// FIXME(#97583): Resugar equality bounds to type/const bindings. // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
// FIXME: Turn this into a structured, translateable & more actionable suggestion. // FIXME: Turn this into a structured, translateable & more actionable suggestion.
let mut where_bounds = vec![]; let mut where_bounds = vec![];
for bound in [bound, bound2].into_iter().chain(matching_candidates) { for bound in [bound, bound2].into_iter().chain(matching_candidates) {
@ -921,9 +926,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bound_span, bound_span,
format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),),
); );
if let Some(binding) = binding { if let Some(constraint) = constraint {
match binding.kind { match constraint.kind {
hir::TypeBindingKind::Equality { term } => { hir::AssocItemConstraintKind::Equality { term } => {
let term: ty::Term<'_> = match term { let term: ty::Term<'_> = match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => { hir::Term::Const(ct) => {
@ -937,7 +942,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
)); ));
} }
// FIXME: Provide a suggestion. // FIXME: Provide a suggestion.
hir::TypeBindingKind::Constraint { bounds: _ } => {} hir::AssocItemConstraintKind::Bound { bounds: _ } => {}
} }
} else { } else {
err.span_suggestion_verbose( err.span_suggestion_verbose(
@ -1540,8 +1545,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
for segment in segments { for segment in segments {
// Only emit the first error to avoid overloading the user with error messages. // Only emit the first error to avoid overloading the user with error messages.
if let Some(b) = segment.args().bindings.first() { if let Some(c) = segment.args().constraints.first() {
return Err(prohibit_assoc_item_binding(self.tcx(), b, None)); return Err(prohibit_assoc_item_constraint(self.tcx(), c, None));
} }
} }

View File

@ -489,7 +489,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
.in_definition_order() .in_definition_order()
.filter(|item| item.kind == AssocKind::Type) .filter(|item| item.kind == AssocKind::Type)
.filter(|item| { .filter(|item| {
!self.gen_args.bindings.iter().any(|binding| binding.ident.name == item.name) !self
.gen_args
.constraints
.iter()
.any(|constraint| constraint.ident.name == item.name)
}) })
.map(|item| item.name.to_ident_string()) .map(|item| item.name.to_ident_string())
.collect() .collect()
@ -679,11 +683,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
(last_lt.span().shrink_to_hi(), false) (last_lt.span().shrink_to_hi(), false)
}; };
let has_non_lt_args = self.num_provided_type_or_const_args() != 0; let has_non_lt_args = self.num_provided_type_or_const_args() != 0;
let has_bindings = !self.gen_args.bindings.is_empty(); let has_constraints = !self.gen_args.constraints.is_empty();
let sugg_prefix = if is_first { "" } else { ", " }; let sugg_prefix = if is_first { "" } else { ", " };
let sugg_suffix = let sugg_suffix =
if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" }; if is_first && (has_non_lt_args || has_constraints) { ", " } else { "" };
let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}"); let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
debug!("sugg: {:?}", sugg); debug!("sugg: {:?}", sugg);
@ -741,7 +745,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg_prefix = if is_first { "" } else { ", " }; let sugg_prefix = if is_first { "" } else { ", " };
let sugg_suffix = let sugg_suffix =
if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" }; if is_first && !self.gen_args.constraints.is_empty() { ", " } else { "" };
let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}"); let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
debug!("sugg: {:?}", sugg); debug!("sugg: {:?}", sugg);

View File

@ -89,7 +89,7 @@ impl<'a> State<'a> {
Node::Stmt(a) => self.print_stmt(a), Node::Stmt(a) => self.print_stmt(a),
Node::PathSegment(a) => self.print_path_segment(a), Node::PathSegment(a) => self.print_path_segment(a),
Node::Ty(a) => self.print_type(a), Node::Ty(a) => self.print_type(a),
Node::TypeBinding(a) => self.print_type_binding(a), Node::AssocItemConstraint(a) => self.print_assoc_item_constraint(a),
Node::TraitRef(a) => self.print_trait_ref(a), Node::TraitRef(a) => self.print_trait_ref(a),
Node::Pat(a) => self.print_pat(a), Node::Pat(a) => self.print_pat(a),
Node::PatField(a) => self.print_patfield(a), Node::PatField(a) => self.print_patfield(a),
@ -1135,7 +1135,7 @@ impl<'a> State<'a> {
self.print_ident(segment.ident); self.print_ident(segment.ident);
let generic_args = segment.args(); let generic_args = segment.args();
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { if !generic_args.args.is_empty() || !generic_args.constraints.is_empty() {
self.print_generic_args(generic_args, true); self.print_generic_args(generic_args, true);
} }
@ -1676,9 +1676,9 @@ impl<'a> State<'a> {
}); });
} }
for binding in generic_args.bindings { for constraint in generic_args.constraints {
start_or_comma(self); start_or_comma(self);
self.print_type_binding(binding); self.print_assoc_item_constraint(constraint);
} }
if !empty.get() { if !empty.get() {
@ -1686,13 +1686,15 @@ impl<'a> State<'a> {
} }
} }
hir::GenericArgsParentheses::ParenSugar => { hir::GenericArgsParentheses::ParenSugar => {
let (inputs, output) = generic_args.paren_sugar_inputs_output().unwrap();
self.word("("); self.word("(");
self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty)); self.commasep(Inconsistent, inputs, |s, ty| s.print_type(ty));
self.word(")"); self.word(")");
self.space_if_not_bol(); self.space_if_not_bol();
self.word_space("->"); self.word_space("->");
self.print_type(generic_args.bindings[0].ty()); self.print_type(output);
} }
hir::GenericArgsParentheses::ReturnTypeNotation => { hir::GenericArgsParentheses::ReturnTypeNotation => {
self.word("(..)"); self.word("(..)");
@ -1700,19 +1702,19 @@ impl<'a> State<'a> {
} }
} }
fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) { fn print_assoc_item_constraint(&mut self, constraint: &hir::AssocItemConstraint<'_>) {
self.print_ident(binding.ident); self.print_ident(constraint.ident);
self.print_generic_args(binding.gen_args, false); self.print_generic_args(constraint.gen_args, false);
self.space(); self.space();
match binding.kind { match constraint.kind {
hir::TypeBindingKind::Equality { ref term } => { hir::AssocItemConstraintKind::Equality { ref term } => {
self.word_space("="); self.word_space("=");
match term { match term {
Term::Ty(ty) => self.print_type(ty), Term::Ty(ty) => self.print_type(ty),
Term::Const(ref c) => self.print_anon_const(c), Term::Const(ref c) => self.print_anon_const(c),
} }
} }
hir::TypeBindingKind::Constraint { bounds } => { hir::AssocItemConstraintKind::Bound { bounds } => {
self.print_bounds(":", bounds); self.print_bounds(":", bounds);
} }
} }

View File

@ -848,19 +848,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds && let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds
&& let Some(hir::PathSegment { args: Some(generic_args), .. }) = && let Some(hir::PathSegment { args: Some(generic_args), .. }) =
trait_ref.trait_ref.path.segments.last() trait_ref.trait_ref.path.segments.last()
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args && let [constraint] = generic_args.constraints
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } = && let Some(ty) = constraint.ty()
ty_binding.kind
{ {
// Check if async function's return type was omitted. // Check if async function's return type was omitted.
// Don't emit suggestions if the found type is `impl Future<...>`. // Don't emit suggestions if the found type is `impl Future<...>`.
debug!(?found); debug!(?found);
if found.is_suggestable(self.tcx, false) { if found.is_suggestable(self.tcx, false) {
if term.span.is_empty() { if ty.span.is_empty() {
err.subdiagnostic( err.subdiagnostic(
self.dcx(), self.dcx(),
errors::AddReturnTypeSuggestion::Add { errors::AddReturnTypeSuggestion::Add {
span: term.span, span: ty.span,
found: found.to_string(), found: found.to_string(),
}, },
); );
@ -868,10 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else { } else {
err.subdiagnostic( err.subdiagnostic(
self.dcx(), self.dcx(),
errors::ExpectedReturnTypeLabel::Other { errors::ExpectedReturnTypeLabel::Other { span: ty.span, expected },
span: term.span,
expected,
},
); );
} }
} }

View File

@ -925,7 +925,7 @@ impl<'hir> Map<'hir> {
.with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi())) .with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi()))
} }
Node::Ty(ty) => ty.span, Node::Ty(ty) => ty.span,
Node::TypeBinding(tb) => tb.span, Node::AssocItemConstraint(constraint) => constraint.span,
Node::TraitRef(tr) => tr.path.span, Node::TraitRef(tr) => tr.path.span,
Node::Pat(pat) => pat.span, Node::Pat(pat) => pat.span,
Node::PatField(field) => field.span, Node::PatField(field) => field.span,
@ -1190,7 +1190,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
Node::Stmt(_) => node_str("stmt"), Node::Stmt(_) => node_str("stmt"),
Node::PathSegment(_) => node_str("path segment"), Node::PathSegment(_) => node_str("path segment"),
Node::Ty(_) => node_str("type"), Node::Ty(_) => node_str("type"),
Node::TypeBinding(_) => node_str("type binding"), Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
Node::TraitRef(_) => node_str("trait ref"), Node::TraitRef(_) => node_str("trait ref"),
Node::Pat(_) => node_str("pat"), Node::Pat(_) => node_str("pat"),
Node::PatField(_) => node_str("pattern field"), Node::PatField(_) => node_str("pattern field"),

View File

@ -7,8 +7,8 @@ use ast::token::IdentIsRaw;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::{ use rustc_ast::{
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocConstraint, self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
Path, PathSegment, QSelf, Path, PathSegment, QSelf,
}; };
use rustc_errors::{Applicability, Diag, PResult}; use rustc_errors::{Applicability, Diag, PResult};
@ -720,10 +720,7 @@ impl<'a> Parser<'a> {
)); ));
} }
let kind = if self.eat(&token::Colon) { let kind = if self.eat(&token::Colon) {
// Parse associated type constraint bound. AssocItemConstraintKind::Bound { bounds: self.parse_generic_bounds()? }
let bounds = self.parse_generic_bounds()?;
AssocConstraintKind::Bound { bounds }
} else if self.eat(&token::Eq) { } else if self.eat(&token::Eq) {
self.parse_assoc_equality_term( self.parse_assoc_equality_term(
ident, ident,
@ -735,17 +732,17 @@ impl<'a> Parser<'a> {
}; };
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
if let AssocConstraintKind::Bound { .. } = kind { if let AssocItemConstraintKind::Bound { .. } = kind
if let Some(ast::GenericArgs::Parenthesized(args)) = &gen_args && let Some(ast::GenericArgs::Parenthesized(args)) = &gen_args
&& args.inputs.is_empty() && args.inputs.is_empty()
&& matches!(args.output, ast::FnRetTy::Default(..)) && let ast::FnRetTy::Default(..) = args.output
{ {
self.psess.gated_spans.gate(sym::return_type_notation, span); self.psess.gated_spans.gate(sym::return_type_notation, span);
}
} }
let constraint = let constraint =
AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span }; AssocItemConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
Ok(Some(AngleBracketedArg::Constraint(constraint))) Ok(Some(AngleBracketedArg::Constraint(constraint)))
} else { } else {
// we only want to suggest `:` and `=` in contexts where the previous token // we only want to suggest `:` and `=` in contexts where the previous token
@ -772,7 +769,7 @@ impl<'a> Parser<'a> {
ident: Ident, ident: Ident,
gen_args: Option<&GenericArgs>, gen_args: Option<&GenericArgs>,
eq: Span, eq: Span,
) -> PResult<'a, AssocConstraintKind> { ) -> PResult<'a, AssocItemConstraintKind> {
let arg = self.parse_generic_arg(None)?; let arg = self.parse_generic_arg(None)?;
let span = ident.span.to(self.prev_token.span); let span = ident.span.to(self.prev_token.span);
let term = match arg { let term = match arg {
@ -820,7 +817,7 @@ impl<'a> Parser<'a> {
return Err(err); return Err(err);
} }
}; };
Ok(AssocConstraintKind::Equality { term }) Ok(AssocItemConstraintKind::Equality { term })
} }
/// We do not permit arbitrary expressions as const arguments. They must be one of: /// We do not permit arbitrary expressions as const arguments. They must be one of:
@ -941,7 +938,7 @@ impl<'a> Parser<'a> {
} }
/// Given a arg inside of generics, we try to destructure it as if it were the LHS in /// Given a arg inside of generics, we try to destructure it as if it were the LHS in
/// `LHS = ...`, i.e. an associated type binding. /// `LHS = ...`, i.e. an associated item binding.
/// This returns a bool indicating if there are any `for<'a, 'b>` binder args, the /// This returns a bool indicating if there are any `for<'a, 'b>` binder args, the
/// identifier, and any GAT arguments. /// identifier, and any GAT arguments.
fn get_ident_from_generic_arg( fn get_ident_from_generic_arg(

View File

@ -477,9 +477,9 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_generic_args(self, ga) hir_visit::walk_generic_args(self, ga)
} }
fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding<'v>) { fn visit_assoc_item_constraint(&mut self, constraint: &'v hir::AssocItemConstraint<'v>) {
self.record("TypeBinding", Id::Node(type_binding.hir_id), type_binding); self.record("AssocItemConstraint", Id::Node(constraint.hir_id), constraint);
hir_visit::walk_assoc_type_binding(self, type_binding) hir_visit::walk_assoc_item_constraint(self, constraint)
} }
fn visit_attribute(&mut self, attr: &'v ast::Attribute) { fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
@ -688,7 +688,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
ast_visit::walk_path_segment(self, path_segment) ast_visit::walk_path_segment(self, path_segment)
} }
// `GenericArgs` has one inline use (in `ast::AssocConstraint::gen_args`) and one // `GenericArgs` has one inline use (in `ast::AssocItemConstraint::gen_args`) and one
// non-inline use (in `ast::PathSegment::args`). The latter case is more // non-inline use (in `ast::PathSegment::args`). The latter case is more
// common, so we implement `visit_generic_args` and tolerate the double // common, so we implement `visit_generic_args` and tolerate the double
// counting in the former case. // counting in the former case.

View File

@ -1148,7 +1148,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
self.diag_metadata.currently_processing_generic_args = prev; self.diag_metadata.currently_processing_generic_args = prev;
} }
fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { fn visit_assoc_item_constraint(&mut self, constraint: &'ast AssocItemConstraint) {
self.visit_ident(constraint.ident); self.visit_ident(constraint.ident);
if let Some(ref gen_args) = constraint.gen_args { if let Some(ref gen_args) = constraint.gen_args {
// Forbid anonymous lifetimes in GAT parameters until proper semantics are decided. // Forbid anonymous lifetimes in GAT parameters until proper semantics are decided.
@ -1157,13 +1157,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
}); });
} }
match constraint.kind { match constraint.kind {
AssocConstraintKind::Equality { ref term } => match term { AssocItemConstraintKind::Equality { ref term } => match term {
Term::Ty(ty) => self.visit_ty(ty), Term::Ty(ty) => self.visit_ty(ty),
Term::Const(c) => { Term::Const(c) => {
self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No)) self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No))
} }
}, },
AssocConstraintKind::Bound { ref bounds } => { AssocItemConstraintKind::Bound { ref bounds } => {
self.record_lifetime_params_for_impl_trait(constraint.id); self.record_lifetime_params_for_impl_trait(constraint.id);
walk_list!(self, visit_param_bound, bounds, BoundKind::Bound); walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
} }

View File

@ -508,7 +508,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let ast::AngleBracketedArg::Constraint(constraint) = param else { let ast::AngleBracketedArg::Constraint(constraint) = param else {
continue; continue;
}; };
let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else { let ast::AssocItemConstraintKind::Bound { bounds } = &constraint.kind else {
continue; continue;
}; };
for bound in bounds { for bound in bounds {
@ -3390,11 +3390,11 @@ fn mk_where_bound_predicate(
}; };
let mut segments = ThinVec::from(preceding); let mut segments = ThinVec::from(preceding);
let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint { let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocItemConstraint {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
ident: last.ident, ident: last.ident,
gen_args: None, gen_args: None,
kind: ast::AssocConstraintKind::Equality { kind: ast::AssocItemConstraintKind::Equality {
term: ast::Term::Ty(ast::ptr::P(ast::Ty { term: ast::Term::Ty(ast::ptr::P(ast::Ty {
kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()), kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,

View File

@ -450,7 +450,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
/// When after several dereferencing, the reference satisfies the trait /// When after several dereferencing, the reference satisfies the trait
/// binding. This function provides dereference suggestion for this /// bound. This function provides dereference suggestion for this
/// specific situation. /// specific situation.
fn suggest_dereferences( fn suggest_dereferences(
&self, &self,
@ -777,7 +777,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
/// We tried to apply the bound to an `fn` or closure. Check whether calling it would /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
/// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling /// evaluate to a type that *would* satisfy the trait bound. If it would, suggest calling
/// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`. /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
fn suggest_fn_call( fn suggest_fn_call(
&self, &self,
@ -1240,7 +1240,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let param_env = obligation.param_env; let param_env = obligation.param_env;
// Try to apply the original trait binding obligation by borrowing. // Try to apply the original trait bound by borrowing.
let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>, let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
blacklist: &[DefId]| blacklist: &[DefId]|
-> bool { -> bool {
@ -4903,14 +4903,12 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
// `async fn` should always lower to a single bound... but don't ICE. // `async fn` should always lower to a single bound... but don't ICE.
return None; return None;
}; };
let Some(hir::PathSegment { args: Some(generics), .. }) = let Some(hir::PathSegment { args: Some(args), .. }) = trait_ref.trait_ref.path.segments.last()
trait_ref.trait_ref.path.segments.last()
else { else {
// desugaring to a single path segment for `Future<...>`. // desugaring to a single path segment for `Future<...>`.
return None; return None;
}; };
let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) = let Some(future_output_ty) = args.constraints.first().and_then(|constraint| constraint.ty())
generics.bindings.get(0).map(|binding| binding.kind)
else { else {
// Also should never happen. // Also should never happen.
return None; return None;

View File

@ -11,7 +11,7 @@ use thin_vec::ThinVec;
use crate::clean::{self, simplify, Lifetime}; use crate::clean::{self, simplify, Lifetime};
use crate::clean::{ use crate::clean::{
clean_generic_param_def, clean_middle_ty, clean_predicate, clean_trait_ref_with_bindings, clean_generic_param_def, clean_middle_ty, clean_predicate, clean_trait_ref_with_constraints,
clean_ty_generics, clean_ty_generics,
}; };
use crate::core::DocContext; use crate::core::DocContext;
@ -121,7 +121,7 @@ fn synthesize_auto_trait_impl<'tcx>(
kind: Box::new(clean::ImplItem(Box::new(clean::Impl { kind: Box::new(clean::ImplItem(Box::new(clean::Impl {
safety: hir::Safety::Safe, safety: hir::Safety::Safe,
generics, generics,
trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref, ThinVec::new())), trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())),
for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None), for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None),
items: Vec::new(), items: Vec::new(),
polarity, polarity,

View File

@ -10,7 +10,7 @@ use thin_vec::ThinVec;
use crate::clean; use crate::clean;
use crate::clean::{ use crate::clean::{
clean_middle_assoc_item, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty_generics, clean_middle_assoc_item, clean_middle_ty, clean_trait_ref_with_constraints, clean_ty_generics,
}; };
use crate::core::DocContext; use crate::core::DocContext;
@ -95,7 +95,7 @@ pub(crate) fn synthesize_blanket_impls(
), ),
// FIXME(eddyb) compute both `trait_` and `for_` from // FIXME(eddyb) compute both `trait_` and `for_` from
// the post-inference `trait_ref`, as it's more accurate. // the post-inference `trait_ref`, as it's more accurate.
trait_: Some(clean_trait_ref_with_bindings( trait_: Some(clean_trait_ref_with_constraints(
cx, cx,
ty::Binder::dummy(trait_ref.instantiate_identity()), ty::Binder::dummy(trait_ref.instantiate_identity()),
ThinVec::new(), ThinVec::new(),

View File

@ -20,7 +20,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
use crate::clean::{ use crate::clean::{
self, clean_bound_vars, clean_generics, clean_impl_item, clean_middle_assoc_item, self, clean_bound_vars, clean_generics, clean_impl_item, clean_middle_assoc_item,
clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_bindings, clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_constraints,
clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
AttributesExt, ImplKind, ItemId, Type, AttributesExt, ImplKind, ItemId, Type,
}; };
@ -566,7 +566,7 @@ pub(crate) fn build_impl(
}; };
let polarity = tcx.impl_polarity(did); let polarity = tcx.impl_polarity(did);
let trait_ = associated_trait let trait_ = associated_trait
.map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new())); .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new()));
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret); super::build_deref_target_impls(cx, &trait_items, ret);
} }
@ -688,7 +688,7 @@ fn build_module_items(
name: prim_ty.as_sym(), name: prim_ty.as_sym(),
args: clean::GenericArgs::AngleBracketed { args: clean::GenericArgs::AngleBracketed {
args: Default::default(), args: Default::default(),
bindings: ThinVec::new(), constraints: ThinVec::new(),
}, },
}], }],
}, },

View File

@ -231,10 +231,10 @@ fn clean_generic_bound<'tcx>(
}) })
} }
pub(crate) fn clean_trait_ref_with_bindings<'tcx>( pub(crate) fn clean_trait_ref_with_constraints<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
bindings: ThinVec<TypeBinding>, constraints: ThinVec<AssocItemConstraint>,
) -> Path { ) -> Path {
let kind = cx.tcx.def_kind(trait_ref.def_id()).into(); let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
@ -245,7 +245,7 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
cx, cx,
trait_ref.def_id(), trait_ref.def_id(),
true, true,
bindings, constraints,
trait_ref.map_bound(|tr| tr.args), trait_ref.map_bound(|tr| tr.args),
); );
@ -254,14 +254,14 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
path path
} }
fn clean_poly_trait_ref_with_bindings<'tcx>( fn clean_poly_trait_ref_with_constraints<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>,
bindings: ThinVec<TypeBinding>, constraints: ThinVec<AssocItemConstraint>,
) -> GenericBound { ) -> GenericBound {
GenericBound::TraitBound( GenericBound::TraitBound(
PolyTrait { PolyTrait {
trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings), trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints),
generic_params: clean_bound_vars(poly_trait_ref.bound_vars()), generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
}, },
hir::TraitBoundModifier::None, hir::TraitBoundModifier::None,
@ -395,7 +395,7 @@ fn clean_poly_trait_predicate<'tcx>(
let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref); let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
Some(WherePredicate::BoundPredicate { Some(WherePredicate::BoundPredicate {
ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None, None), ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None, None),
bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())], bounds: vec![clean_poly_trait_ref_with_constraints(cx, poly_trait_ref, ThinVec::new())],
bound_params: Vec::new(), bound_params: Vec::new(),
}) })
} }
@ -481,8 +481,11 @@ fn clean_projection<'tcx>(
return clean_middle_opaque_bounds(cx, bounds); return clean_middle_opaque_bounds(cx, bounds);
} }
let trait_ = let trait_ = clean_trait_ref_with_constraints(
clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new()); cx,
ty.map_bound(|ty| ty.trait_ref(cx.tcx)),
ThinVec::new(),
);
let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None, None); let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None, None);
let self_def_id = if let Some(def_id) = def_id { let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id)) cx.tcx.opt_parent(def_id).or(Some(def_id))
@ -522,7 +525,7 @@ fn projection_to_path_segment<'tcx>(
def_id, def_id,
) )
.into(), .into(),
bindings: Default::default(), constraints: Default::default(),
}, },
} }
} }
@ -1453,8 +1456,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
_ => return true, _ => return true,
} }
match &assoc.args { match &assoc.args {
GenericArgs::AngleBracketed { args, bindings } => { GenericArgs::AngleBracketed { args, constraints } => {
if !bindings.is_empty() if !constraints.is_empty()
|| generics || generics
.params .params
.iter() .iter()
@ -2135,7 +2138,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
let bindings = obj let bindings = obj
.projection_bounds() .projection_bounds()
.map(|pb| TypeBinding { .map(|pb| AssocItemConstraint {
assoc: projection_to_path_segment( assoc: projection_to_path_segment(
pb.map_bound(|pb| { pb.map_bound(|pb| {
pb pb
@ -2149,7 +2152,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
}), }),
cx, cx,
), ),
kind: TypeBindingKind::Equality { kind: AssocItemConstraintKind::Equality {
term: clean_middle_term(pb.map_bound(|pb| pb.term), cx), term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
}, },
}) })
@ -2198,7 +2201,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
def_id, def_id,
) )
.into(), .into(),
bindings: Default::default(), constraints: Default::default(),
}, },
}, },
should_show_cast: false, should_show_cast: false,
@ -2304,14 +2307,14 @@ fn clean_middle_opaque_bounds<'tcx>(
.filter_map(|bound| { .filter_map(|bound| {
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() { if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() { if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
Some(TypeBinding { Some(AssocItemConstraint {
assoc: projection_to_path_segment( assoc: projection_to_path_segment(
// FIXME: This needs to be made resilient for `AliasTerm`s that // FIXME: This needs to be made resilient for `AliasTerm`s that
// are associated consts. // are associated consts.
bound.kind().rebind(proj.projection_term.expect_ty(cx.tcx)), bound.kind().rebind(proj.projection_term.expect_ty(cx.tcx)),
cx, cx,
), ),
kind: TypeBindingKind::Equality { kind: AssocItemConstraintKind::Equality {
term: clean_middle_term(bound.kind().rebind(proj.term), cx), term: clean_middle_term(bound.kind().rebind(proj.term), cx),
}, },
}) })
@ -2324,7 +2327,7 @@ fn clean_middle_opaque_bounds<'tcx>(
}) })
.collect(); .collect();
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings)) Some(clean_poly_trait_ref_with_constraints(cx, trait_ref, bindings))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -2505,11 +2508,12 @@ fn clean_generic_args<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
) -> GenericArgs { ) -> GenericArgs {
// FIXME(return_type_notation): Fix RTN parens rendering // FIXME(return_type_notation): Fix RTN parens rendering
if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() {
let output = clean_ty(generic_args.bindings[0].ty(), cx); let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into();
let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None }; let output = match output.kind {
let inputs = hir::TyKind::Tup(&[]) => None,
generic_args.inputs().iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into(); _ => Some(Box::new(clean_ty(output, cx))),
};
GenericArgs::Parenthesized { inputs, output } GenericArgs::Parenthesized { inputs, output }
} else { } else {
let args = generic_args let args = generic_args
@ -2536,9 +2540,12 @@ fn clean_generic_args<'tcx>(
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into(); .into();
let bindings = let constraints = generic_args
generic_args.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::<ThinVec<_>>(); .constraints
GenericArgs::AngleBracketed { args, bindings } .iter()
.map(|c| clean_assoc_item_constraint(c, cx))
.collect::<ThinVec<_>>();
GenericArgs::AngleBracketed { args, constraints }
} }
} }
@ -3107,20 +3114,20 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
}) })
} }
fn clean_type_binding<'tcx>( fn clean_assoc_item_constraint<'tcx>(
type_binding: &hir::TypeBinding<'tcx>, constraint: &hir::AssocItemConstraint<'tcx>,
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
) -> TypeBinding { ) -> AssocItemConstraint {
TypeBinding { AssocItemConstraint {
assoc: PathSegment { assoc: PathSegment {
name: type_binding.ident.name, name: constraint.ident.name,
args: clean_generic_args(type_binding.gen_args, cx), args: clean_generic_args(constraint.gen_args, cx),
}, },
kind: match type_binding.kind { kind: match constraint.kind {
hir::TypeBindingKind::Equality { ref term } => { hir::AssocItemConstraintKind::Equality { ref term } => {
TypeBindingKind::Equality { term: clean_hir_term(term, cx) } AssocItemConstraintKind::Equality { term: clean_hir_term(term, cx) }
} }
hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint { hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound {
bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(), bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(),
}, },
}, },

View File

@ -90,10 +90,10 @@ pub(crate) fn merge_bounds(
let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
match last.args { match last.args {
PP::AngleBracketed { ref mut bindings, .. } => { PP::AngleBracketed { ref mut constraints, .. } => {
bindings.push(clean::TypeBinding { constraints.push(clean::AssocItemConstraint {
assoc: assoc.clone(), assoc: assoc.clone(),
kind: clean::TypeBindingKind::Equality { term: rhs.clone() }, kind: clean::AssocItemConstraintKind::Equality { term: rhs.clone() },
}); });
} }
PP::Parenthesized { ref mut output, .. } => match output { PP::Parenthesized { ref mut output, .. } => match output {

View File

@ -1626,9 +1626,9 @@ impl Type {
if let Type::ImplTrait(mut v) = self if let Type::ImplTrait(mut v) = self
&& let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop() && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
&& let Some(segment) = trait_.segments.pop() && let Some(segment) = trait_.segments.pop()
&& let GenericArgs::AngleBracketed { mut bindings, .. } = segment.args && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
&& let Some(binding) = bindings.pop() && let Some(constraint) = constraints.pop()
&& let TypeBindingKind::Equality { term } = binding.kind && let AssocItemConstraintKind::Equality { term } = constraint.kind
&& let Term::Type(ty) = term && let Term::Type(ty) = term
{ {
ty ty
@ -2260,34 +2260,38 @@ impl GenericArg {
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) enum GenericArgs { pub(crate) enum GenericArgs {
AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec<TypeBinding> }, AngleBracketed { args: Box<[GenericArg]>, constraints: ThinVec<AssocItemConstraint> },
Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> }, Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> },
} }
impl GenericArgs { impl GenericArgs {
pub(crate) fn is_empty(&self) -> bool { pub(crate) fn is_empty(&self) -> bool {
match self { match self {
GenericArgs::AngleBracketed { args, bindings } => { GenericArgs::AngleBracketed { args, constraints } => {
args.is_empty() && bindings.is_empty() args.is_empty() && constraints.is_empty()
} }
GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(), GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
} }
} }
pub(crate) fn bindings<'a>(&'a self) -> Box<dyn Iterator<Item = TypeBinding> + 'a> { pub(crate) fn constraints<'a>(&'a self) -> Box<dyn Iterator<Item = AssocItemConstraint> + 'a> {
match self { match self {
GenericArgs::AngleBracketed { bindings, .. } => Box::new(bindings.iter().cloned()), GenericArgs::AngleBracketed { constraints, .. } => {
Box::new(constraints.iter().cloned())
}
GenericArgs::Parenthesized { output, .. } => Box::new( GenericArgs::Parenthesized { output, .. } => Box::new(
output output
.as_ref() .as_ref()
.map(|ty| TypeBinding { .map(|ty| AssocItemConstraint {
assoc: PathSegment { assoc: PathSegment {
name: sym::Output, name: sym::Output,
args: GenericArgs::AngleBracketed { args: GenericArgs::AngleBracketed {
args: Vec::new().into_boxed_slice(), args: Vec::new().into_boxed_slice(),
bindings: ThinVec::new(), constraints: ThinVec::new(),
}, },
}, },
kind: TypeBindingKind::Equality { term: Term::Type((**ty).clone()) }, kind: AssocItemConstraintKind::Equality {
term: Term::Type((**ty).clone()),
},
}) })
.into_iter(), .into_iter(),
), ),
@ -2546,18 +2550,27 @@ pub(crate) struct ProcMacro {
pub(crate) helpers: Vec<Symbol>, pub(crate) helpers: Vec<Symbol>,
} }
/// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or /// A constraint on an associated item.
/// `A: Send + Sync` in `Foo<A: Send + Sync>`). ///
/// ### Examples
///
/// * the `A = Ty` and `B = Ty` in `Trait<A = Ty, B = Ty>`
/// * the `G<Ty> = Ty` in `Trait<G<Ty> = Ty>`
/// * the `A: Bound` in `Trait<A: Bound>`
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct TypeBinding { pub(crate) struct AssocItemConstraint {
pub(crate) assoc: PathSegment, pub(crate) assoc: PathSegment,
pub(crate) kind: TypeBindingKind, pub(crate) kind: AssocItemConstraintKind,
} }
/// The kind of [associated item constraint][AssocItemConstraint].
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) enum TypeBindingKind { pub(crate) enum AssocItemConstraintKind {
Equality { term: Term }, Equality { term: Term },
Constraint { bounds: Vec<GenericBound> }, Bound { bounds: Vec<GenericBound> },
} }
// Some nodes are used a lot. Make sure they don't unintentionally get bigger. // Some nodes are used a lot. Make sure they don't unintentionally get bigger.

View File

@ -2,9 +2,10 @@ use crate::clean::auto_trait::synthesize_auto_trait_impls;
use crate::clean::blanket_impl::synthesize_blanket_impls; use crate::clean::blanket_impl::synthesize_blanket_impls;
use crate::clean::render_macro_matchers::render_macro_matcher; use crate::clean::render_macro_matchers::render_macro_matcher;
use crate::clean::{ use crate::clean::{
clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate, clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline,
ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, AssocItemConstraint, AssocItemConstraintKind, Crate, ExternalCrate, Generic, GenericArg,
PathSegment, Primitive, PrimitiveType, Term, Type, TypeBinding, TypeBindingKind, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, PathSegment, Primitive,
PrimitiveType, Term, Type,
}; };
use crate::core::DocContext; use crate::core::DocContext;
use crate::html::format::visibility_to_src_with_space; use crate::html::format::visibility_to_src_with_space;
@ -200,11 +201,11 @@ fn can_elide_generic_arg<'tcx>(
actual.skip_binder() == default.skip_binder() actual.skip_binder() == default.skip_binder()
} }
fn clean_middle_generic_args_with_bindings<'tcx>( fn clean_middle_generic_args_with_constraints<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
did: DefId, did: DefId,
has_self: bool, has_self: bool,
bindings: ThinVec<TypeBinding>, constraints: ThinVec<AssocItemConstraint>,
ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> GenericArgs { ) -> GenericArgs {
let args = clean_middle_generic_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did); let args = clean_middle_generic_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did);
@ -219,17 +220,19 @@ fn clean_middle_generic_args_with_bindings<'tcx>(
// The trait's first substitution is the one after self, if there is one. // The trait's first substitution is the one after self, if there is one.
match ty.skip_binder().kind() { match ty.skip_binder().kind() {
ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None, None)).collect::<Vec<_>>().into(), ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None, None)).collect::<Vec<_>>().into(),
_ => return GenericArgs::AngleBracketed { args: args.into(), bindings }, _ => return GenericArgs::AngleBracketed { args: args.into(), constraints },
}; };
let output = bindings.into_iter().next().and_then(|binding| match binding.kind { let output = constraints.into_iter().next().and_then(|binding| match binding.kind {
TypeBindingKind::Equality { term: Term::Type(ty) } if ty != Type::Tuple(Vec::new()) => { AssocItemConstraintKind::Equality { term: Term::Type(ty) }
if ty != Type::Tuple(Vec::new()) =>
{
Some(Box::new(ty)) Some(Box::new(ty))
} }
_ => None, _ => None,
}); });
GenericArgs::Parenthesized { inputs, output } GenericArgs::Parenthesized { inputs, output }
} else { } else {
GenericArgs::AngleBracketed { args: args.into(), bindings } GenericArgs::AngleBracketed { args: args.into(), constraints }
} }
} }
@ -237,7 +240,7 @@ pub(super) fn clean_middle_path<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
did: DefId, did: DefId,
has_self: bool, has_self: bool,
bindings: ThinVec<TypeBinding>, constraints: ThinVec<AssocItemConstraint>,
args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> Path { ) -> Path {
let def_kind = cx.tcx.def_kind(did); let def_kind = cx.tcx.def_kind(did);
@ -246,7 +249,7 @@ pub(super) fn clean_middle_path<'tcx>(
res: Res::Def(def_kind, did), res: Res::Def(def_kind, did),
segments: thin_vec![PathSegment { segments: thin_vec![PathSegment {
name, name,
args: clean_middle_generic_args_with_bindings(cx, did, has_self, bindings, args), args: clean_middle_generic_args_with_constraints(cx, did, has_self, constraints, args),
}], }],
} }
} }

View File

@ -420,8 +420,8 @@ impl clean::GenericArgs {
fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> { fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
display_fn(move |f| { display_fn(move |f| {
match self { match self {
clean::GenericArgs::AngleBracketed { args, bindings } => { clean::GenericArgs::AngleBracketed { args, constraints } => {
if !args.is_empty() || !bindings.is_empty() { if !args.is_empty() || !constraints.is_empty() {
if f.alternate() { if f.alternate() {
f.write_str("<")?; f.write_str("<")?;
} else { } else {
@ -439,15 +439,15 @@ impl clean::GenericArgs {
write!(f, "{}", arg.print(cx))?; write!(f, "{}", arg.print(cx))?;
} }
} }
for binding in bindings.iter() { for constraint in constraints.iter() {
if comma { if comma {
f.write_str(", ")?; f.write_str(", ")?;
} }
comma = true; comma = true;
if f.alternate() { if f.alternate() {
write!(f, "{:#}", binding.print(cx))?; write!(f, "{:#}", constraint.print(cx))?;
} else { } else {
write!(f, "{}", binding.print(cx))?; write!(f, "{}", constraint.print(cx))?;
} }
} }
if f.alternate() { if f.alternate() {
@ -1706,7 +1706,7 @@ impl clean::ImportSource {
} }
} }
impl clean::TypeBinding { impl clean::AssocItemConstraint {
pub(crate) fn print<'a, 'tcx: 'a>( pub(crate) fn print<'a, 'tcx: 'a>(
&'a self, &'a self,
cx: &'a Context<'tcx>, cx: &'a Context<'tcx>,
@ -1715,11 +1715,11 @@ impl clean::TypeBinding {
f.write_str(self.assoc.name.as_str())?; f.write_str(self.assoc.name.as_str())?;
self.assoc.args.print(cx).fmt(f)?; self.assoc.args.print(cx).fmt(f)?;
match self.kind { match self.kind {
clean::TypeBindingKind::Equality { ref term } => { clean::AssocItemConstraintKind::Equality { ref term } => {
f.write_str(" = ")?; f.write_str(" = ")?;
term.print(cx).fmt(f)?; term.print(cx).fmt(f)?;
} }
clean::TypeBindingKind::Constraint { ref bounds } => { clean::AssocItemConstraintKind::Bound { ref bounds } => {
if !bounds.is_empty() { if !bounds.is_empty() {
f.write_str(": ")?; f.write_str(": ")?;
print_generic_bounds(bounds, cx).fmt(f)?; print_generic_bounds(bounds, cx).fmt(f)?;

View File

@ -727,7 +727,7 @@ pub(crate) fn get_function_type_for_search<'tcx>(
name: *name, name: *name,
args: clean::GenericArgs::AngleBracketed { args: clean::GenericArgs::AngleBracketed {
args: Vec::new().into_boxed_slice(), args: Vec::new().into_boxed_slice(),
bindings: ThinVec::new(), constraints: ThinVec::new(),
}, },
}) })
.collect(), .collect(),
@ -1049,7 +1049,7 @@ fn simplify_fn_type<'tcx, 'a>(
// So in here, we can add it directly and look for its own type parameters (so for `Option`, // So in here, we can add it directly and look for its own type parameters (so for `Option`,
// we will look for them but not for `T`). // we will look for them but not for `T`).
let mut ty_generics = Vec::new(); let mut ty_generics = Vec::new();
let mut ty_bindings = Vec::new(); let mut ty_constraints = Vec::new();
if let Some(arg_generics) = arg.generic_args() { if let Some(arg_generics) = arg.generic_args() {
for ty in arg_generics.into_iter().filter_map(|gen| match gen { for ty in arg_generics.into_iter().filter_map(|gen| match gen {
clean::GenericArg::Type(ty) => Some(ty), clean::GenericArg::Type(ty) => Some(ty),
@ -1067,14 +1067,14 @@ fn simplify_fn_type<'tcx, 'a>(
cache, cache,
); );
} }
for binding in arg_generics.bindings() { for constraint in arg_generics.constraints() {
simplify_fn_binding( simplify_fn_constraint(
self_, self_,
generics, generics,
&binding, &constraint,
tcx, tcx,
recurse + 1, recurse + 1,
&mut ty_bindings, &mut ty_constraints,
rgen, rgen,
is_return, is_return,
cache, cache,
@ -1137,7 +1137,7 @@ fn simplify_fn_type<'tcx, 'a>(
*stored_bounds = type_bounds; *stored_bounds = type_bounds;
} }
} }
ty_bindings.push(( ty_constraints.push((
RenderTypeId::AssociatedType(name), RenderTypeId::AssociatedType(name),
vec![RenderType { vec![RenderType {
id: Some(RenderTypeId::Index(idx)), id: Some(RenderTypeId::Index(idx)),
@ -1152,17 +1152,17 @@ fn simplify_fn_type<'tcx, 'a>(
if id.is_some() || !ty_generics.is_empty() { if id.is_some() || !ty_generics.is_empty() {
res.push(RenderType { res.push(RenderType {
id, id,
bindings: if ty_bindings.is_empty() { None } else { Some(ty_bindings) }, bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
}); });
} }
} }
} }
fn simplify_fn_binding<'tcx, 'a>( fn simplify_fn_constraint<'tcx, 'a>(
self_: Option<&'a Type>, self_: Option<&'a Type>,
generics: &Generics, generics: &Generics,
binding: &'a clean::TypeBinding, constraint: &'a clean::AssocItemConstraint,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
recurse: usize, recurse: usize,
res: &mut Vec<(RenderTypeId, Vec<RenderType>)>, res: &mut Vec<(RenderTypeId, Vec<RenderType>)>,
@ -1170,9 +1170,9 @@ fn simplify_fn_binding<'tcx, 'a>(
is_return: bool, is_return: bool,
cache: &Cache, cache: &Cache,
) { ) {
let mut ty_binding_constraints = Vec::new(); let mut ty_constraints = Vec::new();
let ty_binding_assoc = RenderTypeId::AssociatedType(binding.assoc.name); let ty_constrained_assoc = RenderTypeId::AssociatedType(constraint.assoc.name);
for gen in &binding.assoc.args { for gen in &constraint.assoc.args {
match gen { match gen {
clean::GenericArg::Type(arg) => simplify_fn_type( clean::GenericArg::Type(arg) => simplify_fn_type(
self_, self_,
@ -1180,7 +1180,7 @@ fn simplify_fn_binding<'tcx, 'a>(
&arg, &arg,
tcx, tcx,
recurse + 1, recurse + 1,
&mut ty_binding_constraints, &mut ty_constraints,
rgen, rgen,
is_return, is_return,
cache, cache,
@ -1190,11 +1190,11 @@ fn simplify_fn_binding<'tcx, 'a>(
| clean::GenericArg::Infer => {} | clean::GenericArg::Infer => {}
} }
} }
for binding in binding.assoc.args.bindings() { for constraint in constraint.assoc.args.constraints() {
simplify_fn_binding( simplify_fn_constraint(
self_, self_,
generics, generics,
&binding, &constraint,
tcx, tcx,
recurse + 1, recurse + 1,
res, res,
@ -1203,8 +1203,8 @@ fn simplify_fn_binding<'tcx, 'a>(
cache, cache,
); );
} }
match &binding.kind { match &constraint.kind {
clean::TypeBindingKind::Equality { term } => { clean::AssocItemConstraintKind::Equality { term } => {
if let clean::Term::Type(arg) = &term { if let clean::Term::Type(arg) = &term {
simplify_fn_type( simplify_fn_type(
self_, self_,
@ -1212,14 +1212,14 @@ fn simplify_fn_binding<'tcx, 'a>(
arg, arg,
tcx, tcx,
recurse + 1, recurse + 1,
&mut ty_binding_constraints, &mut ty_constraints,
rgen, rgen,
is_return, is_return,
cache, cache,
); );
} }
} }
clean::TypeBindingKind::Constraint { bounds } => { clean::AssocItemConstraintKind::Bound { bounds } => {
for bound in &bounds[..] { for bound in &bounds[..] {
if let Some(path) = bound.get_trait_path() { if let Some(path) = bound.get_trait_path() {
let ty = Type::Path { path }; let ty = Type::Path { path };
@ -1229,7 +1229,7 @@ fn simplify_fn_binding<'tcx, 'a>(
&ty, &ty,
tcx, tcx,
recurse + 1, recurse + 1,
&mut ty_binding_constraints, &mut ty_constraints,
rgen, rgen,
is_return, is_return,
cache, cache,
@ -1238,7 +1238,7 @@ fn simplify_fn_binding<'tcx, 'a>(
} }
} }
} }
res.push((ty_binding_assoc, ty_binding_constraints)); res.push((ty_constrained_assoc, ty_constraints));
} }
/// Return the full list of types when bounds have been resolved. /// Return the full list of types when bounds have been resolved.

View File

@ -153,9 +153,9 @@ impl FromWithTcx<clean::GenericArgs> for GenericArgs {
fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self { fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
use clean::GenericArgs::*; use clean::GenericArgs::*;
match args { match args {
AngleBracketed { args, bindings } => GenericArgs::AngleBracketed { AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
args: args.into_vec().into_tcx(tcx), args: args.into_vec().into_tcx(tcx),
bindings: bindings.into_tcx(tcx), bindings: constraints.into_tcx(tcx),
}, },
Parenthesized { inputs, output } => GenericArgs::Parenthesized { Parenthesized { inputs, output } => GenericArgs::Parenthesized {
inputs: inputs.into_vec().into_tcx(tcx), inputs: inputs.into_vec().into_tcx(tcx),
@ -187,22 +187,22 @@ impl FromWithTcx<clean::Constant> for Constant {
} }
} }
impl FromWithTcx<clean::TypeBinding> for TypeBinding { impl FromWithTcx<clean::AssocItemConstraint> for TypeBinding {
fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self { fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self {
TypeBinding { TypeBinding {
name: binding.assoc.name.to_string(), name: constraint.assoc.name.to_string(),
args: binding.assoc.args.into_tcx(tcx), args: constraint.assoc.args.into_tcx(tcx),
binding: binding.kind.into_tcx(tcx), binding: constraint.kind.into_tcx(tcx),
} }
} }
} }
impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind { impl FromWithTcx<clean::AssocItemConstraintKind> for TypeBindingKind {
fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self { fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self {
use clean::TypeBindingKind::*; use clean::AssocItemConstraintKind::*;
match kind { match kind {
Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)), Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
Constraint { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)), Bound { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)),
} }
} }
} }

View File

@ -3,7 +3,7 @@ use clippy_utils::source::snippet;
use rustc_errors::{Applicability, SuggestionStyle}; use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{ use rustc_hir::{
GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, TypeBinding, GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, AssocItemConstraint,
WherePredicate, WherePredicate,
}; };
use rustc_hir_analysis::lower_ty; use rustc_hir_analysis::lower_ty;
@ -54,9 +54,9 @@ fn emit_lint(
poly_trait: &rustc_hir::PolyTraitRef<'_>, poly_trait: &rustc_hir::PolyTraitRef<'_>,
bounds: GenericBounds<'_>, bounds: GenericBounds<'_>,
index: usize, index: usize,
// The bindings that were implied, used for suggestion purposes since removing a bound with associated types // The constraints that were implied, used for suggestion purposes since removing a bound with
// means we might need to then move it to a different bound // associated types means we might need to then move it to a different bound.
implied_bindings: &[TypeBinding<'_>], implied_constraints: &[AssocItemConstraint<'_>],
bound: &ImplTraitBound<'_>, bound: &ImplTraitBound<'_>,
) { ) {
let implied_by = snippet(cx, bound.span, ".."); let implied_by = snippet(cx, bound.span, "..");
@ -83,29 +83,29 @@ fn emit_lint(
let mut sugg = vec![(implied_span_extended, String::new())]; let mut sugg = vec![(implied_span_extended, String::new())];
// We also might need to include associated type binding that were specified in the implied bound, // We also might need to include associated item constraints that were specified in the implied bound,
// but omitted in the implied-by bound: // but omitted in the implied-by bound:
// `fn f() -> impl Deref<Target = u8> + DerefMut` // `fn f() -> impl Deref<Target = u8> + DerefMut`
// If we're going to suggest removing `Deref<..>`, we'll need to put `<Target = u8>` on `DerefMut` // If we're going to suggest removing `Deref<..>`, we'll need to put `<Target = u8>` on `DerefMut`
let omitted_assoc_tys: Vec<_> = implied_bindings let omitted_constraints: Vec<_> = implied_constraints
.iter() .iter()
.filter(|binding| !bound.bindings.iter().any(|b| b.ident == binding.ident)) .filter(|constraint| !bound.constraints.iter().any(|c| c.ident == constraint.ident))
.collect(); .collect();
if !omitted_assoc_tys.is_empty() { if !omitted_constraints.is_empty() {
// `<>` needs to be added if there aren't yet any generic arguments or bindings // `<>` needs to be added if there aren't yet any generic arguments or constraints
let needs_angle_brackets = bound.args.is_empty() && bound.bindings.is_empty(); let needs_angle_brackets = bound.args.is_empty() && bound.constraints.is_empty();
let insert_span = match (bound.args, bound.bindings) { let insert_span = match (bound.args, bound.constraints) {
([.., arg], [.., binding]) => arg.span().max(binding.span).shrink_to_hi(), ([.., arg], [.., constraint]) => arg.span().max(constraint.span).shrink_to_hi(),
([.., arg], []) => arg.span().shrink_to_hi(), ([.., arg], []) => arg.span().shrink_to_hi(),
([], [.., binding]) => binding.span.shrink_to_hi(), ([], [.., constraint]) => constraint.span.shrink_to_hi(),
([], []) => bound.span.shrink_to_hi(), ([], []) => bound.span.shrink_to_hi(),
}; };
let mut associated_tys_sugg = if needs_angle_brackets { let mut constraints_sugg = if needs_angle_brackets {
"<".to_owned() "<".to_owned()
} else { } else {
// If angle brackets aren't needed (i.e., there are already generic arguments or bindings), // If angle brackets aren't needed (i.e., there are already generic arguments or constraints),
// we need to add a comma: // we need to add a comma:
// `impl A<B, C >` // `impl A<B, C >`
// ^ if we insert `Assoc=i32` without a comma here, that'd be invalid syntax: // ^ if we insert `Assoc=i32` without a comma here, that'd be invalid syntax:
@ -113,16 +113,16 @@ fn emit_lint(
", ".to_owned() ", ".to_owned()
}; };
for (index, binding) in omitted_assoc_tys.into_iter().enumerate() { for (index, constraint) in omitted_constraints.into_iter().enumerate() {
if index > 0 { if index > 0 {
associated_tys_sugg += ", "; constraints_sugg += ", ";
} }
associated_tys_sugg += &snippet(cx, binding.span, ".."); constraints_sugg += &snippet(cx, constraint.span, "..");
} }
if needs_angle_brackets { if needs_angle_brackets {
associated_tys_sugg += ">"; constraints_sugg += ">";
} }
sugg.push((insert_span, associated_tys_sugg)); sugg.push((insert_span, constraints_sugg));
} }
diag.multipart_suggestion_with_style( diag.multipart_suggestion_with_style(
@ -229,8 +229,8 @@ struct ImplTraitBound<'tcx> {
trait_def_id: DefId, trait_def_id: DefId,
/// The generic arguments on the `impl Trait` bound /// The generic arguments on the `impl Trait` bound
args: &'tcx [GenericArg<'tcx>], args: &'tcx [GenericArg<'tcx>],
/// The associated types on this bound /// The associated item constraints of this bound
bindings: &'tcx [TypeBinding<'tcx>], constraints: &'tcx [AssocItemConstraint<'tcx>],
} }
/// Given an `impl Trait` type, gets all the supertraits from each bound ("implied bounds"). /// Given an `impl Trait` type, gets all the supertraits from each bound ("implied bounds").
@ -253,7 +253,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds
Some(ImplTraitBound { Some(ImplTraitBound {
predicates, predicates,
args: path.args.map_or([].as_slice(), |p| p.args), args: path.args.map_or([].as_slice(), |p| p.args),
bindings: path.args.map_or([].as_slice(), |p| p.bindings), constraints: path.args.map_or([].as_slice(), |p| p.constraints),
trait_def_id, trait_def_id,
span: bound.span(), span: bound.span(),
}) })
@ -310,20 +310,20 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) {
if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound
&& let [.., path] = poly_trait.trait_ref.path.segments && let [.., path] = poly_trait.trait_ref.path.segments
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args) && let implied_args = path.args.map_or([].as_slice(), |a| a.args)
&& let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings) && let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints)
&& let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id() && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id()
&& let Some(bound) = find_bound_in_supertraits(cx, def_id, implied_args, &supertraits) && let Some(bound) = find_bound_in_supertraits(cx, def_id, implied_args, &supertraits)
// If the implied bound has a type binding that also exists in the implied-by trait, // If the implied bound has a type binding that also exists in the implied-by trait,
// then we shouldn't lint. See #11880 for an example. // then we shouldn't lint. See #11880 for an example.
&& let assocs = cx.tcx.associated_items(bound.trait_def_id) && let assocs = cx.tcx.associated_items(bound.trait_def_id)
&& !implied_bindings.iter().any(|binding| { && !implied_constraints.iter().any(|constraint| {
assocs assocs
.filter_by_name_unhygienic(binding.ident.name) .filter_by_name_unhygienic(constraint.ident.name)
.next() .next()
.is_some_and(|assoc| assoc.kind == ty::AssocKind::Type) .is_some_and(|assoc| assoc.kind == ty::AssocKind::Type)
}) })
{ {
emit_lint(cx, poly_trait, bounds, index, implied_bindings, bound); emit_lint(cx, poly_trait, bounds, index, implied_constraints, bound);
} }
} }
} }

View File

@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_hir::{ use rustc_hir::{
AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath, ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath,
TraitItemRef, TyKind, TypeBindingKind, TraitItemRef, TyKind,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@ -307,17 +307,12 @@ fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&
&& let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds && let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds
&& let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(segment) = trait_ref.trait_ref.path.segments.last()
&& let Some(generic_args) = segment.args && let Some(generic_args) = segment.args
&& generic_args.bindings.len() == 1 && let [constraint] = generic_args.constraints
&& let TypeBindingKind::Equality { && let Some(ty) = constraint.ty()
term: && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
rustc_hir::Term::Ty(rustc_hir::Ty { && let [segment] = path.segments
kind: TyKind::Path(QPath::Resolved(_, path)),
..
}),
} = &generic_args.bindings[0].kind
&& path.segments.len() == 1
{ {
return Some(&path.segments[0]); return Some(segment);
} }
None None

View File

@ -4,8 +4,7 @@ use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{ use rustc_hir::{
Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, TraitRef, Ty, TyKind,
TypeBindingKind,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
@ -138,10 +137,9 @@ fn future_trait_ref<'tcx>(
fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> { fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> {
if let Some(segment) = trait_ref.path.segments.last() if let Some(segment) = trait_ref.path.segments.last()
&& let Some(args) = segment.args && let Some(args) = segment.args
&& args.bindings.len() == 1 && let [constraint] = args.constraints
&& let binding = &args.bindings[0] && constraint.ident.name == sym::Output
&& binding.ident.name == sym::Output && let Some(output) = constraint.ty()
&& let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind
{ {
return Some(output); return Some(output);
} }

View File

@ -108,7 +108,7 @@ pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool {
pub fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool { pub fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool {
match (l, r) { match (l, r) {
(AngleBracketedArg::Arg(l), AngleBracketedArg::Arg(r)) => eq_generic_arg(l, r), (AngleBracketedArg::Arg(l), AngleBracketedArg::Arg(r)) => eq_generic_arg(l, r),
(AngleBracketedArg::Constraint(l), AngleBracketedArg::Constraint(r)) => eq_assoc_constraint(l, r), (AngleBracketedArg::Constraint(l), AngleBracketedArg::Constraint(r)) => eq_assoc_item_constraint(l, r),
_ => false, _ => false,
} }
} }
@ -802,8 +802,8 @@ fn eq_term(l: &Term, r: &Term) -> bool {
} }
} }
pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { pub fn eq_assoc_item_constraint(l: &AssocItemConstraint, r: &AssocItemConstraint) -> bool {
use AssocConstraintKind::*; use AssocItemConstraintKind::*;
eq_id(l.ident, r.ident) eq_id(l.ident, r.ident)
&& match (&l.kind, &r.kind) { && match (&l.kind, &r.kind) {
(Equality { term: l }, Equality { term: r }) => eq_term(l, r), (Equality { term: l }, Equality { term: r }) => eq_term(l, r),

View File

@ -9,7 +9,7 @@ use rustc_hir::MatchSource::TryDesugar;
use rustc_hir::{ use rustc_hir::{
ArrayLen, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, ArrayLen, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, AssocItemConstraint,
}; };
use rustc_lexer::{tokenize, TokenKind}; use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -486,7 +486,7 @@ impl HirEqInterExpr<'_, '_, '_> {
fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool { fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool {
if left.parenthesized == right.parenthesized { if left.parenthesized == right.parenthesized {
over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
&& over(left.bindings, right.bindings, |l, r| self.eq_type_binding(l, r)) && over(left.constraints, right.constraints, |l, r| self.eq_assoc_type_binding(l, r))
} else { } else {
false false
} }
@ -518,8 +518,8 @@ impl HirEqInterExpr<'_, '_, '_> {
} }
} }
fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool { fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool {
left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty()) left.ident.name == right.ident.name && self.eq_ty(left.ty().expect("expected assoc type binding"), right.ty().expect("expected assoc type binding"))
} }
fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool { fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {

View File

@ -140,7 +140,7 @@ pub(crate) enum SegmentParam<'a> {
Const(&'a ast::AnonConst), Const(&'a ast::AnonConst),
LifeTime(&'a ast::Lifetime), LifeTime(&'a ast::Lifetime),
Type(&'a ast::Ty), Type(&'a ast::Ty),
Binding(&'a ast::AssocConstraint), Binding(&'a ast::AssocItemConstraint),
} }
impl<'a> SegmentParam<'a> { impl<'a> SegmentParam<'a> {
@ -175,9 +175,9 @@ impl<'a> Rewrite for SegmentParam<'a> {
} }
} }
impl Rewrite for ast::AssocConstraint { impl Rewrite for ast::AssocItemConstraint {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
use ast::AssocConstraintKind::{Bound, Equality}; use ast::AssocItemConstraintKind::{Bound, Equality};
let mut result = String::with_capacity(128); let mut result = String::with_capacity(128);
result.push_str(rewrite_ident(context, self.ident)); result.push_str(rewrite_ident(context, self.ident));
@ -205,14 +205,14 @@ impl Rewrite for ast::AssocConstraint {
} }
} }
impl Rewrite for ast::AssocConstraintKind { impl Rewrite for ast::AssocItemConstraintKind {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match self { match self {
ast::AssocConstraintKind::Equality { term } => match term { ast::AssocItemConstraintKind::Equality { term } => match term {
Term::Ty(ty) => ty.rewrite(context, shape), Term::Ty(ty) => ty.rewrite(context, shape),
Term::Const(c) => c.rewrite(context, shape), Term::Const(c) => c.rewrite(context, shape),
}, },
ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), ast::AssocItemConstraintKind::Bound { bounds } => bounds.rewrite(context, shape),
} }
} }
} }

View File

@ -2,8 +2,8 @@
trait T { trait T {
type A: S<C<X = 0i32> = 34>; type A: S<C<X = 0i32> = 34>;
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }
trait S { trait S {

View File

@ -1,22 +1,22 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/invalid_associated_const.rs:4:17 --> $DIR/invalid_associated_const.rs:4:17
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ~~~~~~~~~~ | ~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/invalid_associated_const.rs:4:17 --> $DIR/invalid_associated_const.rs:4:17
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ~~~~~~~~~~ | ~~~~~~~~~~

View File

@ -5,8 +5,8 @@
trait T { trait T {
type A: S<C<X = 0i32> = 34>; type A: S<C<X = 0i32> = 34>;
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }
trait S { trait S {

View File

@ -1,22 +1,22 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102467.rs:7:17 --> $DIR/issue-102467.rs:7:17
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ~~~~~~~~~~ | ~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102467.rs:7:17 --> $DIR/issue-102467.rs:7:17
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ~~~~~~~~~~ | ~~~~~~~~~~

View File

@ -2,8 +2,8 @@
trait T { trait T {
type A: S<C<X = 0i32> = 34>; type A: S<C<X = 0i32> = 34>;
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }
trait S { trait S {

View File

@ -1,22 +1,22 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-const.rs:4:17 --> $DIR/issue-102335-const.rs:4:17
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ~~~~~~~~~~ | ~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-const.rs:4:17 --> $DIR/issue-102335-const.rs:4:17
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<X = 0i32> = 34>; LL | type A: S<C<X = 0i32> = 34>;
| ~~~~~~~~~~ | ~~~~~~~~~~

View File

@ -1,13 +1,13 @@
trait T { trait T {
type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }
trait T2 { trait T2 {
type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }
trait Q {} trait Q {}

View File

@ -1,45 +1,45 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-ty.rs:2:17 --> $DIR/issue-102335-ty.rs:2:17
| |
LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
| ^^^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
| ~~~~~~~~~~~ | ~~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-ty.rs:2:17 --> $DIR/issue-102335-ty.rs:2:17
| |
LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
| ^^^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint LL | type A: S<C<i32 = u32> = ()>; // Just one erroneous equality constraint
| ~~~~~~~~~~~ | ~~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-ty.rs:8:17 --> $DIR/issue-102335-ty.rs:8:17
| |
LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
| ^^^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
| ~~~~~~~~~~ | ~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-ty.rs:8:17 --> $DIR/issue-102335-ty.rs:8:17
| |
LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
| ^^^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints LL | type A: S<C<i32 = u32, X = i32> = ()>; // More than one erroneous equality constraints
| ~~~~~~~~~~ | ~~~~~~~~~~

View File

@ -4,7 +4,7 @@ pub trait Iter {
type Item<'a>: 'a where Self: 'a; type Item<'a>: 'a where Self: 'a;
fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>; fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
} }
impl Iter for () { impl Iter for () {

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/no-gat-position.rs:6:56 --> $DIR/no-gat-position.rs:6:56
| |
LL | fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>; LL | fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
| ^^^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -18,14 +18,14 @@ impl Tr1 for isize {
// Test for when the assoc type is // Test for when the assoc type is
// specified as an equality constraint // specified as an equality constraint
impl Tr1<A = usize> for usize { impl Tr1<A = usize> for usize {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR not all trait items implemented, missing: `A` //~| ERROR not all trait items implemented, missing: `A`
fn boo(&self) -> usize { 42 } fn boo(&self) -> usize { 42 }
} }
// Test for a wronngly used equality constraint in a func arg // Test for a wronngly used equality constraint in a func arg
fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {} fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
@ -38,28 +38,28 @@ trait Tr2<T1, T2, T3> {
// (Note: E0229 is emitted only for the first erroneous equality // (Note: E0229 is emitted only for the first erroneous equality
// constraint (T2) not for any subequent ones (e.g. T3)) // constraint (T2) not for any subequent ones (e.g. T3))
impl Tr2<i32, T2 = Qux, T3 = usize> for Bar { impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
} }
// Test for when equality constraint's ident matches a // Test for when equality constraint's ident matches a
// generic param's ident but has different case // generic param's ident but has different case
impl Tr2<i32, t2 = Qux, T3 = usize> for Qux { impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
} }
// Test for when equality constraint's ident // Test for when equality constraint's ident
// matches none of the generic param idents // matches none of the generic param idents
impl Tr2<i32, X = Qux, Y = usize> for Bar { impl Tr2<i32, X = Qux, Y = usize> for Bar {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
} }
// Test for when the term in equality constraint is itself generic // Test for when the term in equality constraint is itself generic
struct GenericTerm<T> { _t: T } struct GenericTerm<T> { _t: T }
impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar { impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR trait takes 3 generic arguments but 2 generic arguments were supplied //~| ERROR trait takes 3 generic arguments but 2 generic arguments were supplied
} }
@ -74,7 +74,7 @@ trait Tr3<const N: i32, T2, T3> {
// (Deliberately spread over multiple lines to test that // (Deliberately spread over multiple lines to test that
// our suggestion spans are kosher in the face of such formatting) // our suggestion spans are kosher in the face of such formatting)
impl Tr3<N impl Tr3<N
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated const equality is incomplete //~| ERROR associated const equality is incomplete
//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
= 42, T2 = Qux, T3 = usize> for Bar { = 42, T2 = Qux, T3 = usize> for Bar {
@ -83,7 +83,7 @@ impl Tr3<N
// Test for when equality constraint's ident // Test for when equality constraint's ident
// matches the const param's ident but has a different case // matches the const param's ident but has a different case
impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux { impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated const equality is incomplete //~| ERROR associated const equality is incomplete
//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
} }
@ -91,14 +91,14 @@ impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
// Test for when equality constraint's ident // Test for when equality constraint's ident
// matches the const param ident but the constraint is a type arg // matches the const param ident but the constraint is a type arg
impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar { impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
} }
// Test for when equality constraint's ident // Test for when equality constraint's ident
// matches a type param ident but the constraint is a const arg // matches a type param ident but the constraint is a const arg
impl Tr3<42, T2 = 42, T3 = usize> for Bar { impl Tr3<42, T2 = 42, T3 = usize> for Bar {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated const equality is incomplete //~| ERROR associated const equality is incomplete
//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
} }
@ -106,7 +106,7 @@ impl Tr3<42, T2 = 42, T3 = usize> for Bar {
// Test for when equality constraint's ident // Test for when equality constraint's ident
// matches none of the param idents // matches none of the param idents
impl Tr3<X = 42, Y = Qux, Z = usize> for Bar { impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated const equality is incomplete //~| ERROR associated const equality is incomplete
//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
} }
@ -117,7 +117,7 @@ impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
struct St<'a, T> { v: &'a T } struct St<'a, T> { v: &'a T }
impl<'a, T> St<'a , T = Qux> { impl<'a, T> St<'a , T = Qux> {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied //~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied
} }

View File

@ -43,13 +43,13 @@ LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:20:10 --> $DIR/associated-types-eq-2.rs:20:10
| |
LL | impl Tr1<A = usize> for usize { LL | impl Tr1<A = usize> for usize {
| ^^^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr1<A = usize> for usize { LL | impl Tr1<A = usize> for usize {
| ~~~~~~~~~~~ | ~~~~~~~~~~~
@ -63,13 +63,13 @@ LL | type A;
LL | impl Tr1<A = usize> for usize { LL | impl Tr1<A = usize> for usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `A` in implementation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `A` in implementation
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:27:31 --> $DIR/associated-types-eq-2.rs:27:31
| |
LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {} LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
| ^^^^^ associated type not allowed here | ^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {} LL | fn baz<I: Tr1>(_x: &<I as Tr1<A=Bar>>::A) {}
| ~~~~~~~ | ~~~~~~~
@ -92,11 +92,11 @@ help: add missing generic arguments
LL | impl Tr2<i32, T2, T3, T2 = Qux, T3 = usize> for Bar { LL | impl Tr2<i32, T2, T3, T2 = Qux, T3 = usize> for Bar {
| ++++++++ | ++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:40:15 --> $DIR/associated-types-eq-2.rs:40:15
| |
LL | impl Tr2<i32, T2 = Qux, T3 = usize> for Bar { LL | impl Tr2<i32, T2 = Qux, T3 = usize> for Bar {
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: to use `Qux` as a generic argument specify it directly help: to use `Qux` as a generic argument specify it directly
| |
@ -121,13 +121,13 @@ help: add missing generic arguments
LL | impl Tr2<i32, T2, T3, t2 = Qux, T3 = usize> for Qux { LL | impl Tr2<i32, T2, T3, t2 = Qux, T3 = usize> for Qux {
| ++++++++ | ++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:47:15 --> $DIR/associated-types-eq-2.rs:47:15
| |
LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux { LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux { LL | impl Tr2<i32, t2 = Qux, T3 = usize> for Qux {
| ~~~~~~~~~~ | ~~~~~~~~~~
@ -150,13 +150,13 @@ help: add missing generic arguments
LL | impl Tr2<i32, T2, T3, X = Qux, Y = usize> for Bar { LL | impl Tr2<i32, T2, T3, X = Qux, Y = usize> for Bar {
| ++++++++ | ++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:54:15 --> $DIR/associated-types-eq-2.rs:54:15
| |
LL | impl Tr2<i32, X = Qux, Y = usize> for Bar { LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
| ^^^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr2<i32, X = Qux, Y = usize> for Bar { LL | impl Tr2<i32, X = Qux, Y = usize> for Bar {
| ~~~~~~~~~ | ~~~~~~~~~
@ -179,11 +179,11 @@ help: add missing generic argument
LL | impl Tr2<i32, Qux, T3, T3 = GenericTerm<i32>> for Bar { LL | impl Tr2<i32, Qux, T3, T3 = GenericTerm<i32>> for Bar {
| ++++ | ++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:61:20 --> $DIR/associated-types-eq-2.rs:61:20
| |
LL | impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar { LL | impl Tr2<i32, Qux, T3 = GenericTerm<i32>> for Bar {
| ^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^^^^^^^^^^^ associated item constraint not allowed here
| |
help: to use `GenericTerm<i32>` as a generic argument specify it directly help: to use `GenericTerm<i32>` as a generic argument specify it directly
| |
@ -206,7 +206,7 @@ help: add missing generic arguments
LL | impl Tr3<N, T2, T3, N LL | impl Tr3<N, T2, T3, N
| ++++++++++ | ++++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:76:10 --> $DIR/associated-types-eq-2.rs:76:10
| |
LL | impl Tr3<N LL | impl Tr3<N
@ -215,7 +215,7 @@ LL | |
LL | | LL | |
LL | | LL | |
LL | | = 42, T2 = Qux, T3 = usize> for Bar { LL | | = 42, T2 = Qux, T3 = usize> for Bar {
| |____^ associated type not allowed here | |____^ associated item constraint not allowed here
| |
help: to use `42` as a generic argument specify it directly help: to use `42` as a generic argument specify it directly
| |
@ -238,13 +238,13 @@ help: add missing generic arguments
LL | impl Tr3<N, T2, T3, n = 42, T2 = Qux, T3 = usize> for Qux { LL | impl Tr3<N, T2, T3, n = 42, T2 = Qux, T3 = usize> for Qux {
| ++++++++++ | ++++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:85:10 --> $DIR/associated-types-eq-2.rs:85:10
| |
LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux { LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
| ^^^^^^ associated type not allowed here | ^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux { LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
| ~~~~~~~ | ~~~~~~~
@ -265,13 +265,13 @@ help: add missing generic arguments
LL | impl Tr3<N, T2, T3, N = u32, T2 = Qux, T3 = usize> for Bar { LL | impl Tr3<N, T2, T3, N = u32, T2 = Qux, T3 = usize> for Bar {
| ++++++++++ | ++++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:93:10 --> $DIR/associated-types-eq-2.rs:93:10
| |
LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar { LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
| ^^^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar { LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
| ~~~~~~~~ | ~~~~~~~~
@ -294,13 +294,13 @@ help: add missing generic arguments
LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar { LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar {
| ++++++++ | ++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:100:14 --> $DIR/associated-types-eq-2.rs:100:14
| |
LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar { LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
| ^^^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar { LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
| ~~~~~~~~~ | ~~~~~~~~~
@ -321,13 +321,13 @@ help: add missing generic arguments
LL | impl Tr3<N, T2, T3, X = 42, Y = Qux, Z = usize> for Bar { LL | impl Tr3<N, T2, T3, X = 42, Y = Qux, Z = usize> for Bar {
| ++++++++++ | ++++++++++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:108:10 --> $DIR/associated-types-eq-2.rs:108:10
| |
LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar { LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
| ^^^^^^ associated type not allowed here | ^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar { LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
| ~~~~~~~ | ~~~~~~~
@ -348,11 +348,11 @@ help: add missing generic argument
LL | impl<'a, T> St<'a, T , T = Qux> { LL | impl<'a, T> St<'a, T , T = Qux> {
| +++ | +++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-2.rs:119:21 --> $DIR/associated-types-eq-2.rs:119:21
| |
LL | impl<'a, T> St<'a , T = Qux> { LL | impl<'a, T> St<'a , T = Qux> {
| ^^^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
help: to use `Qux` as a generic argument specify it directly help: to use `Qux` as a generic argument specify it directly
| |

View File

@ -11,6 +11,6 @@ impl Foo for isize {
} }
pub fn main() { pub fn main() {
let x: isize = Foo::<A=usize>::bar(); let x: isize = Foo::<A = usize>::bar();
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
} }

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/associated-types-eq-expr-path.rs:14:26 --> $DIR/associated-types-eq-expr-path.rs:14:26
| |
LL | let x: isize = Foo::<A=usize>::bar(); LL | let x: isize = Foo::<A = usize>::bar();
| ^^^^^^^ associated type not allowed here | ^^^^^^^^^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -8,7 +8,7 @@ trait Super1<'a> {
} }
impl Super1<'_, bar(): Send> for () {} impl Super1<'_, bar(): Send> for () {}
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR not all trait items implemented //~| ERROR not all trait items implemented
fn main() {} fn main() {}

View File

@ -7,11 +7,11 @@ LL | #![feature(return_type_notation)]
= 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[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/rtn-in-impl-signature.rs:10:17 --> $DIR/rtn-in-impl-signature.rs:10:17
| |
LL | impl Super1<'_, bar(): Send> for () {} LL | impl Super1<'_, bar(): Send> for () {}
| ^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^ associated item constraint not allowed here
error[E0046]: not all trait items implemented, missing: `bar` error[E0046]: not all trait items implemented, missing: `bar`
--> $DIR/rtn-in-impl-signature.rs:10:1 --> $DIR/rtn-in-impl-signature.rs:10:1

View File

@ -8,7 +8,7 @@ const T: usize = 42;
impl Foo<N = 3> for Bar { impl Foo<N = 3> for Bar {
//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied //~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
//~| ERROR associated const equality is incomplete //~| ERROR associated const equality is incomplete
fn do_x(&self) -> [u8; 3] { fn do_x(&self) -> [u8; 3] {
[0u8; 3] [0u8; 3]

View File

@ -24,11 +24,11 @@ help: add missing generic argument
LL | impl Foo<N, N = 3> for Bar { LL | impl Foo<N, N = 3> for Bar {
| ++ | ++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-89013-no-kw.rs:9:10 --> $DIR/issue-89013-no-kw.rs:9:10
| |
LL | impl Foo<N = 3> for Bar { LL | impl Foo<N = 3> for Bar {
| ^^^^^ associated type not allowed here | ^^^^^ associated item constraint not allowed here
| |
help: to use `3` as a generic argument specify it directly help: to use `3` as a generic argument specify it directly
| |

View File

@ -9,7 +9,7 @@ const T: usize = 42;
impl Foo<N = const 3> for Bar { impl Foo<N = const 3> for Bar {
//~^ ERROR expected lifetime, type, or constant, found keyword `const` //~^ ERROR expected lifetime, type, or constant, found keyword `const`
//~| ERROR trait takes 1 generic //~| ERROR trait takes 1 generic
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
//~| ERROR associated const equality is incomplete //~| ERROR associated const equality is incomplete
fn do_x(&self) -> [u8; 3] { fn do_x(&self) -> [u8; 3] {
[0u8; 3] [0u8; 3]

View File

@ -36,11 +36,11 @@ help: add missing generic argument
LL | impl Foo<N, N = const 3> for Bar { LL | impl Foo<N, N = const 3> for Bar {
| ++ | ++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-89013.rs:9:10 --> $DIR/issue-89013.rs:9:10
| |
LL | impl Foo<N = const 3> for Bar { LL | impl Foo<N = const 3> for Bar {
| ^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^ associated item constraint not allowed here
| |
help: to use `3` as a generic argument specify it directly help: to use `3` as a generic argument specify it directly
| |

View File

@ -10,10 +10,10 @@ impl Foo for isize {
fn boo(&self) -> usize { 42 } fn boo(&self) -> usize { 42 }
} }
fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
//~^ ERROR associated type bindings are not allowed here [E0229] //~^ ERROR associated item constraints are not allowed here [E0229]
//~| ERROR associated type bindings are not allowed here [E0229] //~| ERROR associated item constraints are not allowed here [E0229]
//~| ERROR associated type bindings are not allowed here [E0229] //~| ERROR associated item constraints are not allowed here [E0229]
//~| ERROR the trait bound `I: Foo` is not satisfied //~| ERROR the trait bound `I: Foo` is not satisfied
//~| ERROR the trait bound `I: Foo` is not satisfied //~| ERROR the trait bound `I: Foo` is not satisfied

View File

@ -1,58 +1,58 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/E0229.rs:13:25 --> $DIR/E0229.rs:13:25
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ~~~~~~~ | ~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/E0229.rs:13:25 --> $DIR/E0229.rs:13:25
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ~~~~~~~ | ~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/E0229.rs:13:25 --> $DIR/E0229.rs:13:25
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^^^^ associated type not allowed here | ^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ~~~~~~~ | ~~~~~~~~~
error[E0277]: the trait bound `I: Foo` is not satisfied error[E0277]: the trait bound `I: Foo` is not satisfied
--> $DIR/E0229.rs:13:15 --> $DIR/E0229.rs:13:15
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I` | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I`
| |
help: consider restricting type parameter `I` help: consider restricting type parameter `I`
| |
LL | fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I: Foo>(x: &<I as Foo<A = Bar>>::A) {}
| +++++ | +++++
error[E0277]: the trait bound `I: Foo` is not satisfied error[E0277]: the trait bound `I: Foo` is not satisfied
--> $DIR/E0229.rs:13:37 --> $DIR/E0229.rs:13:39
| |
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {}
| ^^ the trait `Foo` is not implemented for `I` | ^^ the trait `Foo` is not implemented for `I`
| |
help: consider restricting type parameter `I` help: consider restricting type parameter `I`
| |
LL | fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {} LL | fn baz<I: Foo>(x: &<I as Foo<A = Bar>>::A) {}
| +++++ | +++++
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View File

@ -16,7 +16,7 @@ impl Fn<()> for Foo {
} }
struct Foo1; struct Foo1;
impl FnOnce() for Foo1 { impl FnOnce() for Foo1 {
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR manual implementations of `FnOnce` are experimental //~| ERROR manual implementations of `FnOnce` are experimental
//~| ERROR not all trait items implemented //~| ERROR not all trait items implemented
extern "rust-call" fn call_once(self, args: ()) -> () {} extern "rust-call" fn call_once(self, args: ()) -> () {}

View File

@ -105,11 +105,11 @@ LL | impl FnOnce() for Foo1 {
| |
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
| |
LL | impl FnOnce() for Foo1 { LL | impl FnOnce() for Foo1 {
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: parenthesized trait syntax expands to `FnOnce<(), Output=()>` help: parenthesized trait syntax expands to `FnOnce<(), Output=()>`
--> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6

View File

@ -4,7 +4,7 @@
struct S; struct S;
impl Fn(u32) -> u32 for S { impl Fn(u32) -> u32 for S {
//~^ ERROR associated type bindings are not allowed here [E0229] //~^ ERROR associated item constraints are not allowed here [E0229]
//~| ERROR expected a `FnMut(u32)` closure, found `S` //~| ERROR expected a `FnMut(u32)` closure, found `S`
fn call(&self) -> u32 { fn call(&self) -> u32 {
//~^ ERROR method `call` has 1 parameter but the declaration in trait `call` has 2 //~^ ERROR method `call` has 1 parameter but the declaration in trait `call` has 2

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-39259.rs:6:17 --> $DIR/issue-39259.rs:6:17
| |
LL | impl Fn(u32) -> u32 for S { LL | impl Fn(u32) -> u32 for S {
| ^^^ associated type not allowed here | ^^^ associated item constraint not allowed here
| |
help: parenthesized trait syntax expands to `Fn<(u32,), Output=u32>` help: parenthesized trait syntax expands to `Fn<(u32,), Output=u32>`
--> $DIR/issue-39259.rs:6:6 --> $DIR/issue-39259.rs:6:6

View File

@ -1,7 +1,7 @@
trait T { trait T {
type A: S<C<(), i32 = ()> = ()>; type A: S<C<(), i32 = ()> = ()>;
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }
trait Q {} trait Q {}

View File

@ -1,22 +1,22 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-gat.rs:2:21 --> $DIR/issue-102335-gat.rs:2:21
| |
LL | type A: S<C<(), i32 = ()> = ()>; LL | type A: S<C<(), i32 = ()> = ()>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<(), i32 = ()> = ()>; LL | type A: S<C<(), i32 = ()> = ()>;
| ~~~~~~~~~~ | ~~~~~~~~~~
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-102335-gat.rs:2:21 --> $DIR/issue-102335-gat.rs:2:21
| |
LL | type A: S<C<(), i32 = ()> = ()>; LL | type A: S<C<(), i32 = ()> = ()>;
| ^^^^^^^^ associated type not allowed here | ^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type A: S<C<(), i32 = ()> = ()>; LL | type A: S<C<(), i32 = ()> = ()>;
| ~~~~~~~~~~ | ~~~~~~~~~~

View File

@ -5,7 +5,7 @@ struct Foo;
pub trait D { pub trait D {
fn f<T>(self) fn f<T>(self)
where T<Bogus = Foo>: A; where T<Bogus = Foo>: A;
//~^ ERROR associated type bindings are not allowed here [E0229] //~^ ERROR associated item constraints are not allowed here [E0229]
} }
fn main() {} fn main() {}

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-23543.rs:7:17 --> $DIR/issue-23543.rs:7:17
| |
LL | where T<Bogus = Foo>: A; LL | where T<Bogus = Foo>: A;
| ^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -3,7 +3,7 @@ pub trait A: Copy {}
pub trait D { pub trait D {
fn f<T>(self) fn f<T>(self)
where T<Bogus = Self::AlsoBogus>: A; where T<Bogus = Self::AlsoBogus>: A;
//~^ ERROR associated type bindings are not allowed here [E0229] //~^ ERROR associated item constraints are not allowed here [E0229]
} }
fn main() {} fn main() {}

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-23544.rs:5:17 --> $DIR/issue-23544.rs:5:17
| |
LL | where T<Bogus = Self::AlsoBogus>: A; LL | where T<Bogus = Self::AlsoBogus>: A;
| ^^^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^^^^^^^^^^^^^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -2,17 +2,17 @@ trait A: Sized {
type N; type N;
fn x() -> fn x() ->
Self< Self<
N= //~ ERROR associated type bindings are not allowed here N= //~ ERROR associated item constraints are not allowed here
Self::N> { Self::N> {
loop {} loop {}
} }
fn y(&self) -> fn y(&self) ->
std std
<N=()> //~ ERROR associated type bindings are not allowed here <N=()> //~ ERROR associated item constraints are not allowed here
::option::Option<()> ::option::Option<()>
{ None } { None }
fn z(&self) -> fn z(&self) ->
u32<N=()> //~ ERROR associated type bindings are not allowed here u32<N=()> //~ ERROR associated item constraints are not allowed here
{ 42 } { 42 }
} }

View File

@ -1,21 +1,21 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-24682.rs:5:11 --> $DIR/issue-24682.rs:5:11
| |
LL | / N= LL | / N=
LL | | Self::N> { LL | | Self::N> {
| |_________________^ associated type not allowed here | |_________________^ associated item constraint not allowed here
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-24682.rs:11:13 --> $DIR/issue-24682.rs:11:13
| |
LL | <N=()> LL | <N=()>
| ^^^^ associated type not allowed here | ^^^^ associated item constraint not allowed here
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-24682.rs:15:13 --> $DIR/issue-24682.rs:15:13
| |
LL | u32<N=()> LL | u32<N=()>
| ^^^^ associated type not allowed here | ^^^^ associated item constraint not allowed here
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View File

@ -2,5 +2,5 @@
fn main() { fn main() {
<fn() as Fn()>::call; <fn() as Fn()>::call;
//~^ ERROR associated type bindings are not allowed here [E0229] //~^ ERROR associated item constraints are not allowed here [E0229]
} }

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-39687.rs:4:14 --> $DIR/issue-39687.rs:4:14
| |
LL | <fn() as Fn()>::call; LL | <fn() as Fn()>::call;
| ^^^^ associated type not allowed here | ^^^^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -7,7 +7,7 @@ trait CallSingle<A, B> {
impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F { impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
fn call(&self, a: A) -> B { fn call(&self, a: A) -> B {
<Self as Fn(A) -> B>::call(self, (a,)) <Self as Fn(A) -> B>::call(self, (a,))
//~^ ERROR associated type bindings are not allowed here //~^ ERROR associated item constraints are not allowed here
} }
} }

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-43431.rs:9:27 --> $DIR/issue-43431.rs:9:27
| |
LL | <Self as Fn(A) -> B>::call(self, (a,)) LL | <Self as Fn(A) -> B>::call(self, (a,))
| ^ associated type not allowed here | ^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -3,6 +3,6 @@
struct Foo {} struct Foo {}
impl Foo { impl Foo {
fn bar(foo: Foo<Target = usize>) {} fn bar(foo: Foo<Target = usize>) {}
//~^ associated type bindings are not allowed here //~^ associated item constraints are not allowed here
} }
fn main() {} fn main() {}

View File

@ -1,10 +1,10 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-83753-invalid-associated-type-supertrait-hrtb.rs:5:21 --> $DIR/issue-83753-invalid-associated-type-supertrait-hrtb.rs:5:21
| |
LL | fn bar(foo: Foo<Target = usize>) {} LL | fn bar(foo: Foo<Target = usize>) {}
| ^^^^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | fn bar(foo: Foo<Target = usize>) {} LL | fn bar(foo: Foo<Target = usize>) {}
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~

View File

@ -2,7 +2,7 @@ struct ErrorKind;
struct Error(ErrorKind); struct Error(ErrorKind);
impl Fn(&isize) for Error { impl Fn(&isize) for Error {
//~^ ERROR manual implementations of `Fn` are experimental [E0183] //~^ ERROR manual implementations of `Fn` are experimental [E0183]
//~^^ ERROR associated type bindings are not allowed here [E0229] //~^^ ERROR associated item constraints are not allowed here [E0229]
//~| ERROR not all trait items implemented //~| ERROR not all trait items implemented
//~| ERROR expected a `FnMut(&isize)` closure, found `Error` //~| ERROR expected a `FnMut(&isize)` closure, found `Error`
fn foo<const N: usize>(&self) -> Self::B<{ N }>; fn foo<const N: usize>(&self) -> Self::B<{ N }>;

View File

@ -20,11 +20,11 @@ LL | impl Fn(&isize) for Error {
| |
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-95023.rs:3:6 --> $DIR/issue-95023.rs:3:6
| |
LL | impl Fn(&isize) for Error { LL | impl Fn(&isize) for Error {
| ^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^ associated item constraint not allowed here
| |
help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>` help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
--> $DIR/issue-95023.rs:3:6 --> $DIR/issue-95023.rs:3:6

View File

@ -1,3 +1,3 @@
fn main() { fn main() {
0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here 0.clone::<T = u8>(); //~ ERROR associated item constraints are not allowed here
} }

View File

@ -1,8 +1,8 @@
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/method-call-type-binding.rs:2:15 --> $DIR/method-call-type-binding.rs:2:15
| |
LL | 0.clone::<T = u8>(); LL | 0.clone::<T = u8>();
| ^^^^^^ associated type not allowed here | ^^^^^^ associated item constraint not allowed here
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -3,12 +3,12 @@ trait Foo {
type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
//~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
//~| HELP add missing //~| HELP add missing
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
//~| HELP consider removing this type binding //~| HELP consider removing this associated item binding
//~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
//~| HELP add missing //~| HELP add missing
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
//~| HELP consider removing this type binding //~| HELP consider removing this associated item binding
} }
fn main() {} fn main() {}

View File

@ -14,13 +14,13 @@ help: add missing lifetime argument
LL | type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>; LL | type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>;
| +++ | +++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-85347.rs:3:46 --> $DIR/issue-85347.rs:3:46
| |
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
| ^^^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^^^ associated item constraint not allowed here
| |
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
| ~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~
@ -42,14 +42,14 @@ help: add missing lifetime argument
LL | type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>; LL | type Bar<'a>: Deref<Target = <Self>::Bar<'a, Target = Self>>;
| +++ | +++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-85347.rs:3:46 --> $DIR/issue-85347.rs:3:46
| |
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
| ^^^^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^^^^ associated item constraint not allowed here
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: consider removing this type binding help: consider removing this associated item binding
| |
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>; LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
| ~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~

View File

@ -8,5 +8,5 @@ fn main() {
//~| HELP you might have meant to write a path instead of an associated type bound //~| HELP you might have meant to write a path instead of an associated type bound
//~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied
//~| HELP add missing generic argument //~| HELP add missing generic argument
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
} }

View File

@ -20,11 +20,11 @@ help: add missing generic argument
LL | let _: Vec<T, A:B> = A::B; LL | let _: Vec<T, A:B> = A::B;
| ++ | ++
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16
| |
LL | let _: Vec<A:B> = A::B; LL | let _: Vec<A:B> = A::B;
| ^^^ associated type not allowed here | ^^^ associated item constraint not allowed here
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View File

@ -2,7 +2,7 @@ struct ErrorKind;
struct Error(ErrorKind); struct Error(ErrorKind);
impl Fn(&isize) for Error { impl Fn(&isize) for Error {
//~^ ERROR manual implementations of `Fn` are experimental //~^ ERROR manual implementations of `Fn` are experimental
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
//~| ERROR closure, found `Error` //~| ERROR closure, found `Error`
//~| ERROR not all trait items implemented, missing: `call` //~| ERROR not all trait items implemented, missing: `call`
fn from() {} //~ ERROR method `from` is not a member of trait `Fn` fn from() {} //~ ERROR method `from` is not a member of trait `Fn`

View File

@ -12,11 +12,11 @@ LL | impl Fn(&isize) for Error {
| |
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/issue-87558.rs:3:6 --> $DIR/issue-87558.rs:3:6
| |
LL | impl Fn(&isize) for Error { LL | impl Fn(&isize) for Error {
| ^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^ associated item constraint not allowed here
| |
help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>` help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
--> $DIR/issue-87558.rs:3:6 --> $DIR/issue-87558.rs:3:6

View File

@ -5,6 +5,6 @@ type Pat<const START: u32, const END: u32> =
std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
//~^ ERROR type and const arguments are not allowed on const parameter `START` //~^ ERROR type and const arguments are not allowed on const parameter `START`
//~| ERROR type arguments are not allowed on const parameter `END` //~| ERROR type arguments are not allowed on const parameter `END`
//~| ERROR associated type bindings are not allowed here //~| ERROR associated item constraints are not allowed here
fn main() {} fn main() {}

View File

@ -26,11 +26,11 @@ note: const parameter `END` defined here
LL | type Pat<const START: u32, const END: u32> = LL | type Pat<const START: u32, const END: u32> =
| ^^^ | ^^^
error[E0229]: associated type bindings are not allowed here error[E0229]: associated item constraints are not allowed here
--> $DIR/bad_const_generics_args_on_const_param.rs:5:67 --> $DIR/bad_const_generics_args_on_const_param.rs:5:67
| |
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| ^^^^^^^^^^ associated type not allowed here | ^^^^^^^^^^ associated item constraint not allowed here
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

Some files were not shown because too many files have changed in this diff Show More