Skip to content

Commit 728d257

Browse files
committed
improve diagnostics for angle args
1 parent f2de221 commit 728d257

File tree

3 files changed

+28
-50
lines changed

3 files changed

+28
-50
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ use super::ty::AllowPlus;
22
use super::TokenType;
33
use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType};
44

5+
use rustc_ast as ast;
56
use rustc_ast::ptr::P;
67
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
78
use rustc_ast::util::parser::AssocOp;
8-
use rustc_ast::{
9-
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
10-
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item, ItemKind, Mutability, Param, Pat,
11-
PatKind, Path, PathSegment, QSelf, Ty, TyKind,
12-
};
9+
use rustc_ast::{AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec};
10+
use rustc_ast::{BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, Item};
11+
use rustc_ast::{ItemKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QSelf, Ty, TyKind};
1312
use rustc_ast_pretty::pprust;
1413
use rustc_data_structures::fx::FxHashSet;
1514
use rustc_errors::{pluralize, struct_span_err};
@@ -220,6 +219,7 @@ impl<'a> Parser<'a> {
220219
edible: &[TokenKind],
221220
inedible: &[TokenKind],
222221
) -> PResult<'a, bool /* recovered */> {
222+
debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
223223
fn tokens_to_string(tokens: &[TokenType]) -> String {
224224
let mut i = tokens.iter();
225225
// This might be a sign we need a connect method on `Iterator`.
@@ -245,6 +245,7 @@ impl<'a> Parser<'a> {
245245
.collect::<Vec<_>>();
246246
expected.sort_by_cached_key(|x| x.to_string());
247247
expected.dedup();
248+
248249
let expect = tokens_to_string(&expected[..]);
249250
let actual = super::token_descr(&self.token);
250251
let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
@@ -270,6 +271,16 @@ impl<'a> Parser<'a> {
270271
};
271272
self.last_unexpected_token_span = Some(self.token.span);
272273
let mut err = self.struct_span_err(self.token.span, &msg_exp);
274+
275+
// Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens
276+
// there are unclosed angle brackets
277+
if self.unmatched_angle_bracket_count > 0
278+
&& self.token.kind == TokenKind::Eq
279+
&& expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt)))
280+
{
281+
err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket");
282+
}
283+
273284
let sp = if self.token == token::Eof {
274285
// This is EOF; don't want to point at the following char, but rather the last token.
275286
self.prev_token.span

compiler/rustc_parse/src/parser/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl TokenCursor {
272272
}
273273
}
274274

275-
#[derive(Clone, PartialEq)]
275+
#[derive(Debug, Clone, PartialEq)]
276276
enum TokenType {
277277
Token(TokenKind),
278278
Keyword(Symbol),

compiler/rustc_parse/src/parser/path.rs

+11-44
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ impl<'a> Parser<'a> {
185185

186186
pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
187187
let ident = self.parse_path_segment_ident()?;
188-
189188
let is_args_start = |token: &Token| {
190189
matches!(
191190
token.kind,
@@ -420,7 +419,10 @@ impl<'a> Parser<'a> {
420419
match arg {
421420
Some(arg) => {
422421
if self.check(&token::Colon) | self.check(&token::Eq) {
423-
let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?;
422+
let (ident, gen_args) = match self.get_ident_from_generic_arg(arg) {
423+
Ok(ident_gen_args) => ident_gen_args,
424+
Err(arg) => return Ok(Some(AngleBracketedArg::Arg(arg))),
425+
};
424426
let kind = if self.eat(&token::Colon) {
425427
// Parse associated type constraint bound.
426428

@@ -561,50 +563,15 @@ impl<'a> Parser<'a> {
561563
fn get_ident_from_generic_arg(
562564
&self,
563565
gen_arg: GenericArg,
564-
lo: Span,
565-
) -> PResult<'a, (Ident, Option<GenericArgs>)> {
566-
let gen_arg_span = gen_arg.span();
567-
match gen_arg {
568-
GenericArg::Type(t) => match t.into_inner().kind {
569-
ast::TyKind::Path(qself, mut path) => {
570-
if let Some(qself) = qself {
571-
let mut err = self.struct_span_err(
572-
gen_arg_span,
573-
"qualified paths cannot be used in associated type constraints",
574-
);
575-
err.span_label(
576-
qself.path_span,
577-
"not allowed in associated type constraints",
578-
);
579-
return Err(err);
580-
}
581-
if path.segments.len() == 1 {
582-
let path_seg = path.segments.remove(0);
583-
let ident = path_seg.ident;
584-
let gen_args = path_seg.args.map(|args| args.into_inner());
585-
return Ok((ident, gen_args));
586-
}
587-
let err = self.struct_span_err(
588-
path.span,
589-
"paths with multiple segments cannot be used in associated type constraints",
590-
);
591-
return Err(err);
592-
}
593-
_ => {
594-
let span = lo.to(self.prev_token.span);
595-
let err = self.struct_span_err(
596-
span,
597-
"only path types can be used in associated type constraints",
598-
);
599-
return Err(err);
566+
) -> Result<(Ident, Option<GenericArgs>), GenericArg> {
567+
if let GenericArg::Type(ty) = &gen_arg {
568+
if let ast::TyKind::Path(qself, path) = &ty.kind {
569+
if qself.is_none() && path.segments.len() == 1 {
570+
let seg = &path.segments[0];
571+
return Ok((seg.ident, seg.args.as_deref().cloned()));
600572
}
601-
},
602-
_ => {
603-
let span = lo.to(self.prev_token.span);
604-
let err = self
605-
.struct_span_err(span, "only types can be used in associated type constraints");
606-
return Err(err);
607573
}
608574
}
575+
Err(gen_arg)
609576
}
610577
}

0 commit comments

Comments
 (0)