Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recover invalid assoc type bounds using == #87566

Merged
merged 2 commits into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1955,7 +1955,19 @@ impl<'a> Parser<'a> {
}
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
Ok(expr) => {
if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() {
// Find a mistake like `MyTrait<Assoc == S::Assoc>`.
if token::EqEq == snapshot.token.kind {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is the wrong place for this. Haven't dug into this, but I would have expected this to be in the same place as the associated type parsing code? There, we just "accept" with an error == when we really want =.

I guess this is potentially "ambiguous" if Assoc == S::Assoc gets treated as a const arg, which I guess is what currently happens.

Is there anything we can to be smarter here? Would we theoretically be allowed to have a variable named Assoc? I'm trying to think of if we had complete knowledge of all traits, types, variables, etc. in scope, are there any cases where we can know if this should be a bracketed const expr arg or an associated type binding?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got somewhat confused as to why we didn't have a == binop here, but looking at the surrounding code I can now see that we discard whatever op this was and what is being parsed here is the RHS, namely a single path. So I'm getting around to thinking that this is not a bad place to make this check.

err.span_suggestion(
snapshot.token.span,
"if you meant to use an associated type binding, replace `==` with `=`",
"=".to_string(),
Applicability::MaybeIncorrect,
);
let value = self.mk_expr_err(start.to(expr.span));
err.emit();
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
} else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
{
// Avoid the following output by checking that we consumed a full const arg:
// help: expressions must be enclosed in braces to be used as const generic
// arguments
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/const-generics/issues/issue-87493.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub trait MyTrait {
type Assoc;
}

pub fn foo<S, T>(_s: S, _t: T)
where
S: MyTrait,
T: MyTrait<Assoc == S::Assoc>,
//~^ ERROR: expected one of `,` or `>`, found `==`
//~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied
{
}

fn main() {}
28 changes: 28 additions & 0 deletions src/test/ui/const-generics/issues/issue-87493.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error: expected one of `,` or `>`, found `==`
--> $DIR/issue-87493.rs:8:22
|
LL | T: MyTrait<Assoc == S::Assoc>,
| ^^ expected one of `,` or `>`
|
help: if you meant to use an associated type binding, replace `==` with `=`
|
LL | T: MyTrait<Assoc = S::Assoc>,
| ~

error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-87493.rs:8:8
|
LL | T: MyTrait<Assoc == S::Assoc>,
| ^^^^^^^------------------- help: remove these generics
| |
| expected 0 generic arguments
|
note: trait defined here, with 0 generic parameters
--> $DIR/issue-87493.rs:1:11
|
LL | pub trait MyTrait {
| ^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0107`.