Recover unclosed char literal being parsed as lifetime
This commit is contained in:
parent
cde693cf96
commit
0270b50eb0
11 changed files with 209 additions and 23 deletions
|
@ -461,6 +461,9 @@ pub enum StashKey {
|
||||||
UnderscoreForArrayLengths,
|
UnderscoreForArrayLengths,
|
||||||
EarlySyntaxWarning,
|
EarlySyntaxWarning,
|
||||||
CallIntoMethod,
|
CallIntoMethod,
|
||||||
|
/// When an invalid lifetime e.g. `'2` should be reinterpreted
|
||||||
|
/// as a char literal in the parser
|
||||||
|
LifetimeIsChar,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_track_diagnostic(_: &Diagnostic) {}
|
fn default_track_diagnostic(_: &Diagnostic) {}
|
||||||
|
|
|
@ -3,7 +3,9 @@ use rustc_ast::ast::{self, AttrStyle};
|
||||||
use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
|
use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast::util::unicode::contains_text_flow_control_chars;
|
use rustc_ast::util::unicode::contains_text_flow_control_chars;
|
||||||
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
use rustc_errors::{
|
||||||
|
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult, StashKey,
|
||||||
|
};
|
||||||
use rustc_lexer::unescape::{self, Mode};
|
use rustc_lexer::unescape::{self, Mode};
|
||||||
use rustc_lexer::Cursor;
|
use rustc_lexer::Cursor;
|
||||||
use rustc_lexer::{Base, DocStyle, RawStrError};
|
use rustc_lexer::{Base, DocStyle, RawStrError};
|
||||||
|
@ -203,7 +205,10 @@ impl<'a> StringReader<'a> {
|
||||||
// this is necessary.
|
// this is necessary.
|
||||||
let lifetime_name = self.str_from(start);
|
let lifetime_name = self.str_from(start);
|
||||||
if starts_with_number {
|
if starts_with_number {
|
||||||
self.err_span_(start, self.pos, "lifetimes cannot start with a number");
|
let span = self.mk_sp(start, self.pos);
|
||||||
|
let mut diag = self.sess.struct_err("lifetimes cannot start with a number");
|
||||||
|
diag.set_span(span);
|
||||||
|
diag.stash(span, StashKey::LifetimeIsChar);
|
||||||
}
|
}
|
||||||
let ident = Symbol::intern(lifetime_name);
|
let ident = Symbol::intern(lifetime_name);
|
||||||
token::Lifetime(ident)
|
token::Lifetime(ident)
|
||||||
|
|
|
@ -42,8 +42,10 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
|
||||||
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
|
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
|
||||||
use rustc_ast::{ClosureBinder, StmtKind};
|
use rustc_ast::{ClosureBinder, StmtKind};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::IntoDiagnostic;
|
use rustc_errors::{
|
||||||
use rustc_errors::{Applicability, Diagnostic, PResult};
|
Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
|
||||||
|
StashKey,
|
||||||
|
};
|
||||||
use rustc_session::errors::ExprParenthesesNeeded;
|
use rustc_session::errors::ExprParenthesesNeeded;
|
||||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||||
|
@ -1513,11 +1515,11 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse `'label: $expr`. The label is already parsed.
|
/// Parse `'label: $expr`. The label is already parsed.
|
||||||
fn parse_labeled_expr(
|
fn parse_labeled_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
label: Label,
|
label_: Label,
|
||||||
mut consume_colon: bool,
|
mut consume_colon: bool,
|
||||||
) -> PResult<'a, P<Expr>> {
|
) -> PResult<'a, P<Expr>> {
|
||||||
let lo = label.ident.span;
|
let lo = label_.ident.span;
|
||||||
let label = Some(label);
|
let label = Some(label_);
|
||||||
let ate_colon = self.eat(&token::Colon);
|
let ate_colon = self.eat(&token::Colon);
|
||||||
let expr = if self.eat_keyword(kw::While) {
|
let expr = if self.eat_keyword(kw::While) {
|
||||||
self.parse_while_expr(label, lo)
|
self.parse_while_expr(label, lo)
|
||||||
|
@ -1529,6 +1531,19 @@ impl<'a> Parser<'a> {
|
||||||
|| self.token.is_whole_block()
|
|| self.token.is_whole_block()
|
||||||
{
|
{
|
||||||
self.parse_block_expr(label, lo, BlockCheckMode::Default)
|
self.parse_block_expr(label, lo, BlockCheckMode::Default)
|
||||||
|
} else if !ate_colon
|
||||||
|
&& (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
|
||||||
|
|| self.token.is_op())
|
||||||
|
{
|
||||||
|
let lit = self.recover_unclosed_char(label_.ident, |self_| {
|
||||||
|
self_.sess.create_err(UnexpectedTokenAfterLabel {
|
||||||
|
span: self_.token.span,
|
||||||
|
remove_label: None,
|
||||||
|
enclose_in_block: None,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
consume_colon = false;
|
||||||
|
Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
|
||||||
} else if !ate_colon
|
} else if !ate_colon
|
||||||
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
|
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
|
||||||
{
|
{
|
||||||
|
@ -1603,6 +1618,39 @@ impl<'a> Parser<'a> {
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emit an error when a char is parsed as a lifetime because of a missing quote
|
||||||
|
pub(super) fn recover_unclosed_char(
|
||||||
|
&mut self,
|
||||||
|
lifetime: Ident,
|
||||||
|
err: impl FnOnce(&mut Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
|
||||||
|
) -> ast::Lit {
|
||||||
|
if let Some(mut diag) =
|
||||||
|
self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
|
||||||
|
{
|
||||||
|
diag.span_suggestion_verbose(
|
||||||
|
lifetime.span.shrink_to_hi(),
|
||||||
|
"add `'` to close the char literal",
|
||||||
|
"'",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
} else {
|
||||||
|
err(self)
|
||||||
|
.span_suggestion_verbose(
|
||||||
|
lifetime.span.shrink_to_hi(),
|
||||||
|
"add `'` to close the char literal",
|
||||||
|
"'",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
ast::Lit {
|
||||||
|
token_lit: token::Lit::new(token::LitKind::Char, lifetime.name, None),
|
||||||
|
kind: ast::LitKind::Char(lifetime.name.as_str().chars().next().unwrap_or('_')),
|
||||||
|
span: lifetime.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
|
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
|
||||||
fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
|
fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
@ -1728,7 +1776,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
|
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
|
||||||
self.parse_opt_lit().ok_or_else(|| {
|
self.parse_opt_lit().ok_or(()).or_else(|()| {
|
||||||
if let token::Interpolated(inner) = &self.token.kind {
|
if let token::Interpolated(inner) = &self.token.kind {
|
||||||
let expr = match inner.as_ref() {
|
let expr = match inner.as_ref() {
|
||||||
token::NtExpr(expr) => Some(expr),
|
token::NtExpr(expr) => Some(expr),
|
||||||
|
@ -1740,12 +1788,22 @@ impl<'a> Parser<'a> {
|
||||||
let mut err = InvalidInterpolatedExpression { span: self.token.span }
|
let mut err = InvalidInterpolatedExpression { span: self.token.span }
|
||||||
.into_diagnostic(&self.sess.span_diagnostic);
|
.into_diagnostic(&self.sess.span_diagnostic);
|
||||||
err.downgrade_to_delayed_bug();
|
err.downgrade_to_delayed_bug();
|
||||||
return err;
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let msg = format!("unexpected token: {}", super::token_descr(&self.token));
|
let token = self.token.clone();
|
||||||
self.struct_span_err(self.token.span, &msg)
|
let err = |self_: &mut Self| {
|
||||||
|
let msg = format!("unexpected token: {}", super::token_descr(&token));
|
||||||
|
self_.struct_span_err(token.span, &msg)
|
||||||
|
};
|
||||||
|
// On an error path, eagerly consider a lifetime to be an unclosed character lit
|
||||||
|
if self.token.is_lifetime() {
|
||||||
|
let lt = self.expect_lifetime();
|
||||||
|
Ok(self.recover_unclosed_char(lt.ident, err))
|
||||||
|
} else {
|
||||||
|
Err(err(self))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -402,6 +402,25 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
PatKind::Path(qself, path)
|
PatKind::Path(qself, path)
|
||||||
}
|
}
|
||||||
|
} else if matches!(self.token.kind, token::Lifetime(_))
|
||||||
|
// In pattern position, we're totally fine with using "next token isn't colon"
|
||||||
|
// as a heuristic. We could probably just always try to recover if it's a lifetime,
|
||||||
|
// because we never have `'a: label {}` in a pattern position anyways, but it does
|
||||||
|
// keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..`
|
||||||
|
&& !self.look_ahead(1, |token| matches!(token.kind, token::Colon))
|
||||||
|
{
|
||||||
|
// Recover a `'a` as a `'a'` literal
|
||||||
|
let lt = self.expect_lifetime();
|
||||||
|
let lit = self.recover_unclosed_char(lt.ident, |self_| {
|
||||||
|
let expected = expected.unwrap_or("pattern");
|
||||||
|
let msg =
|
||||||
|
format!("expected {}, found {}", expected, super::token_descr(&self_.token));
|
||||||
|
|
||||||
|
let mut err = self_.struct_span_err(self_.token.span, &msg);
|
||||||
|
err.span_label(self_.token.span, format!("expected {}", expected));
|
||||||
|
err
|
||||||
|
});
|
||||||
|
PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
|
||||||
} else {
|
} else {
|
||||||
// Try to parse everything else as literal with optional minus
|
// Try to parse everything else as literal with optional minus
|
||||||
match self.parse_literal_maybe_minus() {
|
match self.parse_literal_maybe_minus() {
|
||||||
|
@ -799,6 +818,7 @@ impl<'a> Parser<'a> {
|
||||||
|| t.kind == token::Dot // e.g. `.5` for recovery;
|
|| t.kind == token::Dot // e.g. `.5` for recovery;
|
||||||
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
|
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
|
||||||
|| t.is_whole_expr()
|
|| t.is_whole_expr()
|
||||||
|
|| t.is_lifetime() // recover `'a` instead of `'a'`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,5 @@ fn foo() {
|
||||||
let x = 1;
|
let x = 1;
|
||||||
bar('y, x);
|
bar('y, x);
|
||||||
//~^ ERROR expected
|
//~^ ERROR expected
|
||||||
|
//~| ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
|
||||||
LL | f<'a,>
|
LL | f<'a,>
|
||||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | f<'a',>
|
||||||
|
| +
|
||||||
|
|
||||||
error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,`
|
error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,`
|
||||||
--> $DIR/issue-93282.rs:2:9
|
--> $DIR/issue-93282.rs:2:9
|
||||||
|
@ -20,6 +25,26 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
|
||||||
LL | bar('y, x);
|
LL | bar('y, x);
|
||||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | bar('y', x);
|
||||||
|
| +
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-93282.rs:13:9
|
||||||
|
|
|
||||||
|
LL | bar('y, x);
|
||||||
|
| --- ^^ expected `usize`, found `char`
|
||||||
|
| |
|
||||||
|
| arguments to this function are incorrect
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/issue-93282.rs:7:4
|
||||||
|
|
|
||||||
|
LL | fn bar(a: usize, b: usize) -> usize {
|
||||||
|
| ^^^ --------
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
16
src/test/ui/parser/label-is-actually-char.rs
Normal file
16
src/test/ui/parser/label-is-actually-char.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
fn main() {
|
||||||
|
let c = 'a;
|
||||||
|
//~^ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
//~| HELP add `'` to close the char literal
|
||||||
|
match c {
|
||||||
|
'a'..='b => {}
|
||||||
|
//~^ ERROR unexpected token: `'b`
|
||||||
|
//~| HELP add `'` to close the char literal
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
let x = ['a, 'b];
|
||||||
|
//~^ ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
//~| ERROR expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
//~| HELP add `'` to close the char literal
|
||||||
|
//~| HELP add `'` to close the char literal
|
||||||
|
}
|
46
src/test/ui/parser/label-is-actually-char.stderr
Normal file
46
src/test/ui/parser/label-is-actually-char.stderr
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
--> $DIR/label-is-actually-char.rs:2:15
|
||||||
|
|
|
||||||
|
LL | let c = 'a;
|
||||||
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | let c = 'a';
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: unexpected token: `'b`
|
||||||
|
--> $DIR/label-is-actually-char.rs:6:15
|
||||||
|
|
|
||||||
|
LL | 'a'..='b => {}
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | 'a'..='b' => {}
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
--> $DIR/label-is-actually-char.rs:11:16
|
||||||
|
|
|
||||||
|
LL | let x = ['a, 'b];
|
||||||
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | let x = ['a', 'b];
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
--> $DIR/label-is-actually-char.rs:11:20
|
||||||
|
|
|
||||||
|
LL | let x = ['a, 'b];
|
||||||
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | let x = ['a, 'b'];
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/numeric-lifetime.rs:6:20
|
||||||
|
|
|
||||||
|
LL | let x: usize = "";
|
||||||
|
| ----- ^^ expected `usize`, found `&str`
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
||||||
error: lifetimes cannot start with a number
|
error: lifetimes cannot start with a number
|
||||||
--> $DIR/numeric-lifetime.rs:1:10
|
--> $DIR/numeric-lifetime.rs:1:10
|
||||||
|
|
|
|
||||||
|
@ -10,14 +18,6 @@ error: lifetimes cannot start with a number
|
||||||
LL | struct S<'1> { s: &'1 usize }
|
LL | struct S<'1> { s: &'1 usize }
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/numeric-lifetime.rs:6:20
|
|
||||||
|
|
|
||||||
LL | let x: usize = "";
|
|
||||||
| ----- ^^ expected `usize`, found `&str`
|
|
||||||
| |
|
|
||||||
| expected due to this
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -23,11 +23,13 @@ fn main() {
|
||||||
//~^ ERROR expected one of
|
//~^ ERROR expected one of
|
||||||
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
//~| ERROR expected
|
//~| ERROR expected
|
||||||
|
//~| HELP add `'` to close the char literal
|
||||||
|
|
||||||
f<'_>();
|
f<'_>();
|
||||||
//~^ comparison operators cannot be chained
|
//~^ comparison operators cannot be chained
|
||||||
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
//~| ERROR expected
|
//~| ERROR expected
|
||||||
|
//~| HELP add `'` to close the char literal
|
||||||
|
|
||||||
let _ = f<u8>;
|
let _ = f<u8>;
|
||||||
//~^ ERROR comparison operators cannot be chained
|
//~^ ERROR comparison operators cannot be chained
|
||||||
|
|
|
@ -58,6 +58,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
|
||||||
LL | let _ = f<'_, i8>();
|
LL | let _ = f<'_, i8>();
|
||||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | let _ = f<'_', i8>();
|
||||||
|
| +
|
||||||
|
|
||||||
error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,`
|
error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,`
|
||||||
--> $DIR/require-parens-for-chained-comparison.rs:22:17
|
--> $DIR/require-parens-for-chained-comparison.rs:22:17
|
||||||
|
@ -71,13 +76,18 @@ LL | let _ = f::<'_, i8>();
|
||||||
| ++
|
| ++
|
||||||
|
|
||||||
error: expected `while`, `for`, `loop` or `{` after a label
|
error: expected `while`, `for`, `loop` or `{` after a label
|
||||||
--> $DIR/require-parens-for-chained-comparison.rs:27:9
|
--> $DIR/require-parens-for-chained-comparison.rs:28:9
|
||||||
|
|
|
|
||||||
LL | f<'_>();
|
LL | f<'_>();
|
||||||
| ^ expected `while`, `for`, `loop` or `{` after a label
|
| ^ expected `while`, `for`, `loop` or `{` after a label
|
||||||
|
|
|
||||||
|
help: add `'` to close the char literal
|
||||||
|
|
|
||||||
|
LL | f<'_'>();
|
||||||
|
| +
|
||||||
|
|
||||||
error: comparison operators cannot be chained
|
error: comparison operators cannot be chained
|
||||||
--> $DIR/require-parens-for-chained-comparison.rs:27:6
|
--> $DIR/require-parens-for-chained-comparison.rs:28:6
|
||||||
|
|
|
|
||||||
LL | f<'_>();
|
LL | f<'_>();
|
||||||
| ^ ^
|
| ^ ^
|
||||||
|
@ -88,7 +98,7 @@ LL | f::<'_>();
|
||||||
| ++
|
| ++
|
||||||
|
|
||||||
error: comparison operators cannot be chained
|
error: comparison operators cannot be chained
|
||||||
--> $DIR/require-parens-for-chained-comparison.rs:32:14
|
--> $DIR/require-parens-for-chained-comparison.rs:34:14
|
||||||
|
|
|
|
||||||
LL | let _ = f<u8>;
|
LL | let _ = f<u8>;
|
||||||
| ^ ^
|
| ^ ^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue