Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
```
case wibble {
0, _ -> 1
^^^^ Expected 1 patterns, got 2
^^^^ Expected 1 pattern, got 2
0 | -> 1
^ I was expecting a pattern after this
}
Expand All @@ -55,8 +55,8 @@
([Nafi](https://github.com/re-masashi))

- The lowercase bool pattern error is no longer a syntax error, but instead a
part of the analysis step. This allows the entire module to be analyzed, rather
than stopping at the syntax error.
part of the analysis step. This allows the entire module to be analyzed,
rather than stopping at the syntax error.
([mxtthias](https://github.com/mxtthias))

- Exhaustiveness checks for ints and floats now correctly handle unreachable
Expand Down Expand Up @@ -98,6 +98,7 @@
from 1.13 has been extended to int segments!
Aside from the various performance improvements, this allows the compiler to
mark more branches as unreachable.

```gleam
case bits {
<<"a">> -> 0
Expand All @@ -111,6 +112,7 @@
_ -> 99
}
```

([fruno](https://github.com/fruno-bulax/))

### Build tool
Expand Down Expand Up @@ -207,6 +209,11 @@
rename all its occurrences.
([Giacomo Cavalieri](https://github.com/giacomocavalieri))

- The compiler now reports an error for literal floats that are outside the
floating point representable range on both targets. Previously it would only
do that when compiling on the Erlang target.
([Giacomo Cavalieri](https://github.com/giacomocavalieri))

- Fixed a typo in the error message emitted when trying to run a module that
does not have a main function.
([Louis Pilfold](https://github.com/lpil))
Expand Down Expand Up @@ -240,7 +247,8 @@
([Giacomo Cavalieri](https://github.com/giacomocavalieri))

- Fixed a bug where the "pattern match on variable" code action would generate
invalid patterns by repeating a variable name already used in the same pattern.
invalid patterns by repeating a variable name already used in the same
pattern.
([Giacomo Cavalieri](https://github.com/giacomocavalieri))

- Fixed a bug where useless comparison warnings for floats compared literal
Expand Down
8 changes: 4 additions & 4 deletions compiler-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1558,12 +1558,12 @@ The error from the encryption library was:
} => error
.iter()
.map(|error| match error {
TypeError::ErlangFloatUnsafe { location, .. } => Diagnostic {
title: "Float is outside Erlang's floating point range".into(),
TypeError::LiteralFloatOutOfRange { location, .. } => Diagnostic {
title: "Float outside of valid range".into(),
text: wrap(
"This float value is too large to be represented by \
Erlang's floating point type. To avoid this error float values must be in the range \
-1.7976931348623157e308 - 1.7976931348623157e308.",
a floating point type: float values must be in the range -1.7976931348623157e308 \
- 1.7976931348623157e308.",
),
hint: None,
level: Level::Error,
Expand Down
8 changes: 3 additions & 5 deletions compiler-core/src/javascript/tests/numbers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::assert_js;
use crate::{assert_js, assert_js_module_error};

#[test]
fn int_literals() {
Expand Down Expand Up @@ -41,9 +41,7 @@ pub fn go() {
0.01e-0
-10.01e-1
-10.01e-0
100.001e523
-100.001e-523
100.001e123_456_789
-100.001e-123_456_789
}
"#,
Expand Down Expand Up @@ -458,7 +456,7 @@ pub fn main(x) {

#[test]
fn inf_float_case_statement() {
assert_js!(
assert_js_module_error!(
"
pub fn main(x) {
case x {
Expand All @@ -472,7 +470,7 @@ pub fn main(x) {

#[test]
fn division_inf_by_inf_float() {
assert_js!(
assert_js_module_error!(
"
pub fn main(x) {
-100.001e123_456_789 /. 100.001e123_456_789
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,23 @@ pub fn main(x) {
}


----- COMPILED JAVASCRIPT
export function main(x) {
return -Infinity / Infinity;
}
----- ERROR
error: Float outside of valid range
┌─ /src/one/two.gleam:3:3
3 │ -100.001e123_456_789 /. 100.001e123_456_789
│ ^^^^^^^^^^^^^^^^^^^^

This float value is too large to be represented by a floating point type:
float values must be in the range -1.7976931348623157e308 -
1.7976931348623157e308.

error: Float outside of valid range
┌─ /src/one/two.gleam:3:27
3 │ -100.001e123_456_789 /. 100.001e123_456_789
│ ^^^^^^^^^^^^^^^^^^^

This float value is too large to be represented by a floating point type:
float values must be in the range -1.7976931348623157e308 -
1.7976931348623157e308.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: compiler-core/src/javascript/tests/numbers.rs
expression: "\npub fn go() {\n 0.01e-1\n 0.01e-0\n -10.01e-1\n -10.01e-0\n 100.001e523\n -100.001e-523\n 100.001e123_456_789\n -100.001e-123_456_789\n}\n"
expression: "\npub fn go() {\n 0.01e-1\n 0.01e-0\n -10.01e-1\n -10.01e-0\n -100.001e-523\n -100.001e-123_456_789\n}\n"
---
----- SOURCE CODE

Expand All @@ -9,9 +9,7 @@ pub fn go() {
0.01e-0
-10.01e-1
-10.01e-0
100.001e523
-100.001e-523
100.001e123_456_789
-100.001e-123_456_789
}

Expand All @@ -22,8 +20,6 @@ export function go() {
0.01;
-1.001;
-10.01;
Infinity;
-0.0;
Infinity;
return -0.0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ pub fn main(x) {
}


----- COMPILED JAVASCRIPT
export function main(x) {
if (x === Infinity) {
return "bar";
} else {
return "foo";
}
}
----- ERROR
error: Float outside of valid range
┌─ /src/one/two.gleam:4:3
4 │ 100.001e123_456_789 -> "bar"
│ ^^^^^^^^^^^^^^^^^^^

This float value is too large to be represented by a floating point type:
float values must be in the range -1.7976931348623157e308 -
1.7976931348623157e308.
8 changes: 5 additions & 3 deletions compiler-core/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4739,8 +4739,10 @@ impl PatternPosition {
/// This allows us to implement `Eq`, which require reflexivity.
///
/// Used for gleam float literals, which cannot be NaN.
/// While there is no syntax for "infinity", float literals
/// may overflow into (possibly negative) infinity on the JS target.
///
/// While there is no syntax for "infinity", float literals might be too big and
/// overflow into infinity. This is still allowed so we can parse big literal
/// numbers and the error will be raised during the analysis phase.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct LiteralFloatValue(f64);

Expand All @@ -4755,7 +4757,7 @@ impl LiteralFloatValue {
.replace("_", "")
.parse::<f64>()
.ok()
.filter(|f| !f.is_nan())
.filter(|float| !float.is_nan())
.map(LiteralFloatValue)
}

Expand Down
24 changes: 11 additions & 13 deletions compiler-core/src/type_/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,16 @@ pub enum Error {
location: SrcSpan,
},

/// Occers when any varient of a custom type is deprecated while
/// Occurs when any varient of a custom type is deprecated while
/// the custom type itself is deprecated
DeprecatedVariantOnDeprecatedType {
location: SrcSpan,
},

ErlangFloatUnsafe {
/// Occurs when a literal floating point has a value that is outside of the
/// range representable by floats: -1.7976931348623157e308 to
/// 1.7976931348623157e308.
LiteralFloatOutOfRange {
location: SrcSpan,
},

Expand Down Expand Up @@ -1306,7 +1309,7 @@ impl Error {
| Error::AllVariantsDeprecated { location }
| Error::EchoWithNoFollowingExpression { location }
| Error::DeprecatedVariantOnDeprecatedType { location }
| Error::ErlangFloatUnsafe { location }
| Error::LiteralFloatOutOfRange { location }
| Error::FloatOperatorOnInts { location, .. }
| Error::IntOperatorOnFloats { location, .. }
| Error::StringConcatenationWithAddInt { location }
Expand Down Expand Up @@ -1983,17 +1986,12 @@ pub fn check_javascript_int_safety(int_value: &BigInt, location: SrcSpan, proble
/// -1.7976931348623157e308 to 1.7976931348623157e308 which is the allowed range for
/// Erlang's floating point numbers
///
pub fn check_erlang_float_safety(
value: LiteralFloatValue,
location: SrcSpan,
problems: &mut Problems,
) {
let erl_min_float = -1.7976931348623157e308f64;
let erl_max_float = 1.7976931348623157e308f64;
pub fn check_float_safety(value: LiteralFloatValue, location: SrcSpan, problems: &mut Problems) {
let min_float = -1.7976931348623157e308f64;
let max_float = 1.7976931348623157e308f64;

let float_value = value.value();

if float_value < erl_min_float || float_value > erl_max_float {
problems.error(Error::ErlangFloatUnsafe { location });
if float_value < min_float || float_value > max_float {
problems.error(Error::LiteralFloatOutOfRange { location });
}
}
14 changes: 2 additions & 12 deletions compiler-core/src/type_/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,12 +458,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
value,
float_value,
} => {
if self.environment.target == Target::Erlang
&& !self.current_function_definition.has_erlang_external
{
check_erlang_float_safety(float_value, location, self.problems)
}

check_float_safety(float_value, location, self.problems);
Ok(self.infer_float(value, float_value, location))
}

Expand Down Expand Up @@ -2003,7 +1998,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
// Ensure the pattern matches the type of the value
let mut pattern_typer = pattern::PatternTyper::new(
self.environment,
&self.implementations,
&self.current_function_definition,
&self.hydrator,
self.problems,
Expand Down Expand Up @@ -2332,7 +2326,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
) -> (TypedMultiPattern, Vec<TypedMultiPattern>, bool) {
let mut pattern_typer = pattern::PatternTyper::new(
self.environment,
&self.implementations,
&self.current_function_definition,
&self.hydrator,
self.problems,
Expand Down Expand Up @@ -3801,10 +3794,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
value,
float_value,
} => {
if self.environment.target == Target::Erlang {
check_erlang_float_safety(float_value, location, self.problems)
}

check_float_safety(float_value, location, self.problems);
Ok(Constant::Float {
location,
value,
Expand Down
11 changes: 1 addition & 10 deletions compiler-core/src/type_/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use std::sync::Arc;

pub struct PatternTyper<'a, 'b> {
environment: &'a mut Environment<'b>,
implementations: &'a Implementations,
current_function: &'a FunctionDefinition,
hydrator: &'a Hydrator,
mode: PatternMode,
Expand Down Expand Up @@ -98,15 +97,13 @@ enum PatternMode {
impl<'a, 'b> PatternTyper<'a, 'b> {
pub fn new(
environment: &'a mut Environment<'b>,
implementations: &'a Implementations,
current_function: &'a FunctionDefinition,
hydrator: &'a Hydrator,
problems: &'a mut Problems,
position: PatternPosition,
) -> Self {
Self {
environment,
implementations,
current_function,
hydrator,
mode: PatternMode::Initial,
Expand Down Expand Up @@ -753,13 +750,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
float_value,
} => {
self.unify_types(type_, float(), location);

if self.environment.target == Target::Erlang
&& !self.implementations.uses_erlang_externals
{
check_erlang_float_safety(float_value, location, self.problems)
}

check_float_safety(float_value, location, self.problems);
Pattern::Float {
location,
value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ expression: "-1.8e308"
-1.8e308

----- ERROR
error: Float is outside Erlang's floating point range
error: Float outside of valid range
┌─ /src/one/two.gleam:1:1
1 │ -1.8e308
│ ^^^^^^^^

This float value is too large to be represented by Erlang's floating point
type. To avoid this error float values must be in the range
-1.7976931348623157e308 - 1.7976931348623157e308.
This float value is too large to be represented by a floating point type:
float values must be in the range -1.7976931348623157e308 -
1.7976931348623157e308.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ expression: const x = -1.8e308
const x = -1.8e308

----- ERROR
error: Float is outside Erlang's floating point range
error: Float outside of valid range
┌─ /src/one/two.gleam:1:11
1 │ const x = -1.8e308
│ ^^^^^^^^

This float value is too large to be represented by Erlang's floating point
type. To avoid this error float values must be in the range
-1.7976931348623157e308 - 1.7976931348623157e308.
This float value is too large to be represented by a floating point type:
float values must be in the range -1.7976931348623157e308 -
1.7976931348623157e308.
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ error: Unknown variable

The name `y` is not in scope here.

error: Float is outside Erlang's floating point range
error: Float outside of valid range
┌─ /src/one/two.gleam:1:13
1 │ let assert [-1.8e308, b] = [x, y]
│ ^^^^^^^^

This float value is too large to be represented by Erlang's floating point
type. To avoid this error float values must be in the range
-1.7976931348623157e308 - 1.7976931348623157e308.
This float value is too large to be represented by a floating point type:
float values must be in the range -1.7976931348623157e308 -
1.7976931348623157e308.
Loading
Loading