@@ -877,25 +877,65 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
877877 }
878878
879879 fn infer_negate_bool ( & mut self , location : SrcSpan , value : UntypedExpr ) -> TypedExpr {
880- let value = self . infer ( value) ;
880+ self . infer_multiple_negate_bool ( location, 1 , location, value)
881+ }
881882
883+ fn infer_multiple_negate_bool (
884+ & mut self ,
885+ starting_location : SrcSpan ,
886+ negations : usize ,
887+ location : SrcSpan ,
888+ value : UntypedExpr ,
889+ ) -> TypedExpr {
890+ // If we're typing a double negation we just keep going increasing the
891+ // number of consecutive negations, inferring the wrapped value.
892+ if let UntypedExpr :: NegateBool {
893+ location : inner_location,
894+ value,
895+ } = value
896+ {
897+ return TypedExpr :: NegateBool {
898+ location,
899+ value : Box :: new ( self . infer_multiple_negate_bool (
900+ starting_location,
901+ negations + 1 ,
902+ inner_location,
903+ * value,
904+ ) ) ,
905+ } ;
906+ }
907+
908+ // We know the last value can't be a bool negation if we're here, so
909+ // we're ready to produce a typed value!
910+ let value = self . infer ( value) ;
882911 if let Err ( error) = unify ( bool ( ) , value. type_ ( ) ) {
883912 self . problems
884- . error ( convert_unify_error ( error, value. location ( ) ) )
913+ . error ( convert_unify_error ( error, value. location ( ) ) ) ;
885914 }
886915
887- if let TypedExpr :: NegateBool {
888- location : inner_location,
889- ..
890- } = value
891- {
916+ // If there's more than a single negation we can raise a warning
917+ // highlighting the unneded ones. How many negations are highlighted
918+ // depends if they're an even or odd number:
919+ //
920+ // ```gleam
921+ // !!True // all negations are superfluous.
922+ // !!!True // we can remove all but one negation.
923+ // ```
924+ if negations > 1 {
925+ let location = if negations % 2 == 0 {
926+ SrcSpan {
927+ start : starting_location. start ,
928+ end : location. start + 1 ,
929+ }
930+ } else {
931+ SrcSpan {
932+ start : starting_location. start ,
933+ end : location. start ,
934+ }
935+ } ;
936+
892937 self . problems
893- . warning ( Warning :: UnnecessaryDoubleBoolNegation {
894- location : SrcSpan {
895- start : location. start ,
896- end : inner_location. start + 1 ,
897- } ,
898- } ) ;
938+ . warning ( Warning :: UnnecessaryDoubleBoolNegation { location } ) ;
899939 }
900940
901941 TypedExpr :: NegateBool {
@@ -905,41 +945,82 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
905945 }
906946
907947 fn infer_negate_int ( & mut self , location : SrcSpan , value : UntypedExpr ) -> TypedExpr {
908- let value = self . infer ( value) ;
948+ self . infer_multiple_negate_int ( location, 1 , location, value)
949+ }
909950
951+ fn infer_multiple_negate_int (
952+ & mut self ,
953+ starting_location : SrcSpan ,
954+ mut negations : usize ,
955+ location : SrcSpan ,
956+ value : UntypedExpr ,
957+ ) -> TypedExpr {
958+ // If we're typing a double negation we just keep going increasing the
959+ // number of consecutive negations, inferring the wrapped value.
960+ if let UntypedExpr :: NegateInt {
961+ location : inner_location,
962+ value,
963+ } = value
964+ {
965+ return TypedExpr :: NegateInt {
966+ location,
967+ value : Box :: new ( self . infer_multiple_negate_int (
968+ starting_location,
969+ negations + 1 ,
970+ inner_location,
971+ * value,
972+ ) ) ,
973+ } ;
974+ }
975+
976+ // We know the last value can't be an int negation, so we're ready to
977+ // produce a typed value!
978+ let value = self . infer ( value) ;
910979 if let Err ( error) = unify ( int ( ) , value. type_ ( ) ) {
911980 self . problems
912981 . error ( convert_unify_error ( error, value. location ( ) ) ) ;
913982 }
914983
984+ // This is used to emit a warning in case there's multiple negations.
985+ let mut end = location. start ;
986+
987+ // There's one special case where the final integer being typed might be
988+ // negated as well, in that case we need to update the number of
989+ // consecutive negations.
915990 if let TypedExpr :: Int {
916991 value : ref v,
917- location : ref inner_location ,
992+ ref location ,
918993 ..
919994 } = value
920995 && v. starts_with ( '-' )
921996 {
922- self . problems
923- . warning ( Warning :: UnnecessaryDoubleIntNegation {
924- location : SrcSpan {
925- start : location. start ,
926- end : inner_location. start + 1 ,
927- } ,
928- } ) ;
997+ negations += 1 ;
998+ end = location. start ;
929999 }
9301000
931- if let TypedExpr :: NegateInt {
932- location : inner_location,
933- ..
934- } = value
935- {
1001+ // If there's more than a single negation we can raise a warning
1002+ // highlighting the unneded ones. How many negations are highlighted
1003+ // depends if they're an even or odd number:
1004+ //
1005+ // ```gleam
1006+ // --1 // all negations are superfluous.
1007+ // ---1 // we can remove all but one negation.
1008+ // ```
1009+ if negations > 1 {
1010+ let location = if negations % 2 == 0 {
1011+ SrcSpan {
1012+ start : starting_location. start ,
1013+ end : end + 1 ,
1014+ }
1015+ } else {
1016+ SrcSpan {
1017+ start : starting_location. start ,
1018+ end,
1019+ }
1020+ } ;
1021+
9361022 self . problems
937- . warning ( Warning :: UnnecessaryDoubleIntNegation {
938- location : SrcSpan {
939- start : location. start ,
940- end : inner_location. start + 1 ,
941- } ,
942- } ) ;
1023+ . warning ( Warning :: UnnecessaryDoubleIntNegation { location } ) ;
9431024 }
9441025
9451026 TypedExpr :: NegateInt {
0 commit comments