parse: improve recovery for assoc eq constraints.
This commit is contained in:
parent
f91de44d07
commit
2972bb37b8
7 changed files with 111 additions and 1 deletions
|
@ -4,6 +4,7 @@ use crate::maybe_whole;
|
|||
use rustc_ast::ast::{self, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs};
|
||||
use rustc_ast::ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
||||
use rustc_ast::ast::{Ident, Path, PathSegment, QSelf};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Token};
|
||||
use rustc_errors::{pluralize, Applicability, PResult};
|
||||
use rustc_span::source_map::{BytePos, Span};
|
||||
|
@ -405,7 +406,8 @@ impl<'a> Parser<'a> {
|
|||
let lo = self.token.span;
|
||||
let ident = self.parse_ident()?;
|
||||
let kind = if self.eat(&token::Eq) {
|
||||
AssocTyConstraintKind::Equality { ty: self.parse_ty()? }
|
||||
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
|
||||
AssocTyConstraintKind::Equality { ty }
|
||||
} else if self.eat(&token::Colon) {
|
||||
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
|
||||
AssocTyConstraintKind::Bound { bounds }
|
||||
|
@ -427,6 +429,46 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse the term to the right of an associated item equality constraint.
|
||||
/// That is, parse `<term>` in `Item = <term>`.
|
||||
/// Right now, this only admits types in `<term>`.
|
||||
fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P<ast::Ty>> {
|
||||
let arg = self.parse_generic_arg()?;
|
||||
let span = ident.span.to(self.prev_token.span);
|
||||
match arg {
|
||||
Some(GenericArg::Type(ty)) => return Ok(ty),
|
||||
Some(GenericArg::Const(expr)) => {
|
||||
self.struct_span_err(span, "cannot constrain an associated constant to a value")
|
||||
.span_label(ident.span, "the value constrains this associated constant")
|
||||
.span_label(expr.value.span, "the value is given in this expression")
|
||||
.emit();
|
||||
}
|
||||
Some(GenericArg::Lifetime(lt)) => {
|
||||
self.struct_span_err(span, "associated lifetimes are not supported")
|
||||
.span_label(lt.ident.span, "the lifetime is given here")
|
||||
.help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`")
|
||||
.emit();
|
||||
}
|
||||
None => {
|
||||
self.struct_span_err(span, "missing type to the right of `=`")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"to constrain the associated type, add a type after `=`",
|
||||
format!("{} = TheType", ident),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.span_suggestion(
|
||||
eq,
|
||||
&format!("remove the `=` if `{}` is a type", ident),
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
Ok(self.mk_ty(span, ast::TyKind::Err))
|
||||
}
|
||||
|
||||
/// Parse a generic argument in a path segment.
|
||||
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
||||
fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
|
||||
|
|
7
src/test/ui/parser/recover-assoc-const-constraint.rs
Normal file
7
src/test/ui/parser/recover-assoc-const-constraint.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
#[cfg(FALSE)]
|
||||
fn syntax() {
|
||||
bar::<Item = 42>(); //~ ERROR cannot constrain an associated constant to a value
|
||||
bar::<Item = { 42 }>(); //~ ERROR cannot constrain an associated constant to a value
|
||||
}
|
||||
|
||||
fn main() {}
|
20
src/test/ui/parser/recover-assoc-const-constraint.stderr
Normal file
20
src/test/ui/parser/recover-assoc-const-constraint.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error: cannot constrain an associated constant to a value
|
||||
--> $DIR/recover-assoc-const-constraint.rs:3:11
|
||||
|
|
||||
LL | bar::<Item = 42>();
|
||||
| ----^^^--
|
||||
| | |
|
||||
| | the value is given in this expression
|
||||
| the value constrains this associated constant
|
||||
|
||||
error: cannot constrain an associated constant to a value
|
||||
--> $DIR/recover-assoc-const-constraint.rs:4:11
|
||||
|
|
||||
LL | bar::<Item = { 42 }>();
|
||||
| ----^^^------
|
||||
| | |
|
||||
| | the value is given in this expression
|
||||
| the value constrains this associated constant
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
6
src/test/ui/parser/recover-assoc-eq-missing-term.rs
Normal file
6
src/test/ui/parser/recover-assoc-eq-missing-term.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
#[cfg(FALSE)]
|
||||
fn syntax() {
|
||||
bar::<Item = >(); //~ ERROR missing type to the right of `=`
|
||||
}
|
||||
|
||||
fn main() {}
|
17
src/test/ui/parser/recover-assoc-eq-missing-term.stderr
Normal file
17
src/test/ui/parser/recover-assoc-eq-missing-term.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error: missing type to the right of `=`
|
||||
--> $DIR/recover-assoc-eq-missing-term.rs:3:11
|
||||
|
|
||||
LL | bar::<Item = >();
|
||||
| ^^^^^^
|
||||
|
|
||||
help: to constrain the associated type, add a type after `=`
|
||||
|
|
||||
LL | bar::<Item = TheType >();
|
||||
| ^^^^^^^^^^^^^^
|
||||
help: remove the `=` if `Item` is a type
|
||||
|
|
||||
LL | bar::<Item >();
|
||||
| --
|
||||
|
||||
error: aborting due to previous error
|
||||
|
6
src/test/ui/parser/recover-assoc-lifetime-constraint.rs
Normal file
6
src/test/ui/parser/recover-assoc-lifetime-constraint.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
#[cfg(FALSE)]
|
||||
fn syntax() {
|
||||
bar::<Item = 'a>(); //~ ERROR associated lifetimes are not supported
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/parser/recover-assoc-lifetime-constraint.stderr
Normal file
12
src/test/ui/parser/recover-assoc-lifetime-constraint.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error: associated lifetimes are not supported
|
||||
--> $DIR/recover-assoc-lifetime-constraint.rs:3:11
|
||||
|
|
||||
LL | bar::<Item = 'a>();
|
||||
| ^^^^^^^--
|
||||
| |
|
||||
| the lifetime is given here
|
||||
|
|
||||
= help: if you meant to specify a trait object, write `dyn Trait + 'lifetime`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue