11//! HIR for references to types. Paths in these are not yet resolved. They can
22//! be directly created from an ast::TypeRef, without further queries.
33
4+ use std:: fmt:: Write ;
5+
46use hir_expand:: {
57 name:: { AsName , Name } ,
68 AstId , InFile ,
79} ;
8- use std:: { convert:: TryInto , fmt:: Write } ;
910use syntax:: ast:: { self , HasName } ;
1011
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+ } ;
1219
1320#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
1421pub enum Mutability {
@@ -178,7 +185,6 @@ impl TypeRef {
178185 // `hir_ty` level, which would allow knowing the type of:
179186 // let v: [u8; 2 + 2] = [0u8; 4];
180187 let len = ConstScalarOrPath :: from_expr_opt ( inner. expr ( ) ) ;
181-
182188 TypeRef :: Array ( Box :: new ( TypeRef :: from_ast_opt ( ctx, inner. ty ( ) ) ) , len)
183189 }
184190 ast:: Type :: SliceType ( inner) => {
@@ -403,22 +409,31 @@ impl ConstScalarOrPath {
403409 None => Self :: Scalar ( ConstScalar :: Unknown ) ,
404410 }
405411 }
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,
418423 }
419- _ => Self :: Scalar ( ConstScalar :: Unknown ) ,
420424 }
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+ } ) ,
422437 _ => Self :: Scalar ( ConstScalar :: Unknown ) ,
423438 }
424439 }
@@ -427,9 +442,10 @@ impl ConstScalarOrPath {
427442/// A concrete constant value
428443#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
429444pub 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 ) ,
433449
434450 /// Case of an unknown value that rustc might know but we don't
435451 // FIXME: this is a hack to get around chalk not being able to represent unevaluatable
@@ -439,21 +455,37 @@ pub enum ConstScalar {
439455 Unknown ,
440456}
441457
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 {
444460 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 ,
447465 }
448466 }
449467}
450468
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 > {
454483 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 ( '_' ) ,
457489 }
458490 }
459491}
0 commit comments