parse: improve recovery for assoc eq constraints.

This commit is contained in:
Mazdak Farrokhzad 2020-03-22 06:09:24 +01:00
parent f91de44d07
commit 2972bb37b8
7 changed files with 111 additions and 1 deletions

View file

@ -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>> {

View 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() {}

View 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

View file

@ -0,0 +1,6 @@
#[cfg(FALSE)]
fn syntax() {
bar::<Item = >(); //~ ERROR missing type to the right of `=`
}
fn main() {}

View 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

View file

@ -0,0 +1,6 @@
#[cfg(FALSE)]
fn syntax() {
bar::<Item = 'a>(); //~ ERROR associated lifetimes are not supported
}
fn main() {}

View 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