From 0c1b2731f8aabf994c3fffce16182404081c8f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 7 Feb 2024 20:01:09 +0000 Subject: [PATCH 1/2] Provide more suggestions on invalid equality where bounds ``` error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:50:9 | LL | IntoIterator::Item = A, | ^^^^^^^^^^^^^^^^^^^^^^ not supported | = note: see issue #20041 for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter>(_: T) -> Self LL | where LL ~ | error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:63:9 | LL | T::Item = A, | ^^^^^^^^^^^ not supported | = note: see issue #20041 for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter>(_: T) -> Self LL | where LL ~ | ``` Fix #68982. --- .../rustc_ast_passes/src/ast_validation.rs | 67 ++++++++++++- .../equality-bound.rs | 56 +++++++++++ .../equality-bound.stderr | 95 ++++++++++++++++++- 3 files changed, 212 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9ea5d1ed5fa..ec54f1032c3 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1593,12 +1593,71 @@ fn deny_equality_constraints( } } } - // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { + // Given `A: Foo, Foo::Bar = RhsTy`, suggest `A: Foo`. + for bounds in generics.params.iter().map(|p| &p.bounds).chain( + generics.where_clause.predicates.iter().filter_map(|pred| match pred { + WherePredicate::BoundPredicate(p) => Some(&p.bounds), + _ => None, + }), + ) { + for bound in bounds { + if let GenericBound::Trait(poly, TraitBoundModifiers::NONE) = bound { + if full_path.segments[..full_path.segments.len() - 1] + .iter() + .map(|segment| segment.ident.name) + .zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name)) + .all(|(a, b)| a == b) + { + let potential_assoc = full_path.segments.iter().last().unwrap(); + // println!("asd"); + if let [trait_segment] = &poly.trait_ref.path.segments[..] { + let assoc = pprust::path_to_string(&ast::Path::from_ident( + potential_assoc.ident, + )); + let ty = pprust::ty_to_string(&predicate.rhs_ty); + let (args, span) = match &trait_segment.args { + Some(args) => match args.deref() { + ast::GenericArgs::AngleBracketed(args) => { + let Some(arg) = args.args.last() else { + continue; + }; + (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) + } + _ => continue, + }, + None => ( + format!("<{assoc} = {ty}>"), + trait_segment.span().shrink_to_hi(), + ), + }; + err.assoc2 = Some(errors::AssociatedSuggestion2 { + span, + args, + predicate: predicate.span, + trait_segment: trait_segment.ident, + potential_assoc: potential_assoc.ident, + }); + } + } + } + } + } + // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. if let [potential_param, potential_assoc] = &full_path.segments[..] { - for param in &generics.params { - if param.ident == potential_param.ident { - for bound in ¶m.bounds { + for (ident, bounds) in generics.params.iter().map(|p| (p.ident, &p.bounds)).chain( + generics.where_clause.predicates.iter().filter_map(|pred| match pred { + WherePredicate::BoundPredicate(p) + if let ast::TyKind::Path(None, path) = &p.bounded_ty.kind + && let [segment] = &path.segments[..] => + { + Some((segment.ident, &p.bounds)) + } + _ => None, + }), + ) { + if ident == potential_param.ident { + for bound in bounds { if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) = bound { diff --git a/tests/ui/generic-associated-types/equality-bound.rs b/tests/ui/generic-associated-types/equality-bound.rs index fcc2da8014f..63bb5dd3567 100644 --- a/tests/ui/generic-associated-types/equality-bound.rs +++ b/tests/ui/generic-associated-types/equality-bound.rs @@ -12,4 +12,60 @@ fn sum3(i: J) -> i32 where I::Item = i32 { panic!() } +use std::iter::FromIterator; + +struct X {} + +impl FromIterator for X { + fn from_iter(_: T) -> Self + where + T: IntoIterator, + IntoIterator::Item = A, + //~^ ERROR equality constraints are not yet supported in `where` clauses + //~| ERROR cannot find type `A` in this scope + { + todo!() + } +} + +struct Y {} + +impl FromIterator for Y { + fn from_iter(_: T) -> Self + where + T: IntoIterator, + T::Item = A, + //~^ ERROR equality constraints are not yet supported in `where` clauses + //~| ERROR cannot find type `A` in this scope + { + todo!() + } +} + +struct Z {} + +impl FromIterator for Z { + fn from_iter(_: T) -> Self + where + IntoIterator::Item = A, + //~^ ERROR equality constraints are not yet supported in `where` clauses + //~| ERROR cannot find type `A` in this scope + { + todo!() + } +} + +struct K {} + +impl FromIterator for K { + fn from_iter(_: T) -> Self + where + T::Item = A, + //~^ ERROR equality constraints are not yet supported in `where` clauses + //~| ERROR cannot find type `A` in this scope + { + todo!() + } +} + fn main() {} diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr index b21ff30a27d..8e29d9092c5 100644 --- a/tests/ui/generic-associated-types/equality-bound.stderr +++ b/tests/ui/generic-associated-types/equality-bound.stderr @@ -32,6 +32,96 @@ LL | fn sum3(i: J) -> i32 where I::Item = i32 { | = note: see issue #20041 for more information +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:23:9 + | +LL | IntoIterator::Item = A, + | ^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL ~ T: IntoIterator, +LL ~ , + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:37:9 + | +LL | T::Item = A, + | ^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL ~ T: IntoIterator, +LL ~ , + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:50:9 + | +LL | IntoIterator::Item = A, + | ^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL ~ fn from_iter>(_: T) -> Self +LL | where +LL ~ , + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:63:9 + | +LL | T::Item = A, + | ^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL ~ fn from_iter>(_: T) -> Self +LL | where +LL ~ , + | + +error[E0412]: cannot find type `A` in this scope + --> $DIR/equality-bound.rs:23:30 + | +LL | IntoIterator::Item = A, + | ^ help: a struct with a similar name exists: `K` +... +LL | struct K {} + | -------- similarly named struct `K` defined here + +error[E0412]: cannot find type `A` in this scope + --> $DIR/equality-bound.rs:37:19 + | +LL | T::Item = A, + | ^ help: a struct with a similar name exists: `K` +... +LL | struct K {} + | -------- similarly named struct `K` defined here + +error[E0412]: cannot find type `A` in this scope + --> $DIR/equality-bound.rs:50:30 + | +LL | IntoIterator::Item = A, + | ^ help: a struct with a similar name exists: `K` +... +LL | struct K {} + | -------- similarly named struct `K` defined here + +error[E0412]: cannot find type `A` in this scope + --> $DIR/equality-bound.rs:63:19 + | +LL | struct K {} + | -------- similarly named struct `K` defined here +... +LL | T::Item = A, + | ^ help: a struct with a similar name exists: `K` + error[E0433]: failed to resolve: use of undeclared type `I` --> $DIR/equality-bound.rs:9:41 | @@ -41,6 +131,7 @@ LL | fn sum3(i: J) -> i32 where I::Item = i32 { | use of undeclared type `I` | help: a type parameter with a similar name exists: `J` -error: aborting due to 4 previous errors +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0433`. +Some errors have detailed explanations: E0412, E0433. +For more information about an error, try `rustc --explain E0412`. From 535c64336d6dcd588dd794d526047a4425e6e402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Feb 2024 00:26:42 +0000 Subject: [PATCH 2/2] Do not leave stray commas after applying suggestion --- .../rustc_ast_passes/src/ast_validation.rs | 117 +++++++++--------- .../equality-bound.rs | 39 +++--- .../equality-bound.stderr | 116 +++++++++++------ 3 files changed, 160 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ec54f1032c3..356b578d518 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1593,6 +1593,58 @@ fn deny_equality_constraints( } } } + + let mut suggest = + |poly: &PolyTraitRef, potential_assoc: &PathSegment, predicate: &WhereEqPredicate| { + if let [trait_segment] = &poly.trait_ref.path.segments[..] { + let assoc = pprust::path_to_string(&ast::Path::from_ident(potential_assoc.ident)); + let ty = pprust::ty_to_string(&predicate.rhs_ty); + let (args, span) = match &trait_segment.args { + Some(args) => match args.deref() { + ast::GenericArgs::AngleBracketed(args) => { + let Some(arg) = args.args.last() else { + return; + }; + (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) + } + _ => return, + }, + None => (format!("<{assoc} = {ty}>"), trait_segment.span().shrink_to_hi()), + }; + let removal_span = if generics.where_clause.predicates.len() == 1 { + // We're removing th eonly where bound left, remove the whole thing. + generics.where_clause.span + } else { + let mut span = predicate.span; + let mut prev: Option = None; + let mut preds = generics.where_clause.predicates.iter().peekable(); + // Find the predicate that shouldn't have been in the where bound list. + while let Some(pred) = preds.next() { + if let WherePredicate::EqPredicate(pred) = pred + && pred.span == predicate.span + { + if let Some(next) = preds.peek() { + // This is the first predicate, remove the trailing comma as well. + span = span.with_hi(next.span().lo()); + } else if let Some(prev) = prev { + // Remove the previous comma as well. + span = span.with_lo(prev.hi()); + } + } + prev = Some(pred.span()); + } + span + }; + err.assoc2 = Some(errors::AssociatedSuggestion2 { + span, + args, + predicate: removal_span, + trait_segment: trait_segment.ident, + potential_assoc: potential_assoc.ident, + }); + } + }; + if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { // Given `A: Foo, Foo::Bar = RhsTy`, suggest `A: Foo`. for bounds in generics.params.iter().map(|p| &p.bounds).chain( @@ -1608,37 +1660,9 @@ fn deny_equality_constraints( .map(|segment| segment.ident.name) .zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name)) .all(|(a, b)| a == b) + && let Some(potential_assoc) = full_path.segments.iter().last() { - let potential_assoc = full_path.segments.iter().last().unwrap(); - // println!("asd"); - if let [trait_segment] = &poly.trait_ref.path.segments[..] { - let assoc = pprust::path_to_string(&ast::Path::from_ident( - potential_assoc.ident, - )); - let ty = pprust::ty_to_string(&predicate.rhs_ty); - let (args, span) = match &trait_segment.args { - Some(args) => match args.deref() { - ast::GenericArgs::AngleBracketed(args) => { - let Some(arg) = args.args.last() else { - continue; - }; - (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) - } - _ => continue, - }, - None => ( - format!("<{assoc} = {ty}>"), - trait_segment.span().shrink_to_hi(), - ), - }; - err.assoc2 = Some(errors::AssociatedSuggestion2 { - span, - args, - predicate: predicate.span, - trait_segment: trait_segment.ident, - potential_assoc: potential_assoc.ident, - }); - } + suggest(poly, potential_assoc, predicate); } } } @@ -1658,37 +1682,8 @@ fn deny_equality_constraints( ) { if ident == potential_param.ident { for bound in bounds { - if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) = - bound - { - if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { - let assoc = pprust::path_to_string(&ast::Path::from_ident( - potential_assoc.ident, - )); - let ty = pprust::ty_to_string(&predicate.rhs_ty); - let (args, span) = match &trait_segment.args { - Some(args) => match args.deref() { - ast::GenericArgs::AngleBracketed(args) => { - let Some(arg) = args.args.last() else { - continue; - }; - (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) - } - _ => continue, - }, - None => ( - format!("<{assoc} = {ty}>"), - trait_segment.span().shrink_to_hi(), - ), - }; - err.assoc2 = Some(errors::AssociatedSuggestion2 { - span, - args, - predicate: predicate.span, - trait_segment: trait_segment.ident, - potential_assoc: potential_assoc.ident, - }); - } + if let ast::GenericBound::Trait(poly, TraitBoundModifiers::NONE) = bound { + suggest(poly, potential_assoc, predicate); } } } diff --git a/tests/ui/generic-associated-types/equality-bound.rs b/tests/ui/generic-associated-types/equality-bound.rs index 63bb5dd3567..be05181f5d0 100644 --- a/tests/ui/generic-associated-types/equality-bound.rs +++ b/tests/ui/generic-associated-types/equality-bound.rs @@ -17,10 +17,7 @@ use std::iter::FromIterator; struct X {} impl FromIterator for X { - fn from_iter(_: T) -> Self - where - T: IntoIterator, - IntoIterator::Item = A, + fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, //~^ ERROR equality constraints are not yet supported in `where` clauses //~| ERROR cannot find type `A` in this scope { @@ -31,10 +28,7 @@ impl FromIterator for X { struct Y {} impl FromIterator for Y { - fn from_iter(_: T) -> Self - where - T: IntoIterator, - T::Item = A, + fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, //~^ ERROR equality constraints are not yet supported in `where` clauses //~| ERROR cannot find type `A` in this scope { @@ -45,9 +39,7 @@ impl FromIterator for Y { struct Z {} impl FromIterator for Z { - fn from_iter(_: T) -> Self - where - IntoIterator::Item = A, + fn from_iter(_: T) -> Self where IntoIterator::Item = A, //~^ ERROR equality constraints are not yet supported in `where` clauses //~| ERROR cannot find type `A` in this scope { @@ -58,9 +50,7 @@ impl FromIterator for Z { struct K {} impl FromIterator for K { - fn from_iter(_: T) -> Self - where - T::Item = A, + fn from_iter(_: T) -> Self where T::Item = A, //~^ ERROR equality constraints are not yet supported in `where` clauses //~| ERROR cannot find type `A` in this scope { @@ -68,4 +58,25 @@ impl FromIterator for K { } } +struct L {} + +impl FromIterator for L { + fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, + //~^ ERROR equality constraints are not yet supported in `where` clauses + //~| ERROR cannot find type `A` in this scope + { + todo!() + } +} + +struct M {} + +impl FromIterator for M { + fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, + //~^ ERROR equality constraints are not yet supported in `where` clauses + //~| ERROR cannot find type `A` in this scope + { + todo!() + } +} fn main() {} diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr index 8e29d9092c5..a054c06caeb 100644 --- a/tests/ui/generic-associated-types/equality-bound.stderr +++ b/tests/ui/generic-associated-types/equality-bound.stderr @@ -8,7 +8,7 @@ LL | fn sum>(i: I) -> i32 where I::Item = i32 { help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL - fn sum>(i: I) -> i32 where I::Item = i32 { -LL + fn sum>(i: I) -> i32 where { +LL + fn sum>(i: I) -> i32 { | error: equality constraints are not yet supported in `where` clauses @@ -21,7 +21,7 @@ LL | fn sum2(i: I) -> i32 where I::Item = i32 { help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL - fn sum2(i: I) -> i32 where I::Item = i32 { -LL + fn sum2>(i: I) -> i32 where { +LL + fn sum2>(i: I) -> i32 { | error: equality constraints are not yet supported in `where` clauses @@ -33,94 +33,136 @@ LL | fn sum3(i: J) -> i32 where I::Item = i32 { = note: see issue #20041 for more information error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:23:9 + --> $DIR/equality-bound.rs:20:58 | -LL | IntoIterator::Item = A, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported +LL | fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, + | ^^^^^^^^^^^^^^^^^^^^^^ not supported | = note: see issue #20041 for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | -LL ~ T: IntoIterator, -LL ~ , +LL - fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, +LL + fn from_iter(_: T) -> Self where T: IntoIterator, | error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:37:9 + --> $DIR/equality-bound.rs:31:58 | -LL | T::Item = A, - | ^^^^^^^^^^^ not supported +LL | fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, + | ^^^^^^^^^^^ not supported | = note: see issue #20041 for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | -LL ~ T: IntoIterator, -LL ~ , +LL - fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, +LL + fn from_iter(_: T) -> Self where T: IntoIterator, | error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:50:9 + --> $DIR/equality-bound.rs:42:55 | -LL | IntoIterator::Item = A, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported +LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, + | ^^^^^^^^^^^^^^^^^^^^^^ not supported | = note: see issue #20041 for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | -LL ~ fn from_iter>(_: T) -> Self -LL | where -LL ~ , +LL - fn from_iter(_: T) -> Self where IntoIterator::Item = A, +LL + fn from_iter>(_: T) -> Self | error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:63:9 + --> $DIR/equality-bound.rs:53:55 | -LL | T::Item = A, - | ^^^^^^^^^^^ not supported +LL | fn from_iter(_: T) -> Self where T::Item = A, + | ^^^^^^^^^^^ not supported | = note: see issue #20041 for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | -LL ~ fn from_iter>(_: T) -> Self -LL | where -LL ~ , +LL - fn from_iter(_: T) -> Self where T::Item = A, +LL + fn from_iter>(_: T) -> Self + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:64:41 + | +LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, + | ^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, +LL + fn from_iter(_: T) -> Self where T: IntoIterator, + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:75:41 + | +LL | fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, + | ^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, +LL + fn from_iter(_: T) -> Self where T: IntoIterator, | error[E0412]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:23:30 + --> $DIR/equality-bound.rs:20:79 | -LL | IntoIterator::Item = A, - | ^ help: a struct with a similar name exists: `K` +LL | fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, + | ^ help: a struct with a similar name exists: `K` ... LL | struct K {} | -------- similarly named struct `K` defined here error[E0412]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:37:19 + --> $DIR/equality-bound.rs:31:68 | -LL | T::Item = A, - | ^ help: a struct with a similar name exists: `K` +LL | fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, + | ^ help: a struct with a similar name exists: `K` ... LL | struct K {} | -------- similarly named struct `K` defined here error[E0412]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:50:30 + --> $DIR/equality-bound.rs:42:76 | -LL | IntoIterator::Item = A, - | ^ help: a struct with a similar name exists: `K` +LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, + | ^ help: a struct with a similar name exists: `K` ... LL | struct K {} | -------- similarly named struct `K` defined here error[E0412]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:63:19 + --> $DIR/equality-bound.rs:53:65 | LL | struct K {} | -------- similarly named struct `K` defined here ... -LL | T::Item = A, - | ^ help: a struct with a similar name exists: `K` +LL | fn from_iter(_: T) -> Self where T::Item = A, + | ^ help: a struct with a similar name exists: `K` + +error[E0412]: cannot find type `A` in this scope + --> $DIR/equality-bound.rs:64:62 + | +LL | struct K {} + | -------- similarly named struct `K` defined here +... +LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, + | ^ help: a struct with a similar name exists: `K` + +error[E0412]: cannot find type `A` in this scope + --> $DIR/equality-bound.rs:75:51 + | +LL | struct K {} + | -------- similarly named struct `K` defined here +... +LL | fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, + | ^ help: a struct with a similar name exists: `K` error[E0433]: failed to resolve: use of undeclared type `I` --> $DIR/equality-bound.rs:9:41 @@ -131,7 +173,7 @@ LL | fn sum3(i: J) -> i32 where I::Item = i32 { | use of undeclared type `I` | help: a type parameter with a similar name exists: `J` -error: aborting due to 12 previous errors +error: aborting due to 16 previous errors Some errors have detailed explanations: E0412, E0433. For more information about an error, try `rustc --explain E0412`.