Skip to content

Commit 25a09c4

Browse files
committed
Carry sign through literals
1 parent a46c755 commit 25a09c4

File tree

60 files changed

+594
-278
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+594
-278
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,11 +1874,13 @@ impl StrLit {
18741874
#[derive(HashStable_Generic)]
18751875
pub enum LitIntType {
18761876
/// e.g. `42_i32`.
1877-
Signed(IntTy),
1877+
/// The bool signals whether the literal is negated
1878+
Signed(IntTy, bool),
18781879
/// e.g. `42_u32`.
18791880
Unsigned(UintTy),
18801881
/// e.g. `42`.
1881-
Unsuffixed,
1882+
/// The bool signals whether the literal is negated
1883+
Unsuffixed(bool),
18821884
}
18831885

18841886
/// Type of the float literal based on provided suffix.
@@ -1913,7 +1915,7 @@ pub enum LitKind {
19131915
Char(char),
19141916
/// An integer literal (`1`).
19151917
Int(Pu128, LitIntType),
1916-
/// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is
1918+
/// A float literal (`1.0`, `-1.0`, `1f64` or `1E10f64`). The pre-suffix part is
19171919
/// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq`
19181920
/// and `Hash`.
19191921
Float(Symbol, LitFloatType),
@@ -1964,12 +1966,22 @@ impl LitKind {
19641966
| LitKind::CStr(..)
19651967
| LitKind::Byte(..)
19661968
| LitKind::Char(..)
1967-
| LitKind::Int(_, LitIntType::Unsuffixed)
1969+
| LitKind::Int(_, LitIntType::Unsuffixed(_))
19681970
| LitKind::Float(_, LitFloatType::Unsuffixed)
19691971
| LitKind::Bool(..)
19701972
| LitKind::Err(_) => false,
19711973
}
19721974
}
1975+
1976+
pub fn is_negative(&self) -> bool {
1977+
match self {
1978+
LitKind::Int(_, LitIntType::Signed(_, negative) | LitIntType::Unsuffixed(negative)) => {
1979+
*negative
1980+
}
1981+
LitKind::Float(f, _) => f.as_str().starts_with('-'),
1982+
_ => false,
1983+
}
1984+
}
19731985
}
19741986

19751987
// N.B., If you change this, you'll probably want to change the corresponding

compiler/rustc_ast/src/util/literal.rs

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,35 @@ pub enum LitError {
3636
InvalidSuffix(Symbol),
3737
InvalidIntSuffix(Symbol),
3838
InvalidFloatSuffix(Symbol),
39+
InvalidNegation(token::LitKind),
3940
NonDecimalFloat(u32), // u32 is the base
4041
IntTooLarge(u32), // u32 is the base
4142
}
4243

4344
impl LitKind {
4445
/// Converts literal token into a semantic literal.
4546
pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> {
47+
Self::from_token_lit_maybe_negated(lit, false)
48+
}
49+
50+
/// Converts literal token into a semantic literal.
51+
/// May optionally include a sign, and will error if a literal
52+
/// other than integer or float literals is negated.
53+
pub fn from_token_lit_maybe_negated(
54+
lit: token::Lit,
55+
negated: bool,
56+
) -> Result<LitKind, LitError> {
4657
let token::Lit { kind, symbol, suffix } = lit;
4758
if let Some(suffix) = suffix
4859
&& !kind.may_have_suffix()
4960
{
5061
return Err(LitError::InvalidSuffix(suffix));
5162
}
5263

64+
if negated && !matches!(kind, token::Integer | token::Float) {
65+
return Err(LitError::InvalidNegation(kind));
66+
}
67+
5368
// For byte/char/string literals, chars and escapes have already been
5469
// checked in the lexer (in `cook_lexer_literal`). So we can assume all
5570
// chars and escapes are valid here.
@@ -71,8 +86,8 @@ impl LitKind {
7186

7287
// There are some valid suffixes for integer and float literals,
7388
// so all the handling is done internally.
74-
token::Integer => return integer_lit(symbol, suffix),
75-
token::Float => return float_lit(symbol, suffix),
89+
token::Integer => return integer_lit(symbol, suffix, negated),
90+
token::Float => return float_lit(symbol, suffix, negated),
7691

7792
token::Str => {
7893
// If there are no characters requiring special treatment we can
@@ -189,14 +204,21 @@ impl fmt::Display for LitKind {
189204
let symbol = str::from_utf8(bytes).unwrap();
190205
write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize),)?;
191206
}
192-
LitKind::Int(n, ty) => {
193-
write!(f, "{n}")?;
194-
match ty {
195-
ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?,
196-
ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?,
197-
ast::LitIntType::Unsuffixed => {}
207+
LitKind::Int(n, ty) => match ty {
208+
ast::LitIntType::Unsigned(ty) => write!(f, "{n}{}", ty.name())?,
209+
ast::LitIntType::Signed(ty, negated) => {
210+
if negated {
211+
write!(f, "-")?;
212+
}
213+
write!(f, "{n}{}", ty.name())?
198214
}
199-
}
215+
ast::LitIntType::Unsuffixed(negated) => {
216+
if negated {
217+
write!(f, "-")?;
218+
}
219+
write!(f, "{n}")?;
220+
}
221+
},
200222
LitKind::Float(symbol, ty) => {
201223
write!(f, "{symbol}")?;
202224
match ty {
@@ -269,11 +291,13 @@ fn filtered_float_lit(
269291
symbol: Symbol,
270292
suffix: Option<Symbol>,
271293
base: u32,
294+
negated: bool,
272295
) -> Result<LitKind, LitError> {
273-
debug!("filtered_float_lit: {:?}, {:?}, {:?}", symbol, suffix, base);
296+
debug!(?symbol, ?suffix, ?base, ?negated);
274297
if base != 10 {
275298
return Err(LitError::NonDecimalFloat(base));
276299
}
300+
let symbol = if negated { Symbol::intern(&format!("-{}", symbol.as_str())) } else { symbol };
277301
Ok(match suffix {
278302
Some(suffix) => LitKind::Float(
279303
symbol,
@@ -289,12 +313,12 @@ fn filtered_float_lit(
289313
})
290314
}
291315

292-
fn float_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
316+
fn float_lit(symbol: Symbol, suffix: Option<Symbol>, negated: bool) -> Result<LitKind, LitError> {
293317
debug!("float_lit: {:?}, {:?}", symbol, suffix);
294-
filtered_float_lit(strip_underscores(symbol), suffix, 10)
318+
filtered_float_lit(strip_underscores(symbol), suffix, 10, negated)
295319
}
296320

297-
fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitError> {
321+
fn integer_lit(symbol: Symbol, suffix: Option<Symbol>, negated: bool) -> Result<LitKind, LitError> {
298322
debug!("integer_lit: {:?}, {:?}", symbol, suffix);
299323
let symbol = strip_underscores(symbol);
300324
let s = symbol.as_str();
@@ -308,12 +332,12 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
308332

309333
let ty = match suffix {
310334
Some(suf) => match suf {
311-
sym::isize => ast::LitIntType::Signed(ast::IntTy::Isize),
312-
sym::i8 => ast::LitIntType::Signed(ast::IntTy::I8),
313-
sym::i16 => ast::LitIntType::Signed(ast::IntTy::I16),
314-
sym::i32 => ast::LitIntType::Signed(ast::IntTy::I32),
315-
sym::i64 => ast::LitIntType::Signed(ast::IntTy::I64),
316-
sym::i128 => ast::LitIntType::Signed(ast::IntTy::I128),
335+
sym::isize => ast::LitIntType::Signed(ast::IntTy::Isize, negated),
336+
sym::i8 => ast::LitIntType::Signed(ast::IntTy::I8, negated),
337+
sym::i16 => ast::LitIntType::Signed(ast::IntTy::I16, negated),
338+
sym::i32 => ast::LitIntType::Signed(ast::IntTy::I32, negated),
339+
sym::i64 => ast::LitIntType::Signed(ast::IntTy::I64, negated),
340+
sym::i128 => ast::LitIntType::Signed(ast::IntTy::I128, negated),
317341
sym::usize => ast::LitIntType::Unsigned(ast::UintTy::Usize),
318342
sym::u8 => ast::LitIntType::Unsigned(ast::UintTy::U8),
319343
sym::u16 => ast::LitIntType::Unsigned(ast::UintTy::U16),
@@ -322,11 +346,18 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
322346
sym::u128 => ast::LitIntType::Unsigned(ast::UintTy::U128),
323347
// `1f64` and `2f32` etc. are valid float literals, and
324348
// `fxxx` looks more like an invalid float literal than invalid integer literal.
325-
_ if suf.as_str().starts_with('f') => return filtered_float_lit(symbol, suffix, base),
349+
_ if suf.as_str().starts_with('f') => {
350+
return filtered_float_lit(symbol, suffix, base, negated);
351+
}
326352
_ => return Err(LitError::InvalidIntSuffix(suf)),
327353
},
328-
_ => ast::LitIntType::Unsuffixed,
354+
_ => ast::LitIntType::Unsuffixed(negated),
329355
};
356+
if let ast::LitIntType::Unsigned(_) = ty
357+
&& negated
358+
{
359+
return Err(LitError::InvalidNegation(token::Integer));
360+
}
330361

331362
let s = &s[if base != 10 { 2 } else { 0 }..];
332363
u128::from_str_radix(s, base)

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
138138
hir::ExprKind::Binary(binop, lhs, rhs)
139139
}
140140
ExprKind::Unary(op, ohs) => {
141+
if let UnOp::Neg = op {
142+
if let ExprKind::Lit(token_lit) = &ohs.kind {
143+
return hir::Expr {
144+
hir_id: expr_hir_id,
145+
kind: hir::ExprKind::Lit(self.lower_lit(token_lit, e.span, true)),
146+
span: self.lower_span(e.span),
147+
};
148+
}
149+
}
141150
let op = self.lower_unop(*op);
142151
let ohs = self.lower_expr(ohs);
143152
hir::ExprKind::Unary(op, ohs)
144153
}
145-
ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
154+
ExprKind::Lit(token_lit) => {
155+
hir::ExprKind::Lit(self.lower_lit(token_lit, e.span, false))
156+
}
146157
ExprKind::IncludedBytes(bytes) => {
147158
let lit = self.arena.alloc(respan(
148159
self.lower_span(e.span),
@@ -419,8 +430,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
419430
&mut self,
420431
token_lit: &token::Lit,
421432
span: Span,
433+
negated: bool,
422434
) -> &'hir Spanned<LitKind> {
423-
let lit_kind = match LitKind::from_token_lit(*token_lit) {
435+
let lit_kind = match LitKind::from_token_lit_maybe_negated(*token_lit, negated) {
424436
Ok(lit_kind) => lit_kind,
425437
Err(err) => {
426438
let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span);

compiler/rustc_ast_lowering/src/format.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
3030
Ok(LitKind::Int(n, ty)) => {
3131
match ty {
3232
// unsuffixed integer literals are assumed to be i32's
33-
LitIntType::Unsuffixed => {
34-
(n <= i32::MAX as u128).then_some(Symbol::intern(&n.to_string()))
35-
}
36-
LitIntType::Signed(int_ty) => {
33+
LitIntType::Unsuffixed(negated) => (!negated && n <= i32::MAX as u128)
34+
.then_some(Symbol::intern(&n.to_string())),
35+
LitIntType::Signed(int_ty, negated) => {
3736
let max_literal = self.int_ty_max(int_ty);
38-
(n <= max_literal).then_some(Symbol::intern(&n.to_string()))
37+
(!negated && n <= max_literal).then_some(Symbol::intern(&n.to_string()))
3938
}
4039
LitIntType::Unsigned(uint_ty) => {
4140
let max_literal = self.uint_ty_max(uint_ty);

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -391,18 +391,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
391391
let span = self.lower_span(expr.span);
392392
let err = |guar| hir::PatExprKind::Lit {
393393
lit: self.arena.alloc(respan(span, LitKind::Err(guar))),
394-
negated: false,
395394
};
396395
let kind = match &expr.kind {
397-
ExprKind::Lit(lit) => {
398-
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: false }
399-
}
396+
ExprKind::Lit(lit) => hir::PatExprKind::Lit { lit: self.lower_lit(lit, span, false) },
400397
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
401398
ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit {
402399
lit: self
403400
.arena
404401
.alloc(respan(span, LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked))),
405-
negated: false,
406402
},
407403
ExprKind::Err(guar) => err(*guar),
408404
ExprKind::Dummy => span_bug!(span, "lowered ExprKind::Dummy"),
@@ -416,7 +412,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
416412
None,
417413
)),
418414
ExprKind::Unary(UnOp::Neg, inner) if let ExprKind::Lit(lit) = &inner.kind => {
419-
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: true }
415+
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span, true) }
420416
}
421417
_ => {
422418
let pattern_from_macro = expr.is_approximately_pattern();

compiler/rustc_attr_parsing/src/attributes/repr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ fn parse_repr_align(
225225
}
226226

227227
fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
228-
if let LitKind::Int(literal, LitIntType::Unsuffixed) = node {
228+
if let LitKind::Int(literal, LitIntType::Unsuffixed(false)) = node {
229229
// `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
230230
if literal.get().is_power_of_two() {
231231
// Only possible error is larger than 2^29

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
320320
name: &'a str,
321321

322322
#[skip_arg]
323-
int: u128,
323+
int: String,
324324
},
325325

326326
#[suggestion(
@@ -342,11 +342,13 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
342342

343343
impl<'a> IncorrectReprFormatGenericCause<'a> {
344344
pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
345-
match kind {
346-
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
347-
Some(Self::Int { span, name, int: int.get() })
348-
}
349-
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
345+
match *kind {
346+
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed(negated)) => Some(Self::Int {
347+
span,
348+
name,
349+
int: if negated { format!("-{}", int.get()) } else { int.get().to_string() },
350+
}),
351+
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol }),
350352
_ => None,
351353
}
352354
}

compiler/rustc_builtin_macros/src/concat_bytes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn invalid_type_err(
5151
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span, snippet });
5252
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg })
5353
}
54-
Ok(LitKind::Int(val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8))) => {
54+
Ok(LitKind::Int(val, LitIntType::Unsuffixed(false) | LitIntType::Unsigned(UintTy::U8))) => {
5555
assert!(val.get() > u8::MAX.into()); // must be an error
5656
dcx.emit_err(ConcatBytesOob { span })
5757
}
@@ -79,7 +79,7 @@ fn handle_array_element(
7979
match LitKind::from_token_lit(token_lit) {
8080
Ok(LitKind::Int(
8181
val,
82-
LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8),
82+
LitIntType::Unsuffixed(false) | LitIntType::Unsigned(UintTy::U8),
8383
)) if let Ok(val) = u8::try_from(val.get()) => {
8484
return Some(val);
8585
}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,9 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
750750
tcx.dcx().emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span() });
751751
return None;
752752
};
753-
if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
754-
sole_meta_list.lit()
753+
if let Some(MetaItemLit {
754+
kind: LitKind::Int(ordinal, LitIntType::Unsuffixed(false)), ..
755+
}) = sole_meta_list.lit()
755756
{
756757
// According to the table at
757758
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, the

compiler/rustc_expand/src/mbe/metavar_expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn parse_depth<'psess>(
191191
.struct_span_err(span, "meta-variable expression depth must be a literal"));
192192
};
193193
if let Ok(lit_kind) = LitKind::from_token_lit(*lit)
194-
&& let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind
194+
&& let LitKind::Int(n_u128, LitIntType::Unsuffixed(false)) = lit_kind
195195
&& let Ok(n_usize) = usize::try_from(n_u128.get())
196196
{
197197
Ok(n_usize)

0 commit comments

Comments
 (0)