1
1
//! HIR for references to types. Paths in these are not yet resolved. They can
2
2
//! be directly created from an ast::TypeRef, without further queries.
3
3
4
+ use std:: fmt:: Write ;
5
+
4
6
use hir_expand:: {
5
7
name:: { AsName , Name } ,
6
8
AstId , InFile ,
7
9
} ;
8
- use std:: { convert:: TryInto , fmt:: Write } ;
9
10
use syntax:: ast:: { self , HasName } ;
10
11
11
- use crate :: { body:: LowerCtx , intern:: Interned , path:: Path } ;
12
+ use crate :: {
13
+ body:: LowerCtx ,
14
+ builtin_type:: { BuiltinInt , BuiltinType , BuiltinUint } ,
15
+ expr:: Literal ,
16
+ intern:: Interned ,
17
+ path:: Path ,
18
+ } ;
12
19
13
20
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
14
21
pub enum Mutability {
@@ -178,7 +185,6 @@ impl TypeRef {
178
185
// `hir_ty` level, which would allow knowing the type of:
179
186
// let v: [u8; 2 + 2] = [0u8; 4];
180
187
let len = ConstScalarOrPath :: from_expr_opt ( inner. expr ( ) ) ;
181
-
182
188
TypeRef :: Array ( Box :: new ( TypeRef :: from_ast_opt ( ctx, inner. ty ( ) ) ) , len)
183
189
}
184
190
ast:: Type :: SliceType ( inner) => {
@@ -403,22 +409,31 @@ impl ConstScalarOrPath {
403
409
None => Self :: Scalar ( ConstScalar :: Unknown ) ,
404
410
}
405
411
}
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
- )
412
+ ast:: Expr :: PrefixExpr ( prefix_expr) => match prefix_expr. op_kind ( ) {
413
+ Some ( ast:: UnaryOp :: Neg ) => {
414
+ let unsigned = prefix_expr
415
+ . expr ( )
416
+ . map_or ( Self :: Scalar ( ConstScalar :: Unknown ) , Self :: from_expr) ;
417
+ // Add sign
418
+ match unsigned {
419
+ Self :: Scalar ( ConstScalar :: UInt ( num) ) => {
420
+ Self :: Scalar ( ConstScalar :: Int ( -( num as i128 ) ) )
421
+ }
422
+ other => other,
418
423
}
419
- _ => Self :: Scalar ( ConstScalar :: Unknown ) ,
420
424
}
421
- }
425
+ _ => prefix_expr. expr ( ) . map_or ( Self :: Scalar ( ConstScalar :: Unknown ) , Self :: from_expr) ,
426
+ } ,
427
+ ast:: Expr :: Literal ( literal) => Self :: Scalar ( match literal. kind ( ) {
428
+ ast:: LiteralKind :: IntNumber ( num) => {
429
+ num. value ( ) . map ( ConstScalar :: UInt ) . unwrap_or ( ConstScalar :: Unknown )
430
+ }
431
+ ast:: LiteralKind :: Char ( c) => {
432
+ c. value ( ) . map ( ConstScalar :: Char ) . unwrap_or ( ConstScalar :: Unknown )
433
+ }
434
+ ast:: LiteralKind :: Bool ( f) => ConstScalar :: Bool ( f) ,
435
+ _ => ConstScalar :: Unknown ,
436
+ } ) ,
422
437
_ => Self :: Scalar ( ConstScalar :: Unknown ) ,
423
438
}
424
439
}
@@ -427,9 +442,10 @@ impl ConstScalarOrPath {
427
442
/// A concrete constant value
428
443
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
429
444
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 ) ,
445
+ Int ( i128 ) ,
446
+ UInt ( u128 ) ,
447
+ Bool ( bool ) ,
448
+ Char ( char ) ,
433
449
434
450
/// Case of an unknown value that rustc might know but we don't
435
451
// FIXME: this is a hack to get around chalk not being able to represent unevaluatable
@@ -439,21 +455,37 @@ pub enum ConstScalar {
439
455
Unknown ,
440
456
}
441
457
442
- impl std :: fmt :: Display for ConstScalar {
443
- fn fmt ( & self , f : & mut std :: fmt :: Formatter < ' _ > ) -> Result < ( ) , std :: fmt :: Error > {
458
+ impl ConstScalar {
459
+ pub fn builtin_type ( & self ) -> BuiltinType {
444
460
match self {
445
- ConstScalar :: Usize ( us) => us. fmt ( f) ,
446
- ConstScalar :: Unknown => f. write_char ( '_' ) ,
461
+ ConstScalar :: UInt ( _) | ConstScalar :: Unknown => BuiltinType :: Uint ( BuiltinUint :: U128 ) ,
462
+ ConstScalar :: Int ( _) => BuiltinType :: Int ( BuiltinInt :: I128 ) ,
463
+ ConstScalar :: Char ( _) => BuiltinType :: Char ,
464
+ ConstScalar :: Bool ( _) => BuiltinType :: Bool ,
447
465
}
448
466
}
449
467
}
450
468
451
- impl ConstScalar {
452
- /// Gets a target usize out of the ConstScalar
453
- pub fn as_usize ( & self ) -> Option < u64 > {
469
+ impl From < Literal > for ConstScalar {
470
+ fn from ( literal : Literal ) -> Self {
471
+ match literal {
472
+ Literal :: Char ( c) => Self :: Char ( c) ,
473
+ Literal :: Bool ( flag) => Self :: Bool ( flag) ,
474
+ Literal :: Int ( num, _) => Self :: Int ( num) ,
475
+ Literal :: Uint ( num, _) => Self :: UInt ( num) ,
476
+ _ => Self :: Unknown ,
477
+ }
478
+ }
479
+ }
480
+
481
+ impl std:: fmt:: Display for ConstScalar {
482
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
454
483
match self {
455
- & ConstScalar :: Usize ( us) => Some ( us) ,
456
- _ => None ,
484
+ ConstScalar :: Int ( num) => num. fmt ( f) ,
485
+ ConstScalar :: UInt ( num) => num. fmt ( f) ,
486
+ ConstScalar :: Bool ( flag) => flag. fmt ( f) ,
487
+ ConstScalar :: Char ( c) => write ! ( f, "'{c}'" ) ,
488
+ ConstScalar :: Unknown => f. write_char ( '_' ) ,
457
489
}
458
490
}
459
491
}
0 commit comments