Skip to content

Commit e789d73

Browse files
committed
Auto merge of rust-lang#12157 - lnicola:lower-char-byte-literals, r=Veykril
feat: Lower values of char and byte literals Closes rust-lang#12137
2 parents 0218aeb + 9856144 commit e789d73

File tree

8 files changed

+178
-11
lines changed

8 files changed

+178
-11
lines changed

crates/hir-def/src/body/lower.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -983,9 +983,11 @@ impl From<ast::LiteralKind> for Literal {
983983
let text = s.value().map(Box::from).unwrap_or_else(Default::default);
984984
Literal::String(text)
985985
}
986-
LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)),
986+
LiteralKind::Byte(b) => {
987+
Literal::Uint(b.value().unwrap_or_default() as u128, Some(BuiltinUint::U8))
988+
}
989+
LiteralKind::Char(c) => Literal::Char(c.value().unwrap_or_default()),
987990
LiteralKind::Bool(val) => Literal::Bool(val),
988-
LiteralKind::Char => Literal::Char(Default::default()),
989991
}
990992
}
991993
}

crates/ide/src/hover/tests.rs

+88
Original file line numberDiff line numberDiff line change
@@ -3507,6 +3507,94 @@ const FOO$0: &str = "bar";
35073507
35083508
---
35093509
3510+
This is a doc
3511+
"#]],
3512+
);
3513+
// show char literal
3514+
check(
3515+
r#"
3516+
/// This is a doc
3517+
const FOO$0: char = 'a';
3518+
"#,
3519+
expect![[r#"
3520+
*FOO*
3521+
3522+
```rust
3523+
test
3524+
```
3525+
3526+
```rust
3527+
const FOO: char = 'a'
3528+
```
3529+
3530+
---
3531+
3532+
This is a doc
3533+
"#]],
3534+
);
3535+
// show escaped char literal
3536+
check(
3537+
r#"
3538+
/// This is a doc
3539+
const FOO$0: char = '\x61';
3540+
"#,
3541+
expect![[r#"
3542+
*FOO*
3543+
3544+
```rust
3545+
test
3546+
```
3547+
3548+
```rust
3549+
const FOO: char = 'a'
3550+
```
3551+
3552+
---
3553+
3554+
This is a doc
3555+
"#]],
3556+
);
3557+
// show byte literal
3558+
check(
3559+
r#"
3560+
/// This is a doc
3561+
const FOO$0: u8 = b'a';
3562+
"#,
3563+
expect![[r#"
3564+
*FOO*
3565+
3566+
```rust
3567+
test
3568+
```
3569+
3570+
```rust
3571+
const FOO: u8 = 97 (0x61)
3572+
```
3573+
3574+
---
3575+
3576+
This is a doc
3577+
"#]],
3578+
);
3579+
// show escaped byte literal
3580+
check(
3581+
r#"
3582+
/// This is a doc
3583+
const FOO$0: u8 = b'\x61';
3584+
"#,
3585+
expect![[r#"
3586+
*FOO*
3587+
3588+
```rust
3589+
test
3590+
```
3591+
3592+
```rust
3593+
const FOO: u8 = 97 (0x61)
3594+
```
3595+
3596+
---
3597+
35103598
This is a doc
35113599
"#]],
35123600
);

crates/rust-analyzer/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
//!
99
//! The `cli` submodule implements some batch-processing analysis, primarily as
1010
//! a debugging aid.
11-
#![recursion_limit = "512"]
1211
1312
pub mod cli;
1413

crates/syntax/src/ast/expr_ext.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ pub enum LiteralKind {
283283
ByteString(ast::ByteString),
284284
IntNumber(ast::IntNumber),
285285
FloatNumber(ast::FloatNumber),
286-
Char,
287-
Byte,
286+
Char(ast::Char),
287+
Byte(ast::Byte),
288288
Bool(bool),
289289
}
290290

@@ -312,12 +312,16 @@ impl ast::Literal {
312312
if let Some(t) = ast::ByteString::cast(token.clone()) {
313313
return LiteralKind::ByteString(t);
314314
}
315+
if let Some(t) = ast::Char::cast(token.clone()) {
316+
return LiteralKind::Char(t);
317+
}
318+
if let Some(t) = ast::Byte::cast(token.clone()) {
319+
return LiteralKind::Byte(t);
320+
}
315321

316322
match token.kind() {
317323
T![true] => LiteralKind::Bool(true),
318324
T![false] => LiteralKind::Bool(false),
319-
CHAR => LiteralKind::Char,
320-
BYTE => LiteralKind::Byte,
321325
_ => unreachable!(),
322326
}
323327
}

crates/syntax/src/ast/generated/tokens.rs

+42
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,48 @@ impl AstToken for FloatNumber {
132132
fn syntax(&self) -> &SyntaxToken { &self.syntax }
133133
}
134134

135+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136+
pub struct Char {
137+
pub(crate) syntax: SyntaxToken,
138+
}
139+
impl std::fmt::Display for Char {
140+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141+
std::fmt::Display::fmt(&self.syntax, f)
142+
}
143+
}
144+
impl AstToken for Char {
145+
fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
146+
fn cast(syntax: SyntaxToken) -> Option<Self> {
147+
if Self::can_cast(syntax.kind()) {
148+
Some(Self { syntax })
149+
} else {
150+
None
151+
}
152+
}
153+
fn syntax(&self) -> &SyntaxToken { &self.syntax }
154+
}
155+
156+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
157+
pub struct Byte {
158+
pub(crate) syntax: SyntaxToken,
159+
}
160+
impl std::fmt::Display for Byte {
161+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162+
std::fmt::Display::fmt(&self.syntax, f)
163+
}
164+
}
165+
impl AstToken for Byte {
166+
fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
167+
fn cast(syntax: SyntaxToken) -> Option<Self> {
168+
if Self::can_cast(syntax.kind()) {
169+
Some(Self { syntax })
170+
} else {
171+
None
172+
}
173+
}
174+
fn syntax(&self) -> &SyntaxToken { &self.syntax }
175+
}
176+
135177
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136178
pub struct Ident {
137179
pub(crate) syntax: SyntaxToken,

crates/syntax/src/ast/token_ext.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::borrow::Cow;
44

5-
use rustc_lexer::unescape::{unescape_literal, Mode};
5+
use rustc_lexer::unescape::{unescape_byte, unescape_char, unescape_literal, Mode};
66

77
use crate::{
88
ast::{self, AstToken},
@@ -406,3 +406,35 @@ mod tests {
406406
check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\");
407407
}
408408
}
409+
410+
impl ast::Char {
411+
pub fn value(&self) -> Option<char> {
412+
let mut text = self.text();
413+
if text.starts_with('\'') {
414+
text = &text[1..];
415+
} else {
416+
return None;
417+
}
418+
if text.ends_with('\'') {
419+
text = &text[0..text.len() - 1];
420+
}
421+
422+
unescape_char(text).ok()
423+
}
424+
}
425+
426+
impl ast::Byte {
427+
pub fn value(&self) -> Option<u8> {
428+
let mut text = self.text();
429+
if text.starts_with("b\'") {
430+
text = &text[2..];
431+
} else {
432+
return None;
433+
}
434+
if text.ends_with('\'') {
435+
text = &text[0..text.len() - 1];
436+
}
437+
438+
unescape_byte(text).ok()
439+
}
440+
}

crates/syntax/src/tests/sourcegen_ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ impl Field {
585585

586586
fn lower(grammar: &Grammar) -> AstSrc {
587587
let mut res = AstSrc {
588-
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Ident"
588+
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Char Byte Ident"
589589
.split_ascii_whitespace()
590590
.map(|it| it.to_string())
591591
.collect::<Vec<_>>(),

crates/syntax/src/validation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,12 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
151151
}
152152
}
153153
}
154-
ast::LiteralKind::Char => {
154+
ast::LiteralKind::Char(_) => {
155155
if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
156156
push_err(1, e);
157157
}
158158
}
159-
ast::LiteralKind::Byte => {
159+
ast::LiteralKind::Byte(_) => {
160160
if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
161161
push_err(2, e);
162162
}

0 commit comments

Comments
 (0)