diff --git a/compiler-core/src/ast/constant.rs b/compiler-core/src/ast/constant.rs index dbc71ec..0d90904 100644 --- a/compiler-core/src/ast/constant.rs +++ b/compiler-core/src/ast/constant.rs @@ -638,6 +638,25 @@ impl Constant { } } + #[must_use] + pub fn with_location(mut self, new_location: SrcSpan) -> Self { + match &mut self { + Constant::Int { location, .. } + | Constant::List { location, .. } + | Constant::Float { location, .. } + | Constant::Tuple { location, .. } + | Constant::String { location, .. } + | Constant::Record { location, .. } + | Constant::RecordUpdate { location, .. } + | Constant::BitArray { location, .. } + | Constant::Var { location, .. } + | Constant::Invalid { location, .. } + | Constant::Todo { location, .. } + | Constant::BinaryOperator { location, .. } => *location = new_location, + } + self + } + #[must_use] pub fn can_have_multiple_per_line(&self) -> bool { match self { diff --git a/compiler-core/src/type_/guard.rs b/compiler-core/src/type_/guard.rs index 0a1ff48..890890f 100644 --- a/compiler-core/src/type_/guard.rs +++ b/compiler-core/src/type_/guard.rs @@ -320,7 +320,8 @@ impl<'expression_typer, 'env, 'module> GuardTyper<'expression_typer, 'env, 'modu } ValueConstructorVariant::ModuleConstant { literal, .. } => { - return Ok(ClauseGuard::Constant(literal.clone())); + let literal = literal.clone().with_location(location); + return Ok(ClauseGuard::Constant(literal)); } }; diff --git a/compiler-core/src/type_/tests/guards.rs b/compiler-core/src/type_/tests/guards.rs index aa2afef..c68741d 100644 --- a/compiler-core/src/type_/tests/guards.rs +++ b/compiler-core/src/type_/tests/guards.rs @@ -87,3 +87,42 @@ pub fn main(wibble: wibble.Wibble) { vec![("main", "fn(Wibble) -> Bool")] ); } + +#[test] +fn constant_with_wrong_type_in_guard() { + assert_module_error!( + r#" +pub type Wibble { + Wibble(String) +} + +pub const constant = Wibble("Hi") + +pub fn main() { + let wibble = "wibble" + case 1 { + _ if wibble == constant -> Nil + _ -> Nil + } +} +"# + ); +} + +#[test] +fn unqualified_imported_constant_with_wrong_type_in_guard() { + assert_module_error!( + ("wibble", "pub const constant = 1"), + r#" +import wibble.{constant} + +pub fn main() { + let wibble = "wibble" + case 1 { + _ if wibble == constant -> Nil + _ -> Nil + } +} +"# + ); +} diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__guards__constant_with_wrong_type_in_guard.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__guards__constant_with_wrong_type_in_guard.snap new file mode 100644 index 0000000..bef7301 --- /dev/null +++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__guards__constant_with_wrong_type_in_guard.snap @@ -0,0 +1,35 @@ +--- +source: compiler-core/src/type_/tests/guards.rs +expression: "\npub type Wibble {\n Wibble(String)\n}\n\npub const constant = Wibble(\"Hi\")\n\npub fn main() {\n let wibble = \"wibble\"\n case 1 {\n _ if wibble == constant -> Nil\n _ -> Nil\n }\n}\n" +--- +----- SOURCE CODE + +pub type Wibble { + Wibble(String) +} + +pub const constant = Wibble("Hi") + +pub fn main() { + let wibble = "wibble" + case 1 { + _ if wibble == constant -> Nil + _ -> Nil + } +} + + +----- ERROR +error: Type mismatch + ┌─ /src/one/two.gleam:11:20 + │ +11 │ _ if wibble == constant -> Nil + │ ^^^^^^^^ + +Expected type: + + String + +Found type: + + Wibble diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__guards__unqualified_imported_constant_with_wrong_type_in_guard.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__guards__unqualified_imported_constant_with_wrong_type_in_guard.snap new file mode 100644 index 0000000..2b75bd3 --- /dev/null +++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__guards__unqualified_imported_constant_with_wrong_type_in_guard.snap @@ -0,0 +1,35 @@ +--- +source: compiler-core/src/type_/tests/guards.rs +expression: "\nimport wibble.{constant}\n\npub fn main() {\n let wibble = \"wibble\"\n case 1 {\n _ if wibble == constant -> Nil\n _ -> Nil\n }\n}\n" +--- +----- SOURCE CODE +-- wibble.gleam +pub const constant = 1 + +-- main.gleam + +import wibble.{constant} + +pub fn main() { + let wibble = "wibble" + case 1 { + _ if wibble == constant -> Nil + _ -> Nil + } +} + + +----- ERROR +error: Type mismatch + ┌─ /src/one/two.gleam:7:20 + │ +7 │ _ if wibble == constant -> Nil + │ ^^^^^^^^ + +Expected type: + + String + +Found type: + + Int