From 9f24a5c577a3ef10985e84776807184dd740e780 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Sat, 22 Feb 2025 17:53:58 +0100 Subject: [PATCH] Fix wrong use of 'UnknownVariable' instead of 'UnknownTypeConstructor' While the feedback for human users is mostly the same, it does in fact matter for the LSP since the quickfix will be different depending on whether we look for a top-level identifier or if we look for a constructor. The typical case we see in the stdlib is the `VerificationKey` and `Script` constructors for `Credential`, often being mixed with their types counterparts in aiken/crypto! Signed-off-by: KtorZ --- CHANGELOG.md | 6 ++++++ crates/aiken-lang/src/tipo.rs | 4 ++++ crates/aiken-lang/src/tipo/error.rs | 6 +----- crates/aiken-lang/src/tipo/expr.rs | 32 ++++++++++++++++++++++++----- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35221e9b..af839752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.1.15 - UNRELEASED + +### Changed + +- **aiken-lang**: fixed `UnknownTypeConstructor` wrongly reported as `UnknownVariable` (then messing up with LSP quickfix suggestions). @KtorZ + ## v1.1.14 - 2025-02-21 ### Changed diff --git a/crates/aiken-lang/src/tipo.rs b/crates/aiken-lang/src/tipo.rs index 5b09da53..3952d84b 100644 --- a/crates/aiken-lang/src/tipo.rs +++ b/crates/aiken-lang/src/tipo.rs @@ -1357,6 +1357,10 @@ impl TypeConstructor { public: true, } } + + pub fn might_be(name: &str) -> bool { + name.chars().next().unwrap().is_uppercase() + } } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] diff --git a/crates/aiken-lang/src/tipo/error.rs b/crates/aiken-lang/src/tipo/error.rs index 7b5cda49..21c22220 100644 --- a/crates/aiken-lang/src/tipo/error.rs +++ b/crates/aiken-lang/src/tipo/error.rs @@ -914,11 +914,7 @@ Perhaps, try the following: suggest_neighbor( name, variables.iter(), - &if name.chars().next().unwrap().is_uppercase() { - suggest_import_constructor() - } else { - "Did you forget to import it?".to_string() - } + "Did you forget to import it?", ) ))] UnknownVariable { diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index f04689f3..5064da62 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -21,7 +21,9 @@ use crate::{ expr::{FnStyle, TypedExpr, UntypedExpr}, format, parser::token::Base, - tipo::{fields::FieldMap, DefaultFunction, ModuleKind, PatternConstructor, TypeVar}, + tipo::{ + fields::FieldMap, DefaultFunction, ModuleKind, PatternConstructor, TypeConstructor, TypeVar, + }, IdGenerator, }; use std::{ @@ -2481,10 +2483,30 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.environment .get_variable(name) .cloned() - .ok_or_else(|| Error::UnknownVariable { - location: *location, - name: name.to_string(), - variables: self.environment.local_value_names(), + .ok_or_else(|| { + if TypeConstructor::might_be(name) { + Error::UnknownTypeConstructor { + location: *location, + name: name.to_string(), + constructors: self + .environment + .local_value_names() + .into_iter() + .filter(|s| TypeConstructor::might_be(s)) + .collect::>(), + } + } else { + Error::UnknownVariable { + location: *location, + name: name.to_string(), + variables: self + .environment + .local_value_names() + .into_iter() + .filter(|s| !TypeConstructor::might_be(s)) + .collect::>(), + } + } })?; if let ValueConstructorVariant::ModuleFn { name: fn_name, .. } =