@@ -3779,7 +3779,7 @@ export class Compiler extends DiagnosticEmitter {
3779
3779
3780
3780
rightExpr = this . compileExpression ( right , leftType ) ;
3781
3781
rightType = this . currentType ;
3782
- commonType = Type . commonDenominator ( leftType , rightType , true ) ;
3782
+ commonType = Type . commonType ( leftType , rightType , contextualType , true ) ;
3783
3783
if ( ! commonType || ! commonType . isNumericValue ) {
3784
3784
this . error (
3785
3785
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -3814,7 +3814,7 @@ export class Compiler extends DiagnosticEmitter {
3814
3814
3815
3815
rightExpr = this . compileExpression ( right , leftType ) ;
3816
3816
rightType = this . currentType ;
3817
- commonType = Type . commonDenominator ( leftType , rightType , true ) ;
3817
+ commonType = Type . commonType ( leftType , rightType , contextualType , true ) ;
3818
3818
if ( ! commonType || ! commonType . isNumericValue ) {
3819
3819
this . error (
3820
3820
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -3849,7 +3849,7 @@ export class Compiler extends DiagnosticEmitter {
3849
3849
3850
3850
rightExpr = this . compileExpression ( right , leftType ) ;
3851
3851
rightType = this . currentType ;
3852
- commonType = Type . commonDenominator ( leftType , rightType , true ) ;
3852
+ commonType = Type . commonType ( leftType , rightType , contextualType , true ) ;
3853
3853
if ( ! commonType || ! commonType . isNumericValue ) {
3854
3854
this . error (
3855
3855
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -3884,7 +3884,7 @@ export class Compiler extends DiagnosticEmitter {
3884
3884
3885
3885
rightExpr = this . compileExpression ( right , leftType ) ;
3886
3886
rightType = this . currentType ;
3887
- commonType = Type . commonDenominator ( leftType , rightType , true ) ;
3887
+ commonType = Type . commonType ( leftType , rightType , contextualType , true ) ;
3888
3888
if ( ! commonType || ! commonType . isNumericValue ) {
3889
3889
this . error (
3890
3890
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -3921,7 +3921,7 @@ export class Compiler extends DiagnosticEmitter {
3921
3921
3922
3922
rightExpr = this . compileExpression ( right , leftType ) ;
3923
3923
rightType = this . currentType ;
3924
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
3924
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
3925
3925
if ( ! commonType ) {
3926
3926
this . error (
3927
3927
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -3973,7 +3973,7 @@ export class Compiler extends DiagnosticEmitter {
3973
3973
3974
3974
rightExpr = this . compileExpression ( right , leftType ) ;
3975
3975
rightType = this . currentType ;
3976
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
3976
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
3977
3977
if ( ! commonType ) {
3978
3978
this . error (
3979
3979
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4038,7 +4038,7 @@ export class Compiler extends DiagnosticEmitter {
4038
4038
} else {
4039
4039
rightExpr = this . compileExpression ( right , leftType ) ;
4040
4040
rightType = this . currentType ;
4041
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4041
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4042
4042
if ( ! commonType || ! commonType . isNumericValue ) {
4043
4043
this . error (
4044
4044
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4083,7 +4083,7 @@ export class Compiler extends DiagnosticEmitter {
4083
4083
} else {
4084
4084
rightExpr = this . compileExpression ( right , leftType ) ;
4085
4085
rightType = this . currentType ;
4086
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4086
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4087
4087
if ( ! commonType || ! leftType . isNumericValue ) {
4088
4088
this . error (
4089
4089
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4128,7 +4128,7 @@ export class Compiler extends DiagnosticEmitter {
4128
4128
} else {
4129
4129
rightExpr = this . compileExpression ( right , leftType ) ;
4130
4130
rightType = this . currentType ;
4131
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4131
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4132
4132
if ( ! commonType || ! commonType . isNumericValue ) {
4133
4133
this . error (
4134
4134
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4173,7 +4173,7 @@ export class Compiler extends DiagnosticEmitter {
4173
4173
} else {
4174
4174
rightExpr = this . compileExpression ( right , leftType ) ;
4175
4175
rightType = this . currentType ;
4176
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4176
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4177
4177
if ( ! commonType || ! commonType . isNumericValue ) {
4178
4178
this . error (
4179
4179
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4218,7 +4218,7 @@ export class Compiler extends DiagnosticEmitter {
4218
4218
} else {
4219
4219
rightExpr = this . compileExpression ( right , leftType ) ;
4220
4220
rightType = this . currentType ;
4221
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4221
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4222
4222
if ( ! commonType || ! commonType . isNumericValue ) {
4223
4223
this . error (
4224
4224
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4263,7 +4263,7 @@ export class Compiler extends DiagnosticEmitter {
4263
4263
} else {
4264
4264
rightExpr = this . compileExpression ( right , leftType ) ;
4265
4265
rightType = this . currentType ;
4266
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4266
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4267
4267
if ( ! commonType || ! commonType . isNumericValue ) {
4268
4268
this . error (
4269
4269
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4390,7 +4390,7 @@ export class Compiler extends DiagnosticEmitter {
4390
4390
} else {
4391
4391
rightExpr = this . compileExpression ( right , leftType ) ;
4392
4392
rightType = this . currentType ;
4393
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4393
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4394
4394
if ( ! commonType || ! commonType . isIntegerValue ) {
4395
4395
this . error (
4396
4396
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4435,7 +4435,7 @@ export class Compiler extends DiagnosticEmitter {
4435
4435
} else {
4436
4436
rightExpr = this . compileExpression ( right , leftType ) ;
4437
4437
rightType = this . currentType ;
4438
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4438
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4439
4439
if ( ! commonType || ! commonType . isIntegerValue ) {
4440
4440
this . error (
4441
4441
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4480,7 +4480,7 @@ export class Compiler extends DiagnosticEmitter {
4480
4480
} else {
4481
4481
rightExpr = this . compileExpression ( right , leftType ) ;
4482
4482
rightType = this . currentType ;
4483
- commonType = Type . commonDenominator ( leftType , rightType , false ) ;
4483
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4484
4484
if ( ! commonType || ! commonType . isIntegerValue ) {
4485
4485
this . error (
4486
4486
DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
@@ -4537,8 +4537,21 @@ export class Compiler extends DiagnosticEmitter {
4537
4537
this . currentType = Type . bool ;
4538
4538
4539
4539
} else {
4540
- rightExpr = this . compileExpression ( right , leftType , inheritedConstraints | Constraints . ConvImplicit ) ;
4540
+ rightExpr = this . compileExpression ( right , leftType , inheritedConstraints ) ;
4541
4541
rightType = this . currentType ;
4542
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4543
+ if ( ! commonType ) {
4544
+ this . error (
4545
+ DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
4546
+ expression . range , "&&" , leftType . toString ( ) , rightType . toString ( )
4547
+ ) ;
4548
+ this . currentType = contextualType ;
4549
+ return module . unreachable ( ) ;
4550
+ }
4551
+ leftExpr = this . convertExpression ( leftExpr , leftType , commonType , false , left ) ;
4552
+ leftType = commonType ;
4553
+ rightExpr = this . convertExpression ( rightExpr , rightType , commonType , false , right ) ;
4554
+ rightType = commonType ;
4542
4555
4543
4556
// simplify if copying left is trivial
4544
4557
if ( expr = module . tryCopyTrivialExpression ( leftExpr ) ) {
@@ -4562,7 +4575,7 @@ export class Compiler extends DiagnosticEmitter {
4562
4575
flow . mergeBranch ( rightFlow ) ; // LHS && RHS -> RHS conditionally executes
4563
4576
flow . noteThen ( expr , rightFlow ) ; // LHS && RHS == true -> RHS always executes
4564
4577
this . currentFlow = flow ;
4565
- this . currentType = leftType ;
4578
+ this . currentType = commonType ;
4566
4579
}
4567
4580
break ;
4568
4581
}
@@ -4603,8 +4616,22 @@ export class Compiler extends DiagnosticEmitter {
4603
4616
this . currentType = Type . bool ;
4604
4617
4605
4618
} else {
4606
- rightExpr = this . compileExpression ( right , leftType , inheritedConstraints | Constraints . ConvImplicit ) ;
4619
+ rightExpr = this . compileExpression ( right , leftType , inheritedConstraints ) ;
4607
4620
rightType = this . currentType ;
4621
+ commonType = Type . commonType ( leftType , rightType , contextualType ) ;
4622
+ if ( ! commonType ) {
4623
+ this . error (
4624
+ DiagnosticCode . Operator_0_cannot_be_applied_to_types_1_and_2 ,
4625
+ expression . range , "||" , leftType . toString ( ) , rightType . toString ( )
4626
+ ) ;
4627
+ this . currentType = contextualType ;
4628
+ return module . unreachable ( ) ;
4629
+ }
4630
+ let possiblyNull = leftType . is ( TypeFlags . Nullable ) && rightType . is ( TypeFlags . Nullable ) ;
4631
+ leftExpr = this . convertExpression ( leftExpr , leftType , commonType , false , left ) ;
4632
+ leftType = commonType ;
4633
+ rightExpr = this . convertExpression ( rightExpr , rightType , commonType , false , right ) ;
4634
+ rightType = commonType ;
4608
4635
4609
4636
// simplify if copying left is trivial
4610
4637
if ( expr = module . tryCopyTrivialExpression ( leftExpr ) ) {
@@ -4629,7 +4656,9 @@ export class Compiler extends DiagnosticEmitter {
4629
4656
flow . mergeBranch ( rightFlow ) ; // LHS || RHS -> RHS conditionally executes
4630
4657
flow . noteElse ( expr , rightFlow ) ; // LHS || RHS == false -> RHS always executes
4631
4658
this . currentFlow = flow ;
4632
- this . currentType = leftType ;
4659
+ this . currentType = possiblyNull
4660
+ ? commonType
4661
+ : commonType . nonNullableType ;
4633
4662
}
4634
4663
break ;
4635
4664
}
@@ -8945,7 +8974,7 @@ export class Compiler extends DiagnosticEmitter {
8945
8974
8946
8975
private compileTernaryExpression (
8947
8976
expression : TernaryExpression ,
8948
- ctxType : Type ,
8977
+ contextualType : Type ,
8949
8978
constraints : Constraints
8950
8979
) : ExpressionRef {
8951
8980
let module = this . module ;
@@ -8958,24 +8987,24 @@ export class Compiler extends DiagnosticEmitter {
8958
8987
// FIXME: skips common denominator, inconsistently picking branch type
8959
8988
let condKind = this . evaluateCondition ( condExprTrueish ) ;
8960
8989
if ( condKind == ConditionKind . True ) {
8961
- return module . maybeDropCondition ( condExprTrueish , this . compileExpression ( ifThen , ctxType ) ) ;
8990
+ return module . maybeDropCondition ( condExprTrueish , this . compileExpression ( ifThen , contextualType ) ) ;
8962
8991
}
8963
8992
if ( condKind == ConditionKind . False ) {
8964
- return module . maybeDropCondition ( condExprTrueish , this . compileExpression ( ifElse , ctxType ) ) ;
8993
+ return module . maybeDropCondition ( condExprTrueish , this . compileExpression ( ifElse , contextualType ) ) ;
8965
8994
}
8966
8995
8967
8996
let outerFlow = this . currentFlow ;
8968
8997
let ifThenFlow = outerFlow . forkThen ( condExpr ) ;
8969
8998
this . currentFlow = ifThenFlow ;
8970
- let ifThenExpr = this . compileExpression ( ifThen , ctxType ) ;
8999
+ let ifThenExpr = this . compileExpression ( ifThen , contextualType ) ;
8971
9000
let ifThenType = this . currentType ;
8972
9001
8973
9002
let ifElseFlow = outerFlow . forkElse ( condExpr ) ;
8974
9003
this . currentFlow = ifElseFlow ;
8975
- let ifElseExpr = this . compileExpression ( ifElse , ctxType == Type . auto ? ifThenType : ctxType ) ;
9004
+ let ifElseExpr = this . compileExpression ( ifElse , contextualType == Type . auto ? ifThenType : contextualType ) ;
8976
9005
let ifElseType = this . currentType ;
8977
9006
8978
- if ( ctxType == Type . void ) { // values, including type mismatch, are irrelevant
9007
+ if ( contextualType == Type . void ) { // values, including type mismatch, are irrelevant
8979
9008
if ( ifThenType != Type . void ) {
8980
9009
ifThenExpr = module . drop ( ifThenExpr ) ;
8981
9010
ifThenType = Type . void ;
@@ -8986,13 +9015,13 @@ export class Compiler extends DiagnosticEmitter {
8986
9015
}
8987
9016
this . currentType = Type . void ;
8988
9017
} else {
8989
- let commonType = Type . commonDenominator ( ifThenType , ifElseType , false ) ;
9018
+ let commonType = Type . commonType ( ifThenType , ifElseType , contextualType ) ;
8990
9019
if ( ! commonType ) {
8991
9020
this . error (
8992
9021
DiagnosticCode . Type_0_is_not_assignable_to_type_1 ,
8993
9022
ifElse . range , ifElseType . toString ( ) , ifThenType . toString ( )
8994
9023
) ;
8995
- this . currentType = ctxType ;
9024
+ this . currentType = contextualType ;
8996
9025
return module . unreachable ( ) ;
8997
9026
}
8998
9027
ifThenExpr = this . convertExpression ( ifThenExpr , ifThenType , commonType , false , ifThen ) ;
0 commit comments