Skip to content

Commit 63ad0a4

Browse files
committed
Mark incorrect recovered char literals as TyErr to avoid type errors
1 parent e9af312 commit 63ad0a4

18 files changed

+82
-102
lines changed

src/librustc/ich/impls_syntax.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
164164
impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
165165
impl_stable_hash_for!(enum ::syntax::ast::LitKind {
166166
Str(value, style),
167+
Err(value),
167168
ByteStr(value),
168169
Byte(value),
169170
Char(value),

src/librustc_mir/hair/constant.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
3737
let id = tcx.allocate_bytes(s.as_bytes());
3838
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
3939
},
40+
LitKind::Err(ref s) => {
41+
let s = s.as_str();
42+
let id = tcx.allocate_bytes(s.as_bytes());
43+
return Ok(ty::Const {
44+
val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx),
45+
ty: tcx.types.err,
46+
});
47+
}
4048
LitKind::ByteStr(ref data) => {
4149
let id = tcx.allocate_bytes(data);
4250
ConstValue::Scalar(Scalar::Ptr(id.into()))

src/librustc_typeck/check/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3121,7 +3121,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31213121
opt_ty.unwrap_or_else(
31223122
|| tcx.mk_float_var(self.next_float_var_id()))
31233123
}
3124-
ast::LitKind::Bool(_) => tcx.types.bool
3124+
ast::LitKind::Bool(_) => tcx.types.bool,
3125+
ast::LitKind::Err(_) => tcx.types.err,
31253126
}
31263127
}
31273128

src/libsyntax/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,8 @@ pub enum LitKind {
12851285
FloatUnsuffixed(Symbol),
12861286
/// A boolean literal.
12871287
Bool(bool),
1288+
/// A recovered character literal that contains multiple `char`s, most likely a typo.
1289+
Err(Symbol),
12881290
}
12891291

12901292
impl LitKind {
@@ -1321,6 +1323,7 @@ impl LitKind {
13211323
| LitKind::ByteStr(..)
13221324
| LitKind::Byte(..)
13231325
| LitKind::Char(..)
1326+
| LitKind::Err(..)
13241327
| LitKind::Int(_, LitIntType::Unsuffixed)
13251328
| LitKind::FloatUnsuffixed(..)
13261329
| LitKind::Bool(..) => true,

src/libsyntax/attr/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ impl LitKind {
661661
} else {
662662
"false"
663663
})), false),
664+
LitKind::Err(val) => Token::Literal(token::Lit::Err(val), None),
664665
}
665666
}
666667

src/libsyntax/parse/lexer/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,9 +1456,8 @@ impl<'a> StringReader<'a> {
14561456
}
14571457
}
14581458

1459-
self.err_span_(start_with_quote, pos,
1460-
"character literal may only contain one codepoint");
1461-
self.bump();
1459+
self.fatal_span_verbose(start_with_quote, pos,
1460+
String::from("character literal may only contain one codepoint")).raise();
14621461
}
14631462

14641463
let id = if valid {

src/libsyntax/parse/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ crate fn lit_token(lit: token::Lit, suf: Option<Symbol>, diag: Option<(Span, &Ha
466466
match lit {
467467
token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))),
468468
token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))),
469-
token::Err(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))),
469+
token::Err(i) => (true, Some(LitKind::Err(i))),
470470

471471
// There are some valid suffixes for integer and float literals,
472472
// so all the handling is done internally.

src/libsyntax/parse/token.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,7 @@ impl Token {
473473

474474
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot |
475475
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
476-
Question | OpenDelim(..) | CloseDelim(..) => return None,
477-
476+
Question | OpenDelim(..) | CloseDelim(..) |
478477
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
479478
Whitespace | Comment | Shebang(..) | Eof => return None,
480479
})

src/libsyntax/print/pprust.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,14 @@ pub trait PrintState<'a> {
604604
}
605605
match lit.node {
606606
ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
607+
ast::LitKind::Err(st) => {
608+
let st = st.as_str().escape_debug();
609+
let mut res = String::with_capacity(st.len() + 2);
610+
res.push('\'');
611+
res.push_str(&st);
612+
res.push('\'');
613+
self.writer().word(res)
614+
}
607615
ast::LitKind::Byte(byte) => {
608616
let mut res = String::from("b'");
609617
res.extend(ascii::escape_default(byte).map(|c| c as char));

src/libsyntax_ext/concat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub fn expand_syntax_ext(
2323
match e.node {
2424
ast::ExprKind::Lit(ref lit) => match lit.node {
2525
ast::LitKind::Str(ref s, _)
26+
| ast::LitKind::Err(ref s)
2627
| ast::LitKind::Float(ref s, _)
2728
| ast::LitKind::FloatUnsuffixed(ref s) => {
2829
accumulator.push_str(&s.as_str());

src/test/ui/parser/lex-bad-char-literals-2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error: character literal may only contain one codepoint
22
--> $DIR/lex-bad-char-literals-2.rs:3:5
33
|
4-
LL | 'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
4+
LL | 'nope' //~ ERROR: character literal may only contain one codepoint
55
| ^^^^^^
66

77
error[E0601]: `main` function not found in crate `lex_bad_char_literals_2`
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
// This test needs to the last one appearing in this file as it kills the parser
2-
static c: char =
3-
'●●' //~ ERROR: character literal may only contain one codepoint
4-
;
1+
static c: char = '●●';
2+
//~^ ERROR: character literal may only contain one codepoint
53

64
fn main() {
7-
let ch: &str = '●●'; //~ ERROR: character literal may only contain one codepoint
8-
//~^ ERROR: mismatched types
5+
let ch: &str = '●●';
6+
//~^ ERROR: character literal may only contain one codepoint
97
}
Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,22 @@
11
error: character literal may only contain one codepoint
2-
--> $DIR/lex-bad-char-literals-3.rs:3:5
2+
--> $DIR/lex-bad-char-literals-3.rs:1:18
33
|
4-
LL | '●●' //~ ERROR: character literal may only contain one codepoint
5-
| ^^^^
4+
LL | static c: char = '●●';
5+
| ^^^^
66
help: if you meant to write a `str` literal, use double quotes
77
|
8-
LL | "●●" //~ ERROR: character literal may only contain one codepoint
9-
| ^^^^
8+
LL | static c: char = "●●";
9+
| ^^^^
1010

1111
error: character literal may only contain one codepoint
12-
--> $DIR/lex-bad-char-literals-3.rs:7:20
12+
--> $DIR/lex-bad-char-literals-3.rs:5:20
1313
|
14-
LL | let ch: &str = '●●'; //~ ERROR: character literal may only contain one codepoint
14+
LL | let ch: &str = '●●';
1515
| ^^^^
1616
help: if you meant to write a `str` literal, use double quotes
1717
|
18-
LL | let ch: &str = "●●"; //~ ERROR: character literal may only contain one codepoint
18+
LL | let ch: &str = "●●";
1919
| ^^^^
2020

21-
error[E0308]: mismatched types
22-
--> $DIR/lex-bad-char-literals-3.rs:7:20
23-
|
24-
LL | let ch: &str = '●●'; //~ ERROR: character literal may only contain one codepoint
25-
| ^^^^ expected &str, found char
26-
|
27-
= note: expected type `&str`
28-
found type `char`
29-
30-
error: aborting due to 3 previous errors
21+
error: aborting due to 2 previous errors
3122

32-
For more information about this error, try `rustc --explain E0308`.
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,8 @@
1-
error: character literal may only contain one codepoint
1+
error: character literal may only contain one codepoint: '●
22
--> $DIR/lex-bad-char-literals-4.rs:4:5
33
|
4-
LL | '● //~ ERROR: character literal may only contain one codepoint: '●
4+
LL | '● //~ ERROR: character literal may only contain one codepoint
55
| ^^
66

7-
error: character literal may only contain one codepoint
8-
--> $DIR/lex-bad-char-literals-4.rs:4:70
9-
|
10-
LL | '● //~ ERROR: character literal may only contain one codepoint: '●
11-
| ^^
12-
13-
error: expected one of `.`, `;`, `?`, or an operator, found `~`
14-
--> $DIR/lex-bad-char-literals-4.rs:4:11
15-
|
16-
LL | '● //~ ERROR: character literal may only contain one codepoint: '●
17-
| ^ expected one of `.`, `;`, `?`, or an operator here
18-
19-
error: aborting due to 3 previous errors
7+
error: aborting due to previous error
208

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
//
2-
// This test needs to the last one appearing in this file as it kills the parser
3-
static c: char =
4-
'\x10\x10' //~ ERROR: character literal may only contain one codepoint
5-
;
1+
static c: char = '\x10\x10';
2+
//~^ ERROR: character literal may only contain one codepoint
63

74
fn main() {
8-
let ch: &str = '\x10\x10'; //~ ERROR: character literal may only contain one codepoint
9-
//~^ ERROR: mismatched types
5+
let ch: &str = '\x10\x10';
6+
//~^ ERROR: character literal may only contain one codepoint
107
}
Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,22 @@
11
error: character literal may only contain one codepoint
2-
--> $DIR/lex-bad-char-literals-5.rs:4:5
2+
--> $DIR/lex-bad-char-literals-5.rs:1:18
33
|
4-
LL | '/x10/x10' //~ ERROR: character literal may only contain one codepoint
5-
| ^^^^^^^^^^
4+
LL | static c: char = '/x10/x10';
5+
| ^^^^^^^^^^
66
help: if you meant to write a `str` literal, use double quotes
77
|
8-
LL | "/x10/x10" //~ ERROR: character literal may only contain one codepoint
9-
| ^^^^^^^^^^
8+
LL | static c: char = "/x10/x10";
9+
| ^^^^^^^^^^
1010

1111
error: character literal may only contain one codepoint
12-
--> $DIR/lex-bad-char-literals-5.rs:8:20
12+
--> $DIR/lex-bad-char-literals-5.rs:5:20
1313
|
14-
LL | let ch: &str = '/x10/x10'; //~ ERROR: character literal may only contain one codepoint
14+
LL | let ch: &str = '/x10/x10';
1515
| ^^^^^^^^^^
1616
help: if you meant to write a `str` literal, use double quotes
1717
|
18-
LL | let ch: &str = "/x10/x10"; //~ ERROR: character literal may only contain one codepoint
18+
LL | let ch: &str = "/x10/x10";
1919
| ^^^^^^^^^^
2020

21-
error[E0308]: mismatched types
22-
--> $DIR/lex-bad-char-literals-5.rs:8:20
23-
|
24-
LL | let ch: &str = '/x10/x10'; //~ ERROR: character literal may only contain one codepoint
25-
| ^^^^^^^^^^ expected &str, found char
26-
|
27-
= note: expected type `&str`
28-
found type `char`
29-
30-
error: aborting due to 3 previous errors
21+
error: aborting due to 2 previous errors
3122

32-
For more information about this error, try `rustc --explain E0308`.
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
fn main() {
2-
let x: &str = 'ab'; //~ ERROR: character literal may only contain one codepoint
3-
//~^ ERROR: mismatched types
4-
let y: char = 'cd'; //~ ERROR: character literal may only contain one codepoint
5-
let z = 'ef'; //~ ERROR: character literal may only contain one codepoint
2+
let x: &str = 'ab';
3+
//~^ ERROR: character literal may only contain one codepoint
4+
let y: char = 'cd';
5+
//~^ ERROR: character literal may only contain one codepoint
6+
let z = 'ef';
7+
//~^ ERROR: character literal may only contain one codepoint
68

7-
if x == y {} //~ ERROR: can't compare `&str` with `char`
9+
if x == y {}
10+
//~^ ERROR: can't compare `&str` with `char`
811
if y == z {} // no error here
9-
if x == z {} //~ ERROR: can't compare `&str` with `char`
12+
if x == z {}
13+
//~^ ERROR: can\'t compare `&str` with `char`
1014

11-
let a: usize = ""; //~ ERROR: mismatched types
15+
let a: usize = "";
16+
//~^ ERROR: mismatched types
1217
}
Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,47 @@
11
error: character literal may only contain one codepoint
22
--> $DIR/lex-bad-char-literals-6.rs:2:19
33
|
4-
LL | let x: &str = 'ab'; //~ ERROR: character literal may only contain one codepoint
4+
LL | let x: &str = 'ab';
55
| ^^^^
66

77
error: character literal may only contain one codepoint
8-
--> $DIR/lex-bad-char-literals-6.rs:3:19
8+
--> $DIR/lex-bad-char-literals-6.rs:4:19
99
|
10-
LL | let y: char = 'cd'; //~ ERROR: character literal may only contain one codepoint
10+
LL | let y: char = 'cd';
1111
| ^^^^
1212

1313
error: character literal may only contain one codepoint
14-
--> $DIR/lex-bad-char-literals-6.rs:4:13
14+
--> $DIR/lex-bad-char-literals-6.rs:6:13
1515
|
16-
LL | let z = 'ef'; //~ ERROR: character literal may only contain one codepoint
16+
LL | let z = 'ef';
1717
| ^^^^
1818

19-
error[E0308]: mismatched types
20-
--> $DIR/lex-bad-char-literals-6.rs:2:19
21-
|
22-
LL | let x: &str = 'ab'; //~ ERROR: character literal may only contain one codepoint
23-
| ^^^^ expected &str, found char
24-
|
25-
= note: expected type `&str`
26-
found type `char`
27-
2819
error[E0277]: can't compare `&str` with `char`
29-
--> $DIR/lex-bad-char-literals-6.rs:6:10
20+
--> $DIR/lex-bad-char-literals-6.rs:9:10
3021
|
31-
LL | if x == y {} // no error here
22+
LL | if x == y {}
3223
| ^^ no implementation for `&str == char`
3324
|
3425
= help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
3526

3627
error[E0308]: mismatched types
37-
--> $DIR/lex-bad-char-literals-6.rs:10:20
28+
--> $DIR/lex-bad-char-literals-6.rs:15:20
3829
|
39-
LL | let a: usize = ""; // type error here to confirm we got past the parser
30+
LL | let a: usize = "";
4031
| ^^ expected usize, found reference
4132
|
4233
= note: expected type `usize`
4334
found type `&'static str`
4435

4536
error[E0277]: can't compare `&str` with `char`
46-
--> $DIR/lex-bad-char-literals-6.rs:8:10
37+
--> $DIR/lex-bad-char-literals-6.rs:12:10
4738
|
48-
LL | if x == z {} // no error here
39+
LL | if x == z {}
4940
| ^^ no implementation for `&str == char`
5041
|
5142
= help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
5243

53-
error: aborting due to 7 previous errors
44+
error: aborting due to 6 previous errors
5445

5546
Some errors occurred: E0277, E0308.
5647
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)