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::{self, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs};
|
||||||
use rustc_ast::ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
use rustc_ast::ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
||||||
use rustc_ast::ast::{Ident, Path, PathSegment, QSelf};
|
use rustc_ast::ast::{Ident, Path, PathSegment, QSelf};
|
||||||
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Token};
|
use rustc_ast::token::{self, Token};
|
||||||
use rustc_errors::{pluralize, Applicability, PResult};
|
use rustc_errors::{pluralize, Applicability, PResult};
|
||||||
use rustc_span::source_map::{BytePos, Span};
|
use rustc_span::source_map::{BytePos, Span};
|
||||||
|
@ -405,7 +406,8 @@ impl<'a> Parser<'a> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
let kind = if self.eat(&token::Eq) {
|
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) {
|
} else if self.eat(&token::Colon) {
|
||||||
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
|
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
|
||||||
AssocTyConstraintKind::Bound { bounds }
|
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.
|
/// Parse a generic argument in a path segment.
|
||||||
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
|
/// 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>> {
|
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