@@ -2210,7 +2210,7 @@ impl<'db> TypeInferenceBuilder<'db> {
2210
2210
2211
2211
match ( op, self . infer_expression ( operand) ) {
2212
2212
( UnaryOp :: USub , Type :: IntLiteral ( value) ) => Type :: IntLiteral ( -value) ,
2213
- ( UnaryOp :: Not , Type :: BooleanLiteral ( value ) ) => Type :: BooleanLiteral ( !value ) ,
2213
+ ( UnaryOp :: Not , ty ) => ty . bool ( self . db ) . negate ( ) . into_type ( self . db ) ,
2214
2214
_ => Type :: Unknown , // TODO other unary op types
2215
2215
}
2216
2216
}
@@ -3161,6 +3161,127 @@ mod tests {
3161
3161
Ok ( ( ) )
3162
3162
}
3163
3163
3164
+ #[ test]
3165
+ fn not_none_literal ( ) -> anyhow:: Result < ( ) > {
3166
+ let mut db = setup_db ( ) ;
3167
+
3168
+ db. write_file (
3169
+ "src/a.py" ,
3170
+ r#"
3171
+ a = not None
3172
+ b = not not None
3173
+ "# ,
3174
+ ) ?;
3175
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[True]" ) ;
3176
+ assert_public_ty ( & db, "src/a.py" , "b" , "Literal[False]" ) ;
3177
+
3178
+ Ok ( ( ) )
3179
+ }
3180
+
3181
+ #[ test]
3182
+ fn not_function ( ) -> anyhow:: Result < ( ) > {
3183
+ let mut db = setup_db ( ) ;
3184
+
3185
+ db. write_file (
3186
+ "src/a.py" ,
3187
+ r#"
3188
+ from typing import reveal_type
3189
+ def f():
3190
+ return 1
3191
+
3192
+ a = not f
3193
+ b = not reveal_type
3194
+ "# ,
3195
+ ) ?;
3196
+
3197
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[False]" ) ;
3198
+ // TODO Unknown should not be part of the type of typing.reveal_type
3199
+ // assert_public_ty(&db, "src/a.py", "b", "Literal[False]");
3200
+ Ok ( ( ) )
3201
+ }
3202
+
3203
+ #[ test]
3204
+ fn not_module ( ) -> anyhow:: Result < ( ) > {
3205
+ let mut db = setup_db ( ) ;
3206
+
3207
+ db. write_files ( [
3208
+ (
3209
+ "src/a.py" ,
3210
+ "import b; import warnings;
3211
+ x = not b;
3212
+ z = not warnings" ,
3213
+ ) ,
3214
+ ( "src/b.py" , "y = 1" ) ,
3215
+ ] ) ?;
3216
+
3217
+ assert_public_ty ( & db, "src/a.py" , "x" , "Literal[False]" ) ;
3218
+ assert_public_ty ( & db, "src/a.py" , "z" , "Literal[False]" ) ;
3219
+
3220
+ Ok ( ( ) )
3221
+ }
3222
+
3223
+ #[ test]
3224
+ fn not_union ( ) -> anyhow:: Result < ( ) > {
3225
+ let mut db = setup_db ( ) ;
3226
+
3227
+ db. write_file (
3228
+ "src/a.py" ,
3229
+ r#"
3230
+ if flag:
3231
+ p = 1
3232
+ q = 3.3
3233
+ r = "hello"
3234
+ s = "world"
3235
+ t = 0
3236
+ else:
3237
+ p = "hello"
3238
+ q = 4
3239
+ r = ""
3240
+ s = 0
3241
+ t = ""
3242
+
3243
+ a = not p
3244
+ b = not q
3245
+ c = not r
3246
+ d = not s
3247
+ e = not t
3248
+ "# ,
3249
+ ) ?;
3250
+
3251
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[False]" ) ;
3252
+ assert_public_ty ( & db, "src/a.py" , "b" , "bool" ) ;
3253
+ assert_public_ty ( & db, "src/a.py" , "c" , "bool" ) ;
3254
+ assert_public_ty ( & db, "src/a.py" , "d" , "bool" ) ;
3255
+ assert_public_ty ( & db, "src/a.py" , "e" , "Literal[True]" ) ;
3256
+
3257
+ Ok ( ( ) )
3258
+ }
3259
+
3260
+ #[ test]
3261
+ fn not_integer_literal ( ) -> anyhow:: Result < ( ) > {
3262
+ let mut db = setup_db ( ) ;
3263
+
3264
+ db. write_file (
3265
+ "src/a.py" ,
3266
+ r#"
3267
+ a = not 1
3268
+ b = not 1234567890987654321
3269
+ e = not 0
3270
+ x = not -1
3271
+ y = not -1234567890987654321
3272
+ z = not --987
3273
+ "# ,
3274
+ ) ?;
3275
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[False]" ) ;
3276
+ assert_public_ty ( & db, "src/a.py" , "b" , "Literal[False]" ) ;
3277
+ assert_public_ty ( & db, "src/a.py" , "e" , "Literal[True]" ) ;
3278
+ assert_public_ty ( & db, "src/a.py" , "x" , "Literal[False]" ) ;
3279
+ assert_public_ty ( & db, "src/a.py" , "y" , "Literal[False]" ) ;
3280
+ assert_public_ty ( & db, "src/a.py" , "z" , "Literal[False]" ) ;
3281
+
3282
+ Ok ( ( ) )
3283
+ }
3284
+
3164
3285
#[ test]
3165
3286
fn not_boolean_literal ( ) -> anyhow:: Result < ( ) > {
3166
3287
let mut db = setup_db ( ) ;
@@ -3183,6 +3304,98 @@ mod tests {
3183
3304
Ok ( ( ) )
3184
3305
}
3185
3306
3307
+ #[ test]
3308
+ fn not_string_literal ( ) -> anyhow:: Result < ( ) > {
3309
+ let mut db = setup_db ( ) ;
3310
+
3311
+ db. write_file (
3312
+ "src/a.py" ,
3313
+ r#"
3314
+ a = not "hello"
3315
+ b = not ""
3316
+ c = not "0"
3317
+ d = not "hello" + "world"
3318
+ "# ,
3319
+ ) ?;
3320
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[False]" ) ;
3321
+ assert_public_ty ( & db, "src/a.py" , "b" , "Literal[True]" ) ;
3322
+ assert_public_ty ( & db, "src/a.py" , "c" , "Literal[False]" ) ;
3323
+ assert_public_ty ( & db, "src/a.py" , "d" , "Literal[False]" ) ;
3324
+
3325
+ Ok ( ( ) )
3326
+ }
3327
+
3328
+ #[ test]
3329
+ fn not_literal_string ( ) -> anyhow:: Result < ( ) > {
3330
+ let mut db = setup_db ( ) ;
3331
+ let content = format ! (
3332
+ r#"
3333
+ v = not "{y}"
3334
+ w = not 10*"{y}"
3335
+ x = not "{y}"*10
3336
+ z = not 0*"{y}"
3337
+ u = not (-100)*"{y}"
3338
+ "# ,
3339
+ y = "a" . repeat( TypeInferenceBuilder :: MAX_STRING_LITERAL_SIZE + 1 ) ,
3340
+ ) ;
3341
+ db. write_dedented ( "src/a.py" , & content) ?;
3342
+
3343
+ assert_public_ty ( & db, "src/a.py" , "v" , "bool" ) ;
3344
+ assert_public_ty ( & db, "src/a.py" , "w" , "bool" ) ;
3345
+ assert_public_ty ( & db, "src/a.py" , "x" , "bool" ) ;
3346
+ assert_public_ty ( & db, "src/a.py" , "z" , "Literal[True]" ) ;
3347
+ assert_public_ty ( & db, "src/a.py" , "u" , "Literal[True]" ) ;
3348
+
3349
+ Ok ( ( ) )
3350
+ }
3351
+
3352
+ #[ test]
3353
+ fn not_bytes_literal ( ) -> anyhow:: Result < ( ) > {
3354
+ let mut db = setup_db ( ) ;
3355
+
3356
+ db. write_file (
3357
+ "src/a.py" ,
3358
+ r#"
3359
+ a = not b"hello"
3360
+ b = not b""
3361
+ c = not b"0"
3362
+ d = not b"hello" + b"world"
3363
+ "# ,
3364
+ ) ?;
3365
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[False]" ) ;
3366
+ assert_public_ty ( & db, "src/a.py" , "b" , "Literal[True]" ) ;
3367
+ assert_public_ty ( & db, "src/a.py" , "c" , "Literal[False]" ) ;
3368
+ assert_public_ty ( & db, "src/a.py" , "d" , "Literal[False]" ) ;
3369
+
3370
+ Ok ( ( ) )
3371
+ }
3372
+
3373
+ #[ test]
3374
+ fn not_tuple ( ) -> anyhow:: Result < ( ) > {
3375
+ let mut db = setup_db ( ) ;
3376
+
3377
+ db. write_file (
3378
+ "src/a.py" ,
3379
+ r#"
3380
+ a = not (1,)
3381
+ b = not (1, 2)
3382
+ c = not (1, 2, 3)
3383
+ d = not ()
3384
+ e = not ("hello",)
3385
+ f = not (1, "hello")
3386
+ "# ,
3387
+ ) ?;
3388
+
3389
+ assert_public_ty ( & db, "src/a.py" , "a" , "Literal[False]" ) ;
3390
+ assert_public_ty ( & db, "src/a.py" , "b" , "Literal[False]" ) ;
3391
+ assert_public_ty ( & db, "src/a.py" , "c" , "Literal[False]" ) ;
3392
+ assert_public_ty ( & db, "src/a.py" , "d" , "Literal[True]" ) ;
3393
+ assert_public_ty ( & db, "src/a.py" , "e" , "Literal[False]" ) ;
3394
+ assert_public_ty ( & db, "src/a.py" , "f" , "Literal[False]" ) ;
3395
+
3396
+ Ok ( ( ) )
3397
+ }
3398
+
3186
3399
#[ test]
3187
3400
fn string_type ( ) -> anyhow:: Result < ( ) > {
3188
3401
let mut db = setup_db ( ) ;
0 commit comments