Skip to content

Commit 4954389

Browse files
committed
Account for incorrect where T::Assoc = Ty bound
Provide suggestoin to constrain trait bound for associated type. Revert incorrect changes to `missing-bounds` test. Address part of #20041.
1 parent 311fa1f commit 4954389

File tree

7 files changed

+142
-6
lines changed

7 files changed

+142
-6
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+48-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use rustc_span::symbol::{kw, sym, Ident};
2323
use rustc_span::Span;
2424
use rustc_target::spec::abi;
2525
use std::mem;
26-
use std::ops::DerefMut;
26+
use std::ops::{Deref, DerefMut};
2727

2828
const MORE_EXTERN: &str =
2929
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
@@ -1714,6 +1714,53 @@ fn deny_equality_constraints(
17141714
}
17151715
}
17161716
}
1717+
// Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1718+
if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
1719+
if let [potential_param, potential_assoc] = &full_path.segments[..] {
1720+
for param in &generics.params {
1721+
if param.ident == potential_param.ident {
1722+
for bound in &param.bounds {
1723+
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
1724+
{
1725+
if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
1726+
let assoc = pprust::path_to_string(&ast::Path::from_ident(
1727+
potential_assoc.ident,
1728+
));
1729+
let ty = pprust::ty_to_string(&predicate.rhs_ty);
1730+
let (args, span) = match &trait_segment.args {
1731+
Some(args) => match args.deref() {
1732+
ast::GenericArgs::AngleBracketed(args) => {
1733+
let Some(arg) = args.args.last() else {
1734+
continue;
1735+
};
1736+
(
1737+
format!(", {} = {}", assoc, ty),
1738+
arg.span().shrink_to_hi(),
1739+
)
1740+
}
1741+
_ => continue,
1742+
},
1743+
None => (
1744+
format!("<{} = {}>", assoc, ty),
1745+
trait_segment.span().shrink_to_hi(),
1746+
),
1747+
};
1748+
err.multipart_suggestion(
1749+
&format!(
1750+
"if `{}::{}` is an associated type you're trying to set, \
1751+
use the associated type binding syntax",
1752+
trait_segment.ident, potential_assoc.ident,
1753+
),
1754+
vec![(span, args), (predicate.span, String::new())],
1755+
Applicability::MaybeIncorrect,
1756+
);
1757+
}
1758+
}
1759+
}
1760+
}
1761+
}
1762+
}
1763+
}
17171764
err.note(
17181765
"see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
17191766
);

compiler/rustc_ast_passes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
#![feature(iter_is_partitioned)]
88
#![feature(box_patterns)]
9+
#![feature(let_else)]
910
#![recursion_limit = "256"]
1011

1112
pub mod ast_validation;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
2+
//~^ ERROR equality constraints are not yet supported in `where` clauses
3+
panic!()
4+
}
5+
fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
6+
//~^ ERROR equality constraints are not yet supported in `where` clauses
7+
panic!()
8+
}
9+
fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
10+
//~^ ERROR equality constraints are not yet supported in `where` clauses
11+
//~| ERROR failed to resolve: use of undeclared type `I`
12+
panic!()
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: equality constraints are not yet supported in `where` clauses
2+
--> $DIR/equality-bound.rs:1:51
3+
|
4+
LL | fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
5+
| ^^^^^^^^^^^^^ not supported
6+
|
7+
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
8+
help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax
9+
|
10+
LL - fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
11+
LL + fn sum<I: Iterator<Item = (), Item = i32>>(i: I) -> i32 where {
12+
|
13+
14+
error: equality constraints are not yet supported in `where` clauses
15+
--> $DIR/equality-bound.rs:5:41
16+
|
17+
LL | fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
18+
| ^^^^^^^^^^^^^ not supported
19+
|
20+
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
21+
help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax
22+
|
23+
LL - fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
24+
LL + fn sum2<I: Iterator<Item = i32>>(i: I) -> i32 where {
25+
|
26+
27+
error: equality constraints are not yet supported in `where` clauses
28+
--> $DIR/equality-bound.rs:9:41
29+
|
30+
LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
31+
| ^^^^^^^^^^^^^ not supported
32+
|
33+
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
34+
35+
error[E0433]: failed to resolve: use of undeclared type `I`
36+
--> $DIR/equality-bound.rs:9:41
37+
|
38+
LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
39+
| ^ use of undeclared type `I`
40+
41+
error: aborting due to 4 previous errors
42+
43+
For more information about this error, try `rustc --explain E0433`.

src/test/ui/generic-associated-types/missing-bounds.fixed

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
3434

3535
struct E<B>(B);
3636

37-
impl<B: Add> Add for E<B> where B: Add<Output = B> {
37+
impl<B: Add> Add for E<B> where B: Add<Output = B>, B: Add<Output = B> {
38+
//~^ ERROR equality constraints are not yet supported in `where` clauses
3839
type Output = Self;
3940

4041
fn add(self, rhs: Self) -> Self {
41-
Self(self.0 + rhs.0)
42+
Self(self.0 + rhs.0) //~ ERROR mismatched types
4243
}
4344
}
4445

src/test/ui/generic-associated-types/missing-bounds.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ impl<B> Add for D<B> {
3434

3535
struct E<B>(B);
3636

37-
impl<B: Add> Add for E<B> where B: Add<Output = B> {
37+
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
38+
//~^ ERROR equality constraints are not yet supported in `where` clauses
3839
type Output = Self;
3940

4041
fn add(self, rhs: Self) -> Self {
41-
Self(self.0 + rhs.0)
42+
Self(self.0 + rhs.0) //~ ERROR mismatched types
4243
}
4344
}
4445

src/test/ui/generic-associated-types/missing-bounds.stderr

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: equality constraints are not yet supported in `where` clauses
2+
--> $DIR/missing-bounds.rs:37:33
3+
|
4+
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
5+
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
6+
|
7+
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
8+
help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
9+
|
10+
LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
11+
| ~~~~~~~~~~~~~~~~~~
12+
113
error[E0308]: mismatched types
214
--> $DIR/missing-bounds.rs:11:11
315
|
@@ -43,7 +55,23 @@ help: consider restricting type parameter `B`
4355
LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
4456
| +++++++++++++++++++++++++++
4557

46-
error: aborting due to 3 previous errors
58+
error[E0308]: mismatched types
59+
--> $DIR/missing-bounds.rs:42:14
60+
|
61+
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
62+
| - this type parameter
63+
...
64+
LL | Self(self.0 + rhs.0)
65+
| ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
66+
|
67+
= note: expected type parameter `B`
68+
found associated type `<B as Add>::Output`
69+
help: consider further restricting type parameter `B`
70+
|
71+
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
72+
| ++++++++++++++++++++
73+
74+
error: aborting due to 5 previous errors
4775

4876
Some errors have detailed explanations: E0308, E0369.
4977
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)