improve diagnostics for angle args
This commit is contained in:
parent
f2de221b00
commit
728d257839
3 changed files with 28 additions and 50 deletions
|
@ -2,14 +2,13 @@ use super::ty::AllowPlus;
|
||||||
use super::TokenType;
|
use super::TokenType;
|
||||||
use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType};
|
use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType};
|
||||||
|
|
||||||
|
use rustc_ast as ast;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
|
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::AssocOp;
|
||||||
use rustc_ast::{
|
use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec};
|
||||||
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
|
use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item};
|
||||||
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item, ItemKind, Mutability, Param, Pat,
|
use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind};
|
||||||
PatKind, Path, PathSegment, QSelf, Ty, TyKind,
|
|
||||||
};
|
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{pluralize, struct_span_err};
|
use rustc_errors::{pluralize, struct_span_err};
|
||||||
|
@ -220,6 +219,7 @@ impl<'a> Parser<'a> {
|
||||||
edible: &[TokenKind],
|
edible: &[TokenKind],
|
||||||
inedible: &[TokenKind],
|
inedible: &[TokenKind],
|
||||||
) -> PResult<'a, bool /* recovered */> {
|
) -> PResult<'a, bool /* recovered */> {
|
||||||
|
debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
|
||||||
fn tokens_to_string(tokens: &[TokenType]) -> String {
|
fn tokens_to_string(tokens: &[TokenType]) -> String {
|
||||||
let mut i = tokens.iter();
|
let mut i = tokens.iter();
|
||||||
// This might be a sign we need a connect method on `Iterator`.
|
// This might be a sign we need a connect method on `Iterator`.
|
||||||
|
@ -245,6 +245,7 @@ impl<'a> Parser<'a> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
expected.sort_by_cached_key(|x| x.to_string());
|
expected.sort_by_cached_key(|x| x.to_string());
|
||||||
expected.dedup();
|
expected.dedup();
|
||||||
|
|
||||||
let expect = tokens_to_string(&expected[..]);
|
let expect = tokens_to_string(&expected[..]);
|
||||||
let actual = super::token_descr(&self.token);
|
let actual = super::token_descr(&self.token);
|
||||||
let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
|
let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
|
||||||
|
@ -270,6 +271,16 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
self.last_unexpected_token_span = Some(self.token.span);
|
self.last_unexpected_token_span = Some(self.token.span);
|
||||||
let mut err = self.struct_span_err(self.token.span, &msg_exp);
|
let mut err = self.struct_span_err(self.token.span, &msg_exp);
|
||||||
|
|
||||||
|
// Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens
|
||||||
|
// there are unclosed angle brackets
|
||||||
|
if self.unmatched_angle_bracket_count > 0
|
||||||
|
&& self.token.kind == TokenKind::Eq
|
||||||
|
&& expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt)))
|
||||||
|
{
|
||||||
|
err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket");
|
||||||
|
}
|
||||||
|
|
||||||
let sp = if self.token == token::Eof {
|
let sp = if self.token == token::Eof {
|
||||||
// This is EOF; don't want to point at the following char, but rather the last token.
|
// This is EOF; don't want to point at the following char, but rather the last token.
|
||||||
self.prev_token.span
|
self.prev_token.span
|
||||||
|
|
|
@ -272,7 +272,7 @@ impl TokenCursor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
enum TokenType {
|
enum TokenType {
|
||||||
Token(TokenKind),
|
Token(TokenKind),
|
||||||
Keyword(Symbol),
|
Keyword(Symbol),
|
||||||
|
|
|
@ -185,7 +185,6 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
|
pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
|
||||||
let ident = self.parse_path_segment_ident()?;
|
let ident = self.parse_path_segment_ident()?;
|
||||||
|
|
||||||
let is_args_start = |token: &Token| {
|
let is_args_start = |token: &Token| {
|
||||||
matches!(
|
matches!(
|
||||||
token.kind,
|
token.kind,
|
||||||
|
@ -420,7 +419,10 @@ impl<'a> Parser<'a> {
|
||||||
match arg {
|
match arg {
|
||||||
Some(arg) => {
|
Some(arg) => {
|
||||||
if self.check(&token::Colon) | self.check(&token::Eq) {
|
if self.check(&token::Colon) | self.check(&token::Eq) {
|
||||||
let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?;
|
let (ident, gen_args) = match self.get_ident_from_generic_arg(arg) {
|
||||||
|
Ok(ident_gen_args) => ident_gen_args,
|
||||||
|
Err(arg) => return Ok(Some(AngleBracketedArg::Arg(arg))),
|
||||||
|
};
|
||||||
let kind = if self.eat(&token::Colon) {
|
let kind = if self.eat(&token::Colon) {
|
||||||
// Parse associated type constraint bound.
|
// Parse associated type constraint bound.
|
||||||
|
|
||||||
|
@ -561,50 +563,15 @@ impl<'a> Parser<'a> {
|
||||||
fn get_ident_from_generic_arg(
|
fn get_ident_from_generic_arg(
|
||||||
&self,
|
&self,
|
||||||
gen_arg: GenericArg,
|
gen_arg: GenericArg,
|
||||||
lo: Span,
|
) -> Result<(Ident, Option<GenericArgs>), GenericArg> {
|
||||||
) -> PResult<'a, (Ident, Option<GenericArgs>)> {
|
if let GenericArg::Type(ty) = &gen_arg {
|
||||||
let gen_arg_span = gen_arg.span();
|
if let ast::TyKind::Path(qself, path) = &ty.kind {
|
||||||
match gen_arg {
|
if qself.is_none() && path.segments.len() == 1 {
|
||||||
GenericArg::Type(t) => match t.into_inner().kind {
|
let seg = &path.segments[0];
|
||||||
ast::TyKind::Path(qself, mut path) => {
|
return Ok((seg.ident, seg.args.as_deref().cloned()));
|
||||||
if let Some(qself) = qself {
|
|
||||||
let mut err = self.struct_span_err(
|
|
||||||
gen_arg_span,
|
|
||||||
"qualified paths cannot be used in associated type constraints",
|
|
||||||
);
|
|
||||||
err.span_label(
|
|
||||||
qself.path_span,
|
|
||||||
"not allowed in associated type constraints",
|
|
||||||
);
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
if path.segments.len() == 1 {
|
|
||||||
let path_seg = path.segments.remove(0);
|
|
||||||
let ident = path_seg.ident;
|
|
||||||
let gen_args = path_seg.args.map(|args| args.into_inner());
|
|
||||||
return Ok((ident, gen_args));
|
|
||||||
}
|
|
||||||
let err = self.struct_span_err(
|
|
||||||
path.span,
|
|
||||||
"paths with multiple segments cannot be used in associated type constraints",
|
|
||||||
);
|
|
||||||
return Err(err);
|
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
let span = lo.to(self.prev_token.span);
|
|
||||||
let err = self.struct_span_err(
|
|
||||||
span,
|
|
||||||
"only path types can be used in associated type constraints",
|
|
||||||
);
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
let span = lo.to(self.prev_token.span);
|
|
||||||
let err = self
|
|
||||||
.struct_span_err(span, "only types can be used in associated type constraints");
|
|
||||||
return Err(err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(gen_arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue