@@ -5,10 +5,15 @@ use hir_expand::{
5
5
name:: { AsName , Name } ,
6
6
AstId , InFile ,
7
7
} ;
8
- use std:: { convert:: TryInto , fmt:: Write } ;
9
8
use syntax:: ast:: { self , HasName } ;
10
9
11
- use crate :: { body:: LowerCtx , intern:: Interned , path:: Path } ;
10
+ use crate :: {
11
+ body:: LowerCtx ,
12
+ builtin_type:: { BuiltinInt , BuiltinType , BuiltinUint } ,
13
+ expr:: Literal ,
14
+ intern:: Interned ,
15
+ path:: Path ,
16
+ } ;
12
17
13
18
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
14
19
pub enum Mutability {
@@ -177,7 +182,10 @@ impl TypeRef {
177
182
// `hir_def::body::lower` to lower this into an `Expr` and then evaluate it at the
178
183
// `hir_ty` level, which would allow knowing the type of:
179
184
// let v: [u8; 2 + 2] = [0u8; 4];
180
- let len = ConstScalarOrPath :: from_expr_opt ( inner. expr ( ) ) ;
185
+ let len = inner. expr ( ) . map_or (
186
+ ConstScalarOrPath :: Scalar ( ConstScalar :: Unknown ) ,
187
+ ConstScalarOrPath :: from_expr,
188
+ ) ;
181
189
182
190
TypeRef :: Array ( Box :: new ( TypeRef :: from_ast_opt ( ctx, inner. ty ( ) ) ) , len)
183
191
}
@@ -386,39 +394,41 @@ impl std::fmt::Display for ConstScalarOrPath {
386
394
}
387
395
388
396
impl ConstScalarOrPath {
389
- pub ( crate ) fn from_expr_opt ( expr : Option < ast:: Expr > ) -> Self {
390
- match expr {
391
- Some ( x) => Self :: from_expr ( x) ,
392
- None => Self :: Scalar ( ConstScalar :: Unknown ) ,
393
- }
394
- }
395
-
396
397
// FIXME: as per the comments on `TypeRef::Array`, this evaluation should not happen at this
397
398
// parse stage.
398
- fn from_expr ( expr : ast:: Expr ) -> Self {
399
+ pub ( crate ) fn from_expr ( expr : ast:: Expr ) -> Self {
399
400
match expr {
400
401
ast:: Expr :: PathExpr ( p) => {
401
402
match p. path ( ) . and_then ( |x| x. segment ( ) ) . and_then ( |x| x. name_ref ( ) ) {
402
403
Some ( x) => Self :: Path ( x. as_name ( ) ) ,
403
404
None => Self :: Scalar ( ConstScalar :: Unknown ) ,
404
405
}
405
406
}
406
- ast:: Expr :: Literal ( lit) => {
407
- let lkind = lit. kind ( ) ;
408
- match lkind {
409
- ast:: LiteralKind :: IntNumber ( num)
410
- if num. suffix ( ) == None || num. suffix ( ) == Some ( "usize" ) =>
411
- {
412
- Self :: Scalar (
413
- num. value ( )
414
- . and_then ( |v| v. try_into ( ) . ok ( ) )
415
- . map ( ConstScalar :: Usize )
416
- . unwrap_or ( ConstScalar :: Unknown ) ,
417
- )
407
+ ast:: Expr :: PrefixExpr ( prefix_expr) => match prefix_expr. op_kind ( ) {
408
+ Some ( ast:: UnaryOp :: Neg ) => {
409
+ let unsigned = prefix_expr
410
+ . expr ( )
411
+ . map_or ( Self :: Scalar ( ConstScalar :: Unknown ) , Self :: from_expr) ;
412
+ // Add sign
413
+ match unsigned {
414
+ Self :: Scalar ( ConstScalar :: UInt ( num) ) => {
415
+ Self :: Scalar ( ConstScalar :: Int ( -( num as i128 ) ) )
416
+ }
417
+ other => other,
418
418
}
419
- _ => Self :: Scalar ( ConstScalar :: Unknown ) ,
420
419
}
421
- }
420
+ _ => prefix_expr. expr ( ) . map_or ( Self :: Scalar ( ConstScalar :: Unknown ) , Self :: from_expr) ,
421
+ } ,
422
+ ast:: Expr :: Literal ( literal) => Self :: Scalar ( match literal. kind ( ) {
423
+ ast:: LiteralKind :: IntNumber ( num) => {
424
+ num. value ( ) . map ( ConstScalar :: UInt ) . unwrap_or ( ConstScalar :: Unknown )
425
+ }
426
+ ast:: LiteralKind :: Char ( c) => {
427
+ c. value ( ) . map ( ConstScalar :: Char ) . unwrap_or ( ConstScalar :: Unknown )
428
+ }
429
+ ast:: LiteralKind :: Bool ( f) => ConstScalar :: Bool ( f) ,
430
+ _ => ConstScalar :: Unknown ,
431
+ } ) ,
422
432
_ => Self :: Scalar ( ConstScalar :: Unknown ) ,
423
433
}
424
434
}
@@ -427,9 +437,10 @@ impl ConstScalarOrPath {
427
437
/// A concrete constant value
428
438
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
429
439
pub enum ConstScalar {
430
- // for now, we only support the trivial case of constant evaluating the length of an array
431
- // Note that this is u64 because the target usize may be bigger than our usize
432
- Usize ( u64 ) ,
440
+ Int ( i128 ) ,
441
+ UInt ( u128 ) ,
442
+ Bool ( bool ) ,
443
+ Char ( char ) ,
433
444
434
445
/// Case of an unknown value that rustc might know but we don't
435
446
// FIXME: this is a hack to get around chalk not being able to represent unevaluatable
@@ -439,21 +450,37 @@ pub enum ConstScalar {
439
450
Unknown ,
440
451
}
441
452
442
- impl std :: fmt :: Display for ConstScalar {
443
- fn fmt ( & self , f : & mut std :: fmt :: Formatter < ' _ > ) -> Result < ( ) , std :: fmt :: Error > {
453
+ impl ConstScalar {
454
+ pub fn builtin_type ( & self ) -> BuiltinType {
444
455
match self {
445
- ConstScalar :: Usize ( us) => us. fmt ( f) ,
446
- ConstScalar :: Unknown => f. write_char ( '_' ) ,
456
+ ConstScalar :: UInt ( _) | ConstScalar :: Unknown => BuiltinType :: Uint ( BuiltinUint :: U128 ) ,
457
+ ConstScalar :: Int ( _) => BuiltinType :: Int ( BuiltinInt :: I128 ) ,
458
+ ConstScalar :: Char ( _) => BuiltinType :: Char ,
459
+ ConstScalar :: Bool ( _) => BuiltinType :: Bool ,
447
460
}
448
461
}
449
462
}
450
463
451
- impl ConstScalar {
452
- /// Gets a target usize out of the ConstScalar
453
- pub fn as_usize ( & self ) -> Option < u64 > {
464
+ impl From < Literal > for ConstScalar {
465
+ fn from ( literal : Literal ) -> Self {
466
+ match literal {
467
+ Literal :: Char ( c) => Self :: Char ( c) ,
468
+ Literal :: Bool ( flag) => Self :: Bool ( flag) ,
469
+ Literal :: Int ( num, _) => Self :: Int ( num) ,
470
+ Literal :: Uint ( num, _) => Self :: UInt ( num) ,
471
+ _ => Self :: Unknown ,
472
+ }
473
+ }
474
+ }
475
+
476
+ impl std:: fmt:: Display for ConstScalar {
477
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
454
478
match self {
455
- & ConstScalar :: Usize ( us) => Some ( us) ,
456
- _ => None ,
479
+ ConstScalar :: Int ( num) => num. fmt ( f) ,
480
+ ConstScalar :: UInt ( num) => num. fmt ( f) ,
481
+ ConstScalar :: Bool ( flag) => flag. fmt ( f) ,
482
+ ConstScalar :: Char ( c) => write ! ( f, "'{c}'" ) ,
483
+ ConstScalar :: Unknown => f. write_str ( "{unknown}" ) ,
457
484
}
458
485
}
459
486
}
0 commit comments