Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Update to rust edition 2024

+1529 -1367
+1 -1
compiler-cli/Cargo.toml
··· 2 2 name = "gleam" 3 3 version = "1.8.1" 4 4 authors = ["Louis Pilfold <louis@lpil.uk>"] 5 - edition = "2021" 5 + edition = "2024" 6 6 license-file = "LICENCE" 7 7 8 8 [dependencies]
+2 -2
compiler-cli/src/add.rs
··· 1 1 use camino::{Utf8Path, Utf8PathBuf}; 2 2 3 3 use gleam_core::{ 4 + Error, Result, 4 5 error::{FileIoAction, FileKind}, 5 6 paths::ProjectPaths, 6 - Error, Result, 7 7 }; 8 8 9 9 use crate::{ 10 10 cli, 11 - dependencies::{parse_gleam_add_specifier, UseManifest}, 11 + dependencies::{UseManifest, parse_gleam_add_specifier}, 12 12 fs, 13 13 }; 14 14
+7 -9
compiler-cli/src/beam_compiler.rs
··· 1 1 use gleam_core::{ 2 + Result, 2 3 error::{Error, ShellCommandFailureReason}, 3 4 io::{FileSystemWriter, Stdio}, 4 - paths, Result, 5 + paths, 5 6 }; 6 7 7 8 use crate::fs::get_os; ··· 37 38 stdio: Stdio, 38 39 ) -> Result<Vec<String>, Error> { 39 40 let inner = match self.inner { 40 - Some(ref mut inner) => { 41 - if let Ok(None) = inner.process.try_wait() { 42 - inner 43 - } else { 44 - self.inner.insert(self.spawn(io, out)?) 45 - } 46 - } 41 + Some(ref mut inner) => match inner.process.try_wait() { 42 + Ok(None) => inner, 43 + _ => self.inner.insert(self.spawn(io, out)?), 44 + }, 47 45 48 46 None => self.inner.insert(self.spawn(io, out)?), 49 47 }; ··· 77 75 return Err(Error::ShellCommand { 78 76 program: "escript".into(), 79 77 reason: ShellCommandFailureReason::Unknown, 80 - }) 78 + }); 81 79 } 82 80 s if s.starts_with("gleam-compile-module:") => { 83 81 if let Some(module_content) = s.strip_prefix("gleam-compile-module:") {
+1 -1
compiler-cli/src/build.rs
··· 1 1 use std::{rc::Rc, time::Instant}; 2 2 3 3 use gleam_core::{ 4 + Result, 4 5 build::{Built, Codegen, NullTelemetry, Options, ProjectCompiler, Telemetry}, 5 6 manifest::Manifest, 6 7 paths::ProjectPaths, 7 8 warning::WarningEmitterIO, 8 - Result, 9 9 }; 10 10 11 11 use crate::{
+1 -1
compiler-cli/src/build_lock.rs
··· 1 1 use camino::Utf8PathBuf; 2 2 use gleam_core::{ 3 + Error, Result, 3 4 build::{Mode, Target, Telemetry}, 4 5 error::{FileIoAction, FileKind}, 5 6 paths::ProjectPaths, 6 - Error, Result, 7 7 }; 8 8 use strum::IntoEnumIterator; 9 9
+2 -3
compiler-cli/src/compile_package.rs
··· 1 1 use crate::{ 2 - config, 2 + CompilePackage, config, 3 3 fs::{self, ConsoleWarningEmitter, ProjectIO}, 4 - CompilePackage, 5 4 }; 6 5 use camino::Utf8Path; 7 6 use ecow::EcoString; 8 7 use gleam_core::{ 8 + Error, Result, 9 9 build::{ 10 10 Mode, NullTelemetry, PackageCompiler, StaleTracker, Target, TargetCodegenConfiguration, 11 11 }, ··· 14 14 type_::ModuleInterface, 15 15 uid::UniqueIdGenerator, 16 16 warning::WarningEmitter, 17 - Error, Result, 18 17 }; 19 18 use std::{collections::HashSet, rc::Rc}; 20 19
+4 -4
compiler-cli/src/dependencies.rs
··· 5 5 }; 6 6 7 7 use camino::{Utf8Path, Utf8PathBuf}; 8 - use ecow::{eco_format, EcoString}; 8 + use ecow::{EcoString, eco_format}; 9 9 use flate2::read::GzDecoder; 10 10 use futures::future; 11 11 use gleam_core::{ 12 + Error, Result, 12 13 build::{Mode, Target, Telemetry}, 13 14 config::PackageConfig, 14 15 dependency, ··· 18 19 manifest::{Base16Checksum, Manifest, ManifestPackage, ManifestPackageSource}, 19 20 paths::ProjectPaths, 20 21 requirement::Requirement, 21 - Error, Result, 22 22 }; 23 23 use hexpm::version::Version; 24 24 use itertools::Itertools; ··· 29 29 mod tests; 30 30 31 31 use crate::{ 32 + TreeOptions, 32 33 build_lock::BuildLock, 33 34 cli, 34 35 fs::{self, ProjectIO}, 35 36 http::HttpClient, 36 - TreeOptions, 37 37 }; 38 38 39 39 struct Symbols { ··· 336 336 error: format!( 337 337 "Expected up to 3 numbers in version specifier (MAJOR.MINOR.PATCH), found {n}" 338 338 ), 339 - }) 339 + }); 340 340 } 341 341 }; 342 342
+25 -17
compiler-cli/src/dependencies/tests.rs
··· 6 6 use pretty_assertions::assert_eq; 7 7 8 8 use gleam_core::{ 9 + Error, 9 10 build::Runtime, 10 11 config::{DenoConfig, DenoFlag, Docs, ErlangConfig, JavaScriptConfig, Repository}, 11 12 manifest::{Base16Checksum, Manifest, ManifestPackage, ManifestPackageSource}, 12 13 requirement::Requirement, 13 - Error, 14 14 }; 15 15 16 16 use crate::dependencies::*; ··· 507 507 &mut provided, 508 508 &mut vec!["root".into(), "subpackage".into()], 509 509 ); 510 - if let Err(Error::WrongDependencyProvided { 511 - expected, found, .. 512 - }) = result 513 - { 514 - assert_eq!(expected, "wrong_name"); 515 - assert_eq!(found, "hello_world"); 516 - } else { 517 - panic!("Expected WrongDependencyProvided error") 510 + match result { 511 + Err(Error::WrongDependencyProvided { 512 + expected, found, .. 513 + }) => { 514 + assert_eq!(expected, "wrong_name"); 515 + assert_eq!(found, "hello_world"); 516 + } 517 + _ => { 518 + panic!("Expected WrongDependencyProvided error") 519 + } 518 520 } 519 521 } 520 522 ··· 568 570 &mut provided, 569 571 &mut vec!["root".into(), "subpackage".into()], 570 572 ); 571 - if let Err(Error::ProvidedDependencyConflict { package, .. }) = result { 572 - assert_eq!(package, "hello_world"); 573 - } else { 574 - panic!("Expected ProvidedDependencyConflict error") 573 + match result { 574 + Err(Error::ProvidedDependencyConflict { package, .. }) => { 575 + assert_eq!(package, "hello_world"); 576 + } 577 + _ => { 578 + panic!("Expected ProvidedDependencyConflict error") 579 + } 575 580 } 576 581 } 577 582 ··· 589 594 ); 590 595 assert_eq!(result, Ok(hexpm::version::Range::new("== 0.1.0".into()))); 591 596 let package = provided.get("hello_world").unwrap().clone(); 592 - if let ProvidedPackageSource::Local { path } = package.source { 593 - assert!(path.is_absolute()) 594 - } else { 595 - panic!("Provide_local_package provided a package that is not local!") 597 + match package.source { 598 + ProvidedPackageSource::Local { path } => { 599 + assert!(path.is_absolute()) 600 + } 601 + _ => { 602 + panic!("Provide_local_package provided a package that is not local!") 603 + } 596 604 } 597 605 } 598 606
+1 -1
compiler-cli/src/docs.rs
··· 4 4 5 5 use crate::{cli, fs::ProjectIO, http::HttpClient}; 6 6 use gleam_core::{ 7 + Result, 7 8 analyse::TargetSupport, 8 9 build::{Codegen, Compile, Mode, Options, Package, Target}, 9 10 config::{DocsPage, PackageConfig}, ··· 12 13 hex, 13 14 io::HttpClient as _, 14 15 paths::ProjectPaths, 15 - Result, 16 16 }; 17 17 18 18 pub fn remove(package: String, version: String) -> Result<()> {
+1 -1
compiler-cli/src/export.rs
··· 1 1 use camino::Utf8PathBuf; 2 2 use gleam_core::{ 3 + Result, 3 4 analyse::TargetSupport, 4 5 build::{Codegen, Compile, Mode, Options, Target}, 5 6 paths::ProjectPaths, 6 - Result, 7 7 }; 8 8 9 9 #[cfg(target_os = "windows")]
+1 -1
compiler-cli/src/fix.rs
··· 1 1 use std::rc::Rc; 2 2 3 3 use gleam_core::{ 4 + Error, Result, Warning, 4 5 analyse::TargetSupport, 5 6 build::{Codegen, Compile, Mode, Options}, 6 7 error::{FileIoAction, FileKind}, 7 8 paths::ProjectPaths, 8 9 type_, 9 10 warning::VectorWarningEmitterIO, 10 - Error, Result, Warning, 11 11 }; 12 12 use hexpm::version::Version; 13 13
+2 -2
compiler-cli/src/fs.rs
··· 1 1 use gleam_core::{ 2 + Result, Warning, 2 3 build::{NullTelemetry, Target}, 3 - error::{parse_os, Error, FileIoAction, FileKind, ShellCommandFailureReason, OS}, 4 + error::{Error, FileIoAction, FileKind, OS, ShellCommandFailureReason, parse_os}, 4 5 io::{ 5 6 BeamCompiler, Command, CommandExecutor, Content, DirEntry, FileSystemReader, 6 7 FileSystemWriter, OutputFile, ReadDir, Stdio, WrappedReader, ··· 9 10 manifest::Manifest, 10 11 paths::ProjectPaths, 11 12 warning::WarningEmitterIO, 12 - Result, Warning, 13 13 }; 14 14 use std::{ 15 15 collections::HashSet,
+1 -1
compiler-cli/src/hex.rs
··· 2 2 3 3 use crate::{cli, http::HttpClient}; 4 4 use gleam_core::{ 5 + Error, Result, 5 6 hex::{self, RetirementReason}, 6 7 io::HttpClient as _, 7 8 paths::ProjectPaths, 8 - Error, Result, 9 9 }; 10 10 11 11 pub use auth::HexAuthentication;
+1 -1
compiler-cli/src/hex/auth.rs
··· 1 1 use crate::{cli, http::HttpClient}; 2 - use gleam_core::{encryption, hex, paths::global_hexpm_credentials_path, Error, Result}; 2 + use gleam_core::{Error, Result, encryption, hex, paths::global_hexpm_credentials_path}; 3 3 use std::time::SystemTime; 4 4 5 5 pub const USER_PROMPT: &str = "https://hex.pm username";
+1 -1
compiler-cli/src/http.rs
··· 4 4 use async_trait::async_trait; 5 5 use camino::Utf8PathBuf; 6 6 use gleam_core::{ 7 - error::{FileIoAction, FileKind}, 8 7 Error, Result, 8 + error::{FileIoAction, FileKind}, 9 9 }; 10 10 use http::{Request, Response}; 11 11 use reqwest::{Certificate, Client};
+1 -1
compiler-cli/src/lsp.rs
··· 1 1 use crate::{build_lock::BuildLock, fs::ProjectIO}; 2 2 use gleam_core::{ 3 + Result, 3 4 build::{Mode, NullTelemetry, Target}, 4 5 language_server::{LanguageServer, LockGuard, Locker}, 5 6 paths::ProjectPaths, 6 - Result, 7 7 }; 8 8 9 9 pub fn main() -> Result<()> {
+1 -1
compiler-cli/src/main.rs
··· 88 88 use camino::Utf8PathBuf; 89 89 90 90 use clap::{ 91 - builder::{styling, PossibleValuesParser, Styles, TypedValueParser}, 92 91 Args, Parser, Subcommand, 92 + builder::{PossibleValuesParser, Styles, TypedValueParser, styling}, 93 93 }; 94 94 use strum::VariantNames; 95 95
+4 -4
compiler-cli/src/new.rs
··· 1 1 use camino::{Utf8Path, Utf8PathBuf}; 2 2 use clap::ValueEnum; 3 3 use gleam_core::{ 4 - erlang, error, 4 + Result, erlang, error, 5 5 error::{Error, FileIoAction, FileKind, InvalidProjectNameReason}, 6 - parse, Result, 6 + parse, 7 7 }; 8 8 use serde::{Deserialize, Serialize}; 9 9 use std::fs::File; ··· 13 13 #[cfg(test)] 14 14 mod tests; 15 15 16 - use crate::{fs::get_current_directory, NewOptions}; 16 + use crate::{NewOptions, fs::get_current_directory}; 17 17 18 18 const GLEAM_STDLIB_REQUIREMENT: &str = ">= 0.44.0 and < 2.0.0"; 19 19 const GLEEUNIT_REQUIREMENT: &str = ">= 1.0.0 and < 2.0.0"; ··· 419 419 return Err(Error::InvalidProjectName { 420 420 name: initial_name, 421 421 reason: invalid_reason, 422 - }) 422 + }); 423 423 } 424 424 }; 425 425 let prompt_for_suggested_name = error::format_invalid_project_name_error(
+55 -44
compiler-cli/src/new/tests.rs
··· 53 53 54 54 insta::glob!(path, "my_project/*.*", |file_path| { 55 55 if !file_path.is_dir() { 56 - insta::assert_snapshot!(crate::fs::read( 57 - Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect("Non Utf8 Path"), 58 - ) 59 - .unwrap()); 56 + insta::assert_snapshot!( 57 + crate::fs::read( 58 + Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect("Non Utf8 Path"), 59 + ) 60 + .unwrap() 61 + ); 60 62 } 61 63 }); 62 64 } ··· 81 83 82 84 insta::glob!(path, "my_project/*.*", |file_path| { 83 85 if !file_path.is_dir() { 84 - insta::assert_snapshot!(crate::fs::read( 85 - Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect("Non Utf8 Path"), 86 - ) 87 - .unwrap()); 86 + insta::assert_snapshot!( 87 + crate::fs::read( 88 + Utf8PathBuf::from_path_buf(file_path.to_path_buf()).expect("Non Utf8 Path"), 89 + ) 90 + .unwrap() 91 + ); 88 92 } 89 93 }); 90 94 } ··· 163 167 let tmp = tempfile::tempdir().unwrap(); 164 168 let path = Utf8PathBuf::from_path_buf(tmp.path().join("-------")).expect("Non Utf8 Path"); 165 169 166 - assert!(super::Creator::new( 167 - super::NewOptions { 168 - project_root: path.to_string(), 169 - template: super::Template::Erlang, 170 - name: None, 171 - skip_git: false, 172 - skip_github: false, 173 - }, 174 - "1.0.0-gleam", 175 - ) 176 - .is_err()); 170 + assert!( 171 + super::Creator::new( 172 + super::NewOptions { 173 + project_root: path.to_string(), 174 + template: super::Template::Erlang, 175 + name: None, 176 + skip_git: false, 177 + skip_github: false, 178 + }, 179 + "1.0.0-gleam", 180 + ) 181 + .is_err() 182 + ); 177 183 } 178 184 179 185 #[test] ··· 181 187 let tmp = tempfile::tempdir().unwrap(); 182 188 let path = Utf8PathBuf::from_path_buf(tmp.path().join("projec")).expect("Non Utf8 Path"); 183 189 184 - assert!(super::Creator::new( 185 - super::NewOptions { 186 - project_root: path.to_string(), 187 - template: super::Template::Erlang, 188 - name: Some("-".into()), 189 - skip_git: false, 190 - skip_github: false, 191 - }, 192 - "1.0.0-gleam", 193 - ) 194 - .is_err()); 190 + assert!( 191 + super::Creator::new( 192 + super::NewOptions { 193 + project_root: path.to_string(), 194 + template: super::Template::Erlang, 195 + name: Some("-".into()), 196 + skip_git: false, 197 + skip_github: false, 198 + }, 199 + "1.0.0-gleam", 200 + ) 201 + .is_err() 202 + ); 195 203 } 196 204 197 205 #[test] ··· 228 236 let _ = std::fs::File::create(PathBuf::from(&path).join("README.md")).unwrap(); 229 237 let _ = std::fs::File::create(PathBuf::from(&path).join("my_project.gleam")).unwrap(); 230 238 231 - assert!(super::Creator::new( 232 - super::NewOptions { 233 - project_root: path.to_string(), 234 - template: super::Template::Erlang, 235 - name: None, 236 - skip_git: true, 237 - skip_github: true, 238 - }, 239 - "1.0.0-gleam", 240 - ) 241 - .is_err()); 239 + assert!( 240 + super::Creator::new( 241 + super::NewOptions { 242 + project_root: path.to_string(), 243 + template: super::Template::Erlang, 244 + name: None, 245 + skip_git: true, 246 + skip_github: true, 247 + }, 248 + "1.0.0-gleam", 249 + ) 250 + .is_err() 251 + ); 242 252 } 243 253 244 254 #[test] ··· 266 276 creator.run().unwrap(); 267 277 268 278 assert!(path.join("README.md").exists()); 269 - assert!(path 270 - .join("some_fake_thing_that_is_not_generated.md") 271 - .exists()); 279 + assert!( 280 + path.join("some_fake_thing_that_is_not_generated.md") 281 + .exists() 282 + ); 272 283 } 273 284 274 285 #[test]
+3 -3
compiler-cli/src/publish.rs
··· 1 1 use camino::{Utf8Path, Utf8PathBuf}; 2 - use flate2::{write::GzEncoder, Compression}; 2 + use flate2::{Compression, write::GzEncoder}; 3 3 use gleam_core::{ 4 + Error, Result, 4 5 analyse::TargetSupport, 5 6 build::{Codegen, Compile, Mode, Options, Package, Target}, 6 7 config::{PackageConfig, SpdxLicense}, 7 8 docs::DocContext, 8 - error::{wrap, SmallVersion}, 9 + error::{SmallVersion, wrap}, 9 10 hex, 10 11 paths::{self, ProjectPaths}, 11 12 requirement::Requirement, 12 - Error, Result, 13 13 }; 14 14 use hexpm::version::{Range, Version}; 15 15 use itertools::Itertools;
+1 -1
compiler-cli/src/remove.rs
··· 1 1 use gleam_core::{ 2 + Error, Result, 2 3 error::{FileIoAction, FileKind}, 3 4 paths::ProjectPaths, 4 - Error, Result, 5 5 }; 6 6 7 7 use crate::{cli, fs};
+1 -1
compiler-core/Cargo.toml
··· 2 2 name = "gleam-core" 3 3 version = "1.8.1" 4 4 authors = ["Louis Pilfold <louis@lpil.uk>"] 5 - edition = "2021" 5 + edition = "2024" 6 6 license-file = "LICENCE" 7 7 8 8 [dependencies]
+26 -26
compiler-core/src/analyse.rs
··· 5 5 mod tests; 6 6 7 7 use crate::{ 8 + GLEAM_CORE_PACKAGE_NAME, 8 9 ast::{ 9 10 self, Arg, BitArrayOption, CustomType, Definition, DefinitionLocation, Function, 10 11 GroupedStatements, Import, ModuleConstant, Publicity, RecordConstructor, ··· 14 15 UntypedModule, UntypedModuleConstant, UntypedStatement, UntypedTypeAlias, 15 16 }, 16 17 build::{Origin, Outcome, Target}, 17 - call_graph::{into_dependency_order, CallGraphNode}, 18 + call_graph::{CallGraphNode, into_dependency_order}, 18 19 config::PackageConfig, 19 20 dep_tree, 20 21 line_numbers::LineNumbers, 21 22 parse::SpannedString, 22 23 type_::{ 23 - self, 24 + self, AccessorsMap, Deprecation, ModuleInterface, PatternConstructor, RecordAccessor, Type, 25 + TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, 26 + ValueConstructor, ValueConstructorVariant, Warning, 24 27 environment::*, 25 - error::{convert_unify_error, Error, FeatureKind, MissingAnnotation, Named, Problems}, 28 + error::{Error, FeatureKind, MissingAnnotation, Named, Problems, convert_unify_error}, 26 29 expression::{ExprTyper, FunctionDefinition, Implementations}, 27 30 fields::{FieldMap, FieldMapBuilder}, 28 31 hydrator::Hydrator, 29 32 prelude::*, 30 - AccessorsMap, Deprecation, ModuleInterface, PatternConstructor, RecordAccessor, Type, 31 - TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, 32 - ValueConstructor, ValueConstructorVariant, Warning, 33 33 }, 34 34 uid::UniqueIdGenerator, 35 35 warning::TypeWarningEmitter, 36 - GLEAM_CORE_PACKAGE_NAME, 37 36 }; 38 37 use camino::Utf8PathBuf; 39 38 use ecow::EcoString; ··· 847 846 .expect("Could not find preregistered type for function"); 848 847 let preregistered_type = preregistered_fn.type_.clone(); 849 848 850 - let args = 851 - if let Some((args_types, _return_type)) = preregistered_type.fn_types() { 852 - args.into_iter() 853 - .zip(&args_types) 854 - .map(|(argument, t)| { 855 - if let Some((location, label)) = &argument.label { 856 - self.check_name_case(*location, label, Named::Label); 857 - } 849 + let args = match preregistered_type.fn_types() { 850 + Some((args_types, _return_type)) => args 851 + .into_iter() 852 + .zip(&args_types) 853 + .map(|(argument, t)| { 854 + if let Some((location, label)) = &argument.label { 855 + self.check_name_case(*location, label, Named::Label); 856 + } 858 857 859 - RecordConstructorArg { 860 - label: argument.label, 861 - ast: argument.ast, 862 - location: argument.location, 863 - type_: t.clone(), 864 - doc: argument.doc, 865 - } 866 - }) 867 - .collect() 868 - } else { 858 + RecordConstructorArg { 859 + label: argument.label, 860 + ast: argument.ast, 861 + location: argument.location, 862 + type_: t.clone(), 863 + doc: argument.doc, 864 + } 865 + }) 866 + .collect(), 867 + _ => { 869 868 vec![] 870 - }; 869 + } 870 + }; 871 871 872 872 RecordConstructor { 873 873 location,
+1 -1
compiler-core/src/analyse/name.rs
··· 1 1 use std::sync::OnceLock; 2 2 3 - use ecow::{eco_format, EcoString}; 3 + use ecow::{EcoString, eco_format}; 4 4 use regex::Regex; 5 5 6 6 use crate::{
+20 -16
compiler-core/src/ast.rs
··· 1287 1287 .or_else(|| body.iter().find_map(|s| s.find_node(byte_index))), 1288 1288 // In all other cases we're happy with the default behaviour. 1289 1289 // 1290 - _ => { 1291 - if let Some(located) = self.value.find_node(byte_index) { 1292 - Some(located) 1293 - } else if self.location.contains(byte_index) && self.label.is_some() { 1294 - Some(Located::Label(self.location, self.value.type_())) 1295 - } else { 1296 - None 1290 + _ => match self.value.find_node(byte_index) { 1291 + Some(located) => Some(located), 1292 + _ => { 1293 + if self.location.contains(byte_index) && self.label.is_some() { 1294 + Some(Located::Label(self.location, self.value.type_())) 1295 + } else { 1296 + None 1297 + } 1297 1298 } 1298 - } 1299 + }, 1299 1300 } 1300 1301 } 1301 1302 ··· 1312 1313 1313 1314 pub fn is_capture_hole(&self) -> bool { 1314 1315 match &self.value { 1315 - TypedExpr::Var { ref name, .. } => name == CAPTURE_VARIABLE, 1316 + TypedExpr::Var { name, .. } => name == CAPTURE_VARIABLE, 1316 1317 _ => false, 1317 1318 } 1318 1319 } ··· 1320 1321 1321 1322 impl CallArg<TypedPattern> { 1322 1323 pub fn find_node(&self, byte_index: u32) -> Option<Located<'_>> { 1323 - if let Some(located) = self.value.find_node(byte_index) { 1324 - Some(located) 1325 - } else if self.location.contains(byte_index) && self.label.is_some() { 1326 - Some(Located::Label(self.location, self.value.type_())) 1327 - } else { 1328 - None 1324 + match self.value.find_node(byte_index) { 1325 + Some(located) => Some(located), 1326 + _ => { 1327 + if self.location.contains(byte_index) && self.label.is_some() { 1328 + Some(Located::Label(self.location, self.value.type_())) 1329 + } else { 1330 + None 1331 + } 1332 + } 1329 1333 } 1330 1334 } 1331 1335 } ··· 1333 1337 impl CallArg<UntypedExpr> { 1334 1338 pub fn is_capture_hole(&self) -> bool { 1335 1339 match &self.value { 1336 - UntypedExpr::Var { ref name, .. } => name == CAPTURE_VARIABLE, 1340 + UntypedExpr::Var { name, .. } => name == CAPTURE_VARIABLE, 1337 1341 _ => false, 1338 1342 } 1339 1343 }
+1 -1
compiler-core/src/ast/tests.rs
··· 8 8 use crate::line_numbers::LineNumbers; 9 9 use crate::type_::error::VariableOrigin; 10 10 use crate::type_::expression::FunctionDefinition; 11 - use crate::type_::{Deprecation, Problems, PRELUDE_MODULE_NAME}; 11 + use crate::type_::{Deprecation, PRELUDE_MODULE_NAME, Problems}; 12 12 use crate::warning::WarningEmitter; 13 13 use crate::{ 14 14 ast::{SrcSpan, TypedExpr},
+1 -1
compiler-core/src/ast/typed.rs
··· 3 3 use type_::{FieldMap, TypedCallArg}; 4 4 5 5 use super::*; 6 - use crate::type_::{bool, HasType, Type, ValueConstructorVariant}; 6 + use crate::type_::{HasType, Type, ValueConstructorVariant, bool}; 7 7 8 8 #[derive(Debug, Clone, PartialEq, Eq)] 9 9 pub enum TypedExpr {
+6 -5
compiler-core/src/ast/visit.rs
··· 41 41 use crate::{ 42 42 analyse::Inferred, 43 43 type_::{ 44 - error::VariableOrigin, ModuleValueConstructor, PatternConstructor, TypedCallArg, 45 - ValueConstructor, 44 + ModuleValueConstructor, PatternConstructor, TypedCallArg, ValueConstructor, 45 + error::VariableOrigin, 46 46 }, 47 47 }; 48 48 use std::sync::Arc; ··· 53 53 use crate::type_::Type; 54 54 55 55 use super::{ 56 - untyped::FunctionLiteralKind, AssignName, BinOp, BitArrayOption, CallArg, Definition, Pattern, 57 - PipelineAssignmentKind, SrcSpan, Statement, TodoKind, TypeAst, TypedArg, TypedAssignment, 58 - TypedClause, TypedClauseGuard, TypedConstant, TypedCustomType, TypedDefinition, TypedExpr, 56 + AssignName, BinOp, BitArrayOption, CallArg, Definition, Pattern, PipelineAssignmentKind, 57 + SrcSpan, Statement, TodoKind, TypeAst, TypedArg, TypedAssignment, TypedClause, 58 + TypedClauseGuard, TypedConstant, TypedCustomType, TypedDefinition, TypedExpr, 59 59 TypedExprBitArraySegment, TypedFunction, TypedModule, TypedModuleConstant, TypedPattern, 60 60 TypedPatternBitArraySegment, TypedPipelineAssignment, TypedStatement, TypedUse, 61 + untyped::FunctionLiteralKind, 61 62 }; 62 63 63 64 pub trait Visit<'ast> {
+8 -8
compiler-core/src/build/elixir_libraries.rs
··· 1 1 use crate::{ 2 + Error, 2 3 error::ShellCommandFailureReason, 3 4 io::{Command, CommandExecutor, FileSystemReader, FileSystemWriter, Stdio}, 4 - Error, 5 5 }; 6 6 use camino::Utf8PathBuf; 7 7 ··· 79 79 ELIXIR_LIBS.iter().map(|lib| format!(":{}", lib)).collect(); 80 80 // Use Elixir to find its core lib paths and write the pathfinder file 81 81 let args = vec![ 82 - "--eval".to_string(), 83 - format!( 84 - ":ok = File.write(~s({}), [{}] |> Stream.map(fn(lib) -> lib |> :code.lib_dir |> Path.expand end) |> Enum.join(~s(\\n)))", 85 - self.paths_cache_filename(), 86 - elixir_atoms.join(", "), 87 - ), 88 - ]; 82 + "--eval".to_string(), 83 + format!( 84 + ":ok = File.write(~s({}), [{}] |> Stream.map(fn(lib) -> lib |> :code.lib_dir |> Path.expand end) |> Enum.join(~s(\\n)))", 85 + self.paths_cache_filename(), 86 + elixir_atoms.join(", "), 87 + ), 88 + ]; 89 89 tracing::debug!("writing_elixir_paths_to_build"); 90 90 let status = self.io.exec(Command { 91 91 program: ELIXIR_EXECUTABLE.into(),
+3 -3
compiler-core/src/build/module_loader.rs
··· 9 9 use serde::{Deserialize, Serialize}; 10 10 11 11 use super::{ 12 - package_compiler::{module_name, CacheMetadata, CachedModule, Input, UncompiledModule}, 13 - package_loader::CodegenRequired, 14 12 Mode, Origin, SourceFingerprint, Target, 13 + package_compiler::{CacheMetadata, CachedModule, Input, UncompiledModule, module_name}, 14 + package_loader::CodegenRequired, 15 15 }; 16 16 use crate::{ 17 + Error, Result, 17 18 error::{FileIoAction, FileKind}, 18 19 io::{CommandExecutor, FileSystemReader, FileSystemWriter}, 19 20 warning::{TypeWarningEmitter, WarningEmitter}, 20 - Error, Result, 21 21 }; 22 22 23 23 #[derive(Debug)]
+1 -1
compiler-core/src/build/module_loader/tests.rs
··· 1 1 use super::*; 2 2 use crate::{ 3 3 build::SourceFingerprint, 4 - io::{memory::InMemoryFileSystem, FileSystemWriter}, 4 + io::{FileSystemWriter, memory::InMemoryFileSystem}, 5 5 line_numbers::LineNumbers, 6 6 }; 7 7 use std::time::Duration;
+2 -2
compiler-core/src/build/native_file_copier.rs
··· 4 4 use std::collections::{HashMap, HashSet}; 5 5 6 6 use camino::{Utf8Path, Utf8PathBuf}; 7 - use ecow::{eco_format, EcoString}; 7 + use ecow::{EcoString, eco_format}; 8 8 9 9 use crate::{ 10 - io::{DirWalker, FileSystemReader, FileSystemWriter}, 11 10 Error, Result, 11 + io::{DirWalker, FileSystemReader, FileSystemWriter}, 12 12 }; 13 13 14 14 #[derive(Debug, Clone, PartialEq, Eq)]
+1 -1
compiler-core/src/build/native_file_copier/tests.rs
··· 1 1 use super::NativeFileCopier; 2 2 use crate::{ 3 3 build::native_file_copier::CopiedNativeFiles, 4 - io::{memory::InMemoryFileSystem, FileSystemWriter}, 4 + io::{FileSystemWriter, memory::InMemoryFileSystem}, 5 5 }; 6 6 use std::{ 7 7 collections::HashMap,
+3 -3
compiler-core/src/build/package_compiler.rs
··· 2 2 use crate::line_numbers::{self, LineNumbers}; 3 3 use crate::type_::PRELUDE_MODULE_NAME; 4 4 use crate::{ 5 + Error, Result, Warning, 5 6 ast::{SrcSpan, TypedModule, UntypedModule}, 6 7 build::{ 8 + Mode, Module, Origin, Outcome, Package, SourceFingerprint, Target, 7 9 elixir_libraries::ElixirLibraries, 8 10 native_file_copier::NativeFileCopier, 9 11 package_loader::{CodegenRequired, PackageLoader, StaleTracker}, 10 - Mode, Module, Origin, Outcome, Package, SourceFingerprint, Target, 11 12 }, 12 13 codegen::{Erlang, ErlangApp, JavaScript, TypeScriptDeclarations}, 13 14 config::PackageConfig, ··· 18 19 paths, type_, 19 20 uid::UniqueIdGenerator, 20 21 warning::{TypeWarningEmitter, WarningEmitter}, 21 - Error, Result, Warning, 22 22 }; 23 23 use askama::Template; 24 24 use ecow::EcoString; ··· 540 540 path: path.clone(), 541 541 src: code.clone(), 542 542 errors, 543 - }) 543 + }); 544 544 } 545 545 }; 546 546 }
+4 -4
compiler-core/src/build/package_loader.rs
··· 15 15 use vec1::Vec1; 16 16 17 17 use crate::{ 18 + Error, Result, 18 19 ast::SrcSpan, 19 - build::{module_loader::ModuleLoader, package_compiler::module_name, Module, Origin}, 20 + build::{Module, Origin, module_loader::ModuleLoader, package_compiler::module_name}, 20 21 config::PackageConfig, 21 22 dep_tree, 22 23 error::{FileIoAction, FileKind, ImportCycleLocationDetails}, 23 24 io::{ 24 - gleam_cache_files, gleam_source_files, CommandExecutor, FileSystemReader, FileSystemWriter, 25 + CommandExecutor, FileSystemReader, FileSystemWriter, gleam_cache_files, gleam_source_files, 25 26 }, 26 27 metadata, type_, 27 28 uid::UniqueIdGenerator, 28 29 warning::WarningEmitter, 29 - Error, Result, 30 30 }; 31 31 32 32 use super::{ 33 + Mode, Target, 33 34 module_loader::read_source, 34 35 package_compiler::{ 35 36 CacheMetadata, CachedModule, CachedWarnings, Input, Loaded, UncompiledModule, 36 37 }, 37 - Mode, Target, 38 38 }; 39 39 40 40 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+3 -3
compiler-core/src/build/package_loader/tests.rs
··· 1 - use ecow::{eco_format, EcoString}; 1 + use ecow::{EcoString, eco_format}; 2 2 use hexpm::version::Version; 3 3 4 4 use super::*; 5 5 use crate::{ 6 + Warning, 6 7 build::SourceFingerprint, 7 - io::{memory::InMemoryFileSystem, FileSystemWriter}, 8 + io::{FileSystemWriter, memory::InMemoryFileSystem}, 8 9 line_numbers, 9 10 parse::extra::ModuleExtra, 10 11 warning::NullWarningEmitterIO, 11 - Warning, 12 12 }; 13 13 14 14 use std::time::Duration;
+5 -5
compiler-core/src/build/project_compiler.rs
··· 1 1 use crate::{ 2 + Error, Result, Warning, 2 3 analyse::TargetSupport, 3 4 build::{ 5 + Mode, Module, Origin, Package, Target, 4 6 package_compiler::{self, PackageCompiler}, 5 7 package_loader::StaleTracker, 6 8 project_compiler, 7 9 telemetry::Telemetry, 8 - Mode, Module, Origin, Package, Target, 9 10 }, 10 11 codegen::{self, ErlangApp}, 11 12 config::PackageConfig, ··· 19 20 uid::UniqueIdGenerator, 20 21 version::COMPILER_VERSION, 21 22 warning::{self, WarningEmitter, WarningEmitterIO}, 22 - Error, Result, Warning, 23 23 }; 24 24 use ecow::EcoString; 25 25 use hexpm::version::Version; ··· 36 36 }; 37 37 38 38 use super::{ 39 - elixir_libraries::ElixirLibraries, package_compiler::CachedWarnings, Codegen, Compile, 40 - ErlangAppCodegenConfiguration, Outcome, 39 + Codegen, Compile, ErlangAppCodegenConfiguration, Outcome, elixir_libraries::ElixirLibraries, 40 + package_compiler::CachedWarnings, 41 41 }; 42 42 43 43 use camino::{Utf8Path, Utf8PathBuf}; ··· 302 302 return Err(Error::UnsupportedBuildTool { 303 303 package: package.name.to_string(), 304 304 build_tools: package.build_tools.clone(), 305 - }) 305 + }); 306 306 } 307 307 }; 308 308
+2 -2
compiler-core/src/build/tests.rs
··· 1 - use crate::{manifest::ManifestPackage, Error}; 1 + use crate::{Error, manifest::ManifestPackage}; 2 2 3 - use super::project_compiler::{usable_build_tools, BuildTool}; 3 + use super::project_compiler::{BuildTool, usable_build_tools}; 4 4 5 5 #[test] 6 6 fn usable_build_tool_unknown() {
+2 -2
compiler-core/src/call_graph.rs
··· 5 5 mod into_dependency_order_tests; 6 6 7 7 use crate::{ 8 + Result, 8 9 ast::{ 9 10 AssignName, BitArrayOption, ClauseGuard, Constant, Pattern, SrcSpan, Statement, 10 11 UntypedClauseGuard, UntypedExpr, UntypedFunction, UntypedModuleConstant, UntypedPattern, 11 12 UntypedStatement, 12 13 }, 13 14 type_::Error, 14 - Result, 15 15 }; 16 16 use itertools::Itertools; 17 17 use petgraph::stable_graph::NodeIndex; 18 - use petgraph::{stable_graph::StableGraph, Directed}; 18 + use petgraph::{Directed, stable_graph::StableGraph}; 19 19 20 20 #[derive(Debug, Default)] 21 21 struct CallGraphBuilder<'a> {
+1 -1
compiler-core/src/call_graph/into_dependency_order_tests.rs
··· 1 1 use super::*; 2 2 use crate::{ 3 3 ast::{Arg, Function, ModuleConstant, Publicity}, 4 - type_::{expression::Implementations, Deprecation}, 4 + type_::{Deprecation, expression::Implementations}, 5 5 }; 6 6 use ecow::EcoString; 7 7
+1 -1
compiler-core/src/codegen.rs
··· 1 1 use crate::{ 2 + Result, 2 3 analyse::TargetSupport, 3 4 build::{ErlangAppCodegenConfiguration, Module}, 4 5 config::PackageConfig, ··· 6 7 io::FileSystemWriter, 7 8 javascript, 8 9 line_numbers::LineNumbers, 9 - Result, 10 10 }; 11 11 use ecow::EcoString; 12 12 use erlang::escape_atom_string;
+2 -2
compiler-core/src/config.rs
··· 790 790 // Note we don't use http-serde since we also want to validate the scheme and host is set. 791 791 mod uri_serde { 792 792 use http::uri::InvalidUri; 793 - use serde::{de::Error as _, Deserialize, Deserializer}; 793 + use serde::{Deserialize, Deserializer, de::Error as _}; 794 794 795 795 pub fn deserialize<'de, D>(deserializer: D) -> Result<http::Uri, D::Error> 796 796 where ··· 824 824 // This prefixes https as a default in the event no scheme was provided 825 825 mod uri_serde_default_https { 826 826 use http::uri::InvalidUri; 827 - use serde::{de::Error as _, Deserialize, Deserializer}; 827 + use serde::{Deserialize, Deserializer, de::Error as _}; 828 828 829 829 pub fn deserialize<'de, D>(deserializer: D) -> Result<http::Uri, D::Error> 830 830 where
+1 -1
compiler-core/src/dep_tree.rs
··· 1 1 use ecow::EcoString; 2 - use petgraph::{algo::Cycle, graph::NodeIndex, Direction}; 2 + use petgraph::{Direction, algo::Cycle, graph::NodeIndex}; 3 3 use std::collections::{HashMap, HashSet}; 4 4 5 5 #[cfg(test)]
+7 -7
compiler-core/src/dependency.rs
··· 4 4 5 5 use ecow::EcoString; 6 6 use hexpm::{ 7 - version::{Range, ResolutionError, Version}, 8 7 Dependency, Release, 8 + version::{Range, ResolutionError, Version}, 9 9 }; 10 10 use pubgrub::{ 11 - solver::{choose_package_with_fewest_versions, Dependencies}, 11 + solver::{Dependencies, choose_package_with_fewest_versions}, 12 12 type_aliases::Map, 13 13 }; 14 14 ··· 789 789 .unwrap_err(); 790 790 791 791 match err { 792 - Error::DependencyResolutionFailed(msg) => assert_eq!( 793 - msg, 794 - "An unrecoverable error happened while solving dependencies: gleam_stdlib is specified with the requirement `~> 0.1.0`, but it is locked to 0.2.0, which is incompatible." 795 - ), 796 - _ => panic!("wrong error: {err}"), 792 + Error::DependencyResolutionFailed(msg) => assert_eq!( 793 + msg, 794 + "An unrecoverable error happened while solving dependencies: gleam_stdlib is specified with the requirement `~> 0.1.0`, but it is locked to 0.2.0, which is incompatible." 795 + ), 796 + _ => panic!("wrong error: {err}"), 797 797 } 798 798 } 799 799
+3 -4
compiler-core/src/diagnostic.rs
··· 91 91 .extra_labels 92 92 .iter() 93 93 .map(|l| { 94 - let (location_src, location_path) = if let Some(info) = &l.src_info { 95 - (info.0.as_str(), info.1.as_str()) 96 - } else { 97 - (main_location_src, main_location_path) 94 + let (location_src, location_path) = match &l.src_info { 95 + Some(info) => (info.0.as_str(), info.1.as_str()), 96 + _ => (main_location_src, main_location_path), 98 97 }; 99 98 match file_map.get(location_path) { 100 99 None => {
+3 -4
compiler-core/src/docs/source_links.rs
··· 26 26 .expect("path is not in root") 27 27 .with_extension("gleam"); 28 28 29 - let path_in_repo = if let Some(repo_path) = project_config.repository.path() { 30 - to_url_path(&Utf8PathBuf::from(repo_path).join(path)) 31 - } else { 32 - to_url_path(&path) 29 + let path_in_repo = match project_config.repository.path() { 30 + Some(repo_path) => to_url_path(&Utf8PathBuf::from(repo_path).join(path)), 31 + _ => to_url_path(&path), 33 32 } 34 33 .unwrap_or_default(); 35 34
+5 -3
compiler-core/src/docs/tests.rs
··· 5 5 build::{Mode, NullTelemetry, PackageCompiler, StaleTracker, TargetCodegenConfiguration}, 6 6 config::{DocsPage, PackageConfig, Repository}, 7 7 docs::DocContext, 8 - io::{memory::InMemoryFileSystem, FileSystemWriter}, 8 + io::{FileSystemWriter, memory::InMemoryFileSystem}, 9 9 paths::ProjectPaths, 10 10 uid::UniqueIdGenerator, 11 11 version::COMPILER_VERSION, ··· 392 392 }; 393 393 394 394 let modules = vec![("app.gleam", "pub type Wibble = Int")]; 395 - assert!(compile(config, modules) 396 - .contains("https://github.com/wibble/wobble/blob/v0.1.0/src/app.gleam#L1-L1")); 395 + assert!( 396 + compile(config, modules) 397 + .contains("https://github.com/wibble/wobble/blob/v0.1.0/src/app.gleam#L1-L1") 398 + ); 397 399 } 398 400 399 401 #[test]
+24 -21
compiler-core/src/erlang.rs
··· 10 10 use crate::strings::convert_string_escape_chars; 11 11 use crate::type_::is_prelude_module; 12 12 use crate::{ 13 + Result, 13 14 ast::{CustomType, Function, Import, ModuleConstant, TypeAlias, *}, 14 15 docvec, 15 16 line_numbers::LineNumbers, ··· 18 19 ModuleValueConstructor, PatternConstructor, Type, TypeVar, TypedCallArg, ValueConstructor, 19 20 ValueConstructorVariant, 20 21 }, 21 - Result, 22 22 }; 23 23 use camino::Utf8Path; 24 - use ecow::{eco_format, EcoString}; 24 + use ecow::{EcoString, eco_format}; 25 25 use heck::ToSnakeCase; 26 26 use im::HashSet; 27 27 use itertools::Itertools; ··· 489 489 // So the doc directive will look like this: `-doc(false).` 490 490 env.needs_function_docs = true; 491 491 docvec![attributes, line(), hidden_function_doc()] 492 - } else if let Some((_, documentation)) = &function.documentation { 493 - env.needs_function_docs = true; 494 - let doc_lines = documentation 495 - .trim_end() 496 - .split('\n') 497 - .map(EcoString::from) 498 - .collect_vec(); 499 - docvec![attributes, line(), function_doc(&doc_lines)] 500 492 } else { 501 - attributes 493 + match &function.documentation { 494 + Some((_, documentation)) => { 495 + env.needs_function_docs = true; 496 + let doc_lines = documentation 497 + .trim_end() 498 + .split('\n') 499 + .map(EcoString::from) 500 + .collect_vec(); 501 + docvec![attributes, line(), function_doc(&doc_lines)] 502 + } 503 + _ => attributes, 504 + } 502 505 }; 503 506 504 507 Some(( ··· 1275 1278 .. 1276 1279 } => function_reference(Some(module), name, *arity), 1277 1280 1278 - ValueConstructorVariant::ModuleFn { 1279 - arity, ref module, .. 1280 - } if module == env.module => function_reference(None, name, *arity), 1281 + ValueConstructorVariant::ModuleFn { arity, module, .. } if module == env.module => { 1282 + function_reference(None, name, *arity) 1283 + } 1281 1284 1282 1285 ValueConstructorVariant::ModuleFn { 1283 1286 arity, ··· 1715 1718 ValueConstructorVariant::ModuleConstant { 1716 1719 literal: 1717 1720 Constant::Var { 1718 - constructor: Some(ref constructor), 1721 + constructor: Some(constructor), 1719 1722 .. 1720 1723 }, 1721 1724 .. ··· 1723 1726 .. 1724 1727 }, 1725 1728 .. 1726 - } if constructor.variant.is_module_fn() => { 1727 - if let ValueConstructorVariant::ModuleFn { 1729 + } if constructor.variant.is_module_fn() => match &constructor.variant { 1730 + ValueConstructorVariant::ModuleFn { 1728 1731 external_erlang: Some((module, name)), 1729 1732 .. 1730 1733 } 1731 - | ValueConstructorVariant::ModuleFn { module, name, .. } = &constructor.variant 1732 - { 1734 + | ValueConstructorVariant::ModuleFn { module, name, .. } => { 1733 1735 module_fn_with_args(module, name, args, env) 1734 - } else { 1736 + } 1737 + _ => { 1735 1738 unreachable!("The above clause guard ensures that this is a module fn") 1736 1739 } 1737 - } 1740 + }, 1738 1741 1739 1742 TypedExpr::ModuleSelect { 1740 1743 constructor:
+2 -2
compiler-core/src/erlang/tests.rs
··· 122 122 123 123 #[macro_export] 124 124 macro_rules! assert_erl { 125 - (($dep_package:expr, $dep_name:expr, $dep_src:expr), $src:expr $(,)?) => {{ 125 + (($dep_package:expr_2021, $dep_name:expr_2021, $dep_src:expr_2021), $src:expr_2021 $(,)?) => {{ 126 126 let compiled = $crate::erlang::tests::compile_test_project( 127 127 $src, 128 128 "/root/project/test/my/mod.gleam", ··· 135 135 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 136 136 }}; 137 137 138 - ($src:expr $(,)?) => {{ 138 + ($src:expr_2021 $(,)?) => {{ 139 139 let compiled = $crate::erlang::tests::compile_test_project( 140 140 $src, 141 141 "/root/project/test/my/mod.gleam",
+15 -10
compiler-core/src/error.rs
··· 7 7 UnsafeRecordUpdateReason, 8 8 }; 9 9 use crate::type_::printer::{Names, Printer}; 10 - use crate::type_::{error::PatternMatchKind, FieldAccessUsage}; 10 + use crate::type_::{FieldAccessUsage, error::PatternMatchKind}; 11 11 use crate::{ast::BinOp, parse::error::ParseErrorType, type_::Type}; 12 12 use crate::{bit_array, diagnostic::Level, javascript, type_::UnifyErrorSituation}; 13 13 use ecow::EcoString; ··· 290 290 #[error("The modules {unfinished:?} contain todo expressions and so cannot be published")] 291 291 CannotPublishTodo { unfinished: Vec<EcoString> }, 292 292 293 - #[error("The modules {unfinished:?} contain internal types in their public API so cannot be published")] 293 + #[error( 294 + "The modules {unfinished:?} contain internal types in their public API so cannot be published" 295 + )] 294 296 CannotPublishLeakedInternalType { unfinished: Vec<EcoString> }, 295 297 296 298 #[error("Publishing packages to reserve names is not permitted")] ··· 455 457 let mut conflicting_packages = HashSet::new(); 456 458 collect_conflicting_packages(&derivation_tree, &mut conflicting_packages); 457 459 458 - wrap_format!("Unable to find compatible versions for \ 460 + wrap_format!( 461 + "Unable to find compatible versions for \ 459 462 the version constraints in your gleam.toml. \ 460 463 The conflicting packages are: 461 464 462 465 {} 463 466 ", 464 - conflicting_packages.into_iter().map(|s| format!("- {s}")).join("\n")) 467 + conflicting_packages 468 + .into_iter() 469 + .map(|s| format!("- {s}")) 470 + .join("\n") 471 + ) 465 472 } 466 473 467 474 ResolutionError::ErrorRetrievingDependencies { ··· 476 483 package, 477 484 version, 478 485 dependent, 479 - } => format!( 480 - "{package}@{version} has an impossible dependency on {dependent}", 481 - ), 486 + } => format!("{package}@{version} has an impossible dependency on {dependent}",), 482 487 483 488 ResolutionError::SelfDependency { package, version } => { 484 489 format!("{package}@{version} somehow depends on itself.") ··· 492 497 format!("Dependency resolution was cancelled. {err}") 493 498 } 494 499 495 - ResolutionError::Failure(err) => format!( 496 - "An unrecoverable error happened while solving dependencies: {err}" 497 - ), 500 + ResolutionError::Failure(err) => { 501 + format!("An unrecoverable error happened while solving dependencies: {err}") 502 + } 498 503 }) 499 504 } 500 505
+2 -2
compiler-core/src/exhaustiveness.rs
··· 38 38 use crate::{ 39 39 ast::AssignName, 40 40 type_::{ 41 + Environment, Type, TypeValueConstructor, TypeValueConstructorField, TypeVar, 41 42 collapse_links, 42 43 error::{UnknownTypeConstructorError, UnreachableCaseClauseReason}, 43 - is_prelude_module, Environment, Type, TypeValueConstructor, TypeValueConstructorField, 44 - TypeVar, 44 + is_prelude_module, 45 45 }, 46 46 }; 47 47 use ecow::EcoString;
+1 -1
compiler-core/src/exhaustiveness/missing_patterns.rs
··· 1 - use super::{printer::Printer, Constructor, Decision, Match, Variable}; 1 + use super::{Constructor, Decision, Match, Variable, printer::Printer}; 2 2 use crate::type_::environment::Environment; 3 3 use ecow::EcoString; 4 4 use std::collections::{HashMap, HashSet};
+3 -3
compiler-core/src/exhaustiveness/printer.rs
··· 4 4 5 5 use crate::type_::printer::{NameContextInformation, Names}; 6 6 7 - use super::{missing_patterns::Term, Variable}; 7 + use super::{Variable, missing_patterns::Term}; 8 8 9 9 #[derive(Debug)] 10 10 pub struct Printer<'a> { ··· 167 167 use std::{collections::HashMap, sync::Arc}; 168 168 169 169 use crate::{ 170 - exhaustiveness::{missing_patterns::Term, Variable}, 171 - type_::{printer::Names, Type}, 170 + exhaustiveness::{Variable, missing_patterns::Term}, 171 + type_::{Type, printer::Names}, 172 172 }; 173 173 174 174 /// Create a variable with a dummy type, for ease of writing tests
+1 -1
compiler-core/src/fix.rs
··· 1 1 use crate::{ 2 + Error, Result, 2 3 format::{Formatter, Intermediate}, 3 4 warning::WarningEmitter, 4 - Error, Result, 5 5 }; 6 6 use camino::Utf8Path; 7 7 use ecow::EcoString;
+12 -6
compiler-core/src/format.rs
··· 2 2 mod tests; 3 3 4 4 use crate::{ 5 + Error, Result, 5 6 ast::{ 6 7 CustomType, Import, ModuleConstant, TypeAlias, TypeAstConstructor, TypeAstFn, TypeAstHole, 7 8 TypeAstTuple, TypeAstVar, *, ··· 9 10 build::Target, 10 11 docvec, 11 12 io::Utf8Writer, 12 - parse::extra::{Comment, ModuleExtra}, 13 13 parse::SpannedString, 14 + parse::extra::{Comment, ModuleExtra}, 14 15 pretty::{self, *}, 15 16 type_::{self, Type}, 16 17 warning::WarningEmitter, 17 - Error, Result, 18 18 }; 19 - use ecow::{eco_format, EcoString}; 19 + use ecow::{EcoString, eco_format}; 20 20 use itertools::Itertools; 21 21 use std::{cmp::Ordering, sync::Arc}; 22 22 use vec1::Vec1; ··· 136 136 fn pop_comments_with_position( 137 137 &mut self, 138 138 limit: u32, 139 - ) -> impl Iterator<Item = (u32, Option<&'comments str>)> { 139 + ) -> impl Iterator<Item = (u32, Option<&'comments str>)> + use<'comments> { 140 140 let (popped, rest, empty_lines) = 141 141 comments_before(self.comments, self.empty_lines, limit, true); 142 142 self.comments = rest; ··· 146 146 147 147 /// Pop comments that occur before a byte-index in the source, consuming 148 148 /// and retaining any empty lines contained within. 149 - fn pop_comments(&mut self, limit: u32) -> impl Iterator<Item = Option<&'comments str>> { 149 + fn pop_comments( 150 + &mut self, 151 + limit: u32, 152 + ) -> impl Iterator<Item = Option<&'comments str>> + use<'comments> { 150 153 self.pop_comments_with_position(limit) 151 154 .map(|(_position, comment)| comment) 152 155 } 153 156 154 157 /// Pop doc comments that occur before a byte-index in the source, consuming 155 158 /// and dropping any empty lines contained within. 156 - fn pop_doc_comments(&mut self, limit: u32) -> impl Iterator<Item = Option<&'comments str>> { 159 + fn pop_doc_comments( 160 + &mut self, 161 + limit: u32, 162 + ) -> impl Iterator<Item = Option<&'comments str>> + use<'comments> { 157 163 let (popped, rest, empty_lines) = 158 164 comments_before(self.doc_comments, self.empty_lines, limit, false); 159 165 self.doc_comments = rest;
+2 -2
compiler-core/src/format/tests.rs
··· 19 19 20 20 #[macro_export] 21 21 macro_rules! assert_format { 22 - ($src:expr $(,)?) => { 22 + ($src:expr_2021 $(,)?) => { 23 23 let mut writer = String::new(); 24 24 $crate::format::pretty(&mut writer, &$src.into(), camino::Utf8Path::new("<stdin>")) 25 25 .unwrap(); ··· 29 29 30 30 #[macro_export] 31 31 macro_rules! assert_format_rewrite { 32 - ($src:expr, $expected:expr $(,)?) => { 32 + ($src:expr_2021, $expected:expr_2021 $(,)?) => { 33 33 let mut writer = String::new(); 34 34 $crate::format::pretty(&mut writer, &$src.into(), camino::Utf8Path::new("<stdin>")) 35 35 .unwrap();
+1 -1
compiler-core/src/graph.rs
··· 1 1 //! General functions for working with graphs. 2 2 3 - use petgraph::{prelude::NodeIndex, stable_graph::StableGraph, Direction}; 3 + use petgraph::{Direction, prelude::NodeIndex, stable_graph::StableGraph}; 4 4 5 5 /// Sort a graph into a sequence from the leaves to the roots. 6 6 ///
+7 -7
compiler-core/src/hex.rs
··· 2 2 use debug_ignore::DebugIgnore; 3 3 use flate2::read::GzDecoder; 4 4 use futures::future; 5 - use hexpm::{version::Version, ApiError}; 5 + use hexpm::{ApiError, version::Version}; 6 6 use tar::Archive; 7 7 8 8 use crate::{ 9 + Error, Result, 9 10 io::{FileSystemReader, FileSystemWriter, HttpClient, TarUnpacker}, 10 11 manifest::{ManifestPackage, ManifestPackageSource}, 11 12 paths::{self, ProjectPaths}, 12 - Error, Result, 13 13 }; 14 14 15 15 pub const HEXPM_PUBLIC_KEY: &[u8] = b"-----BEGIN PUBLIC KEY----- ··· 158 158 &self, 159 159 package: &ManifestPackage, 160 160 ) -> Result<bool, Error> { 161 - let outer_checksum = if let ManifestPackageSource::Hex { outer_checksum } = &package.source 162 - { 163 - outer_checksum 164 - } else { 165 - panic!("Attempt to download non-hex package from hex") 161 + let outer_checksum = match &package.source { 162 + ManifestPackageSource::Hex { outer_checksum } => outer_checksum, 163 + _ => { 164 + panic!("Attempt to download non-hex package from hex") 165 + } 166 166 }; 167 167 168 168 let tarball_path = paths::global_package_cache_package_tarball(
+1 -1
compiler-core/src/io.rs
··· 402 402 #[async_trait] 403 403 pub trait HttpClient { 404 404 async fn send(&self, request: http::Request<Vec<u8>>) 405 - -> Result<http::Response<Vec<u8>>, Error>; 405 + -> Result<http::Response<Vec<u8>>, Error>; 406 406 } 407 407 408 408 pub trait TarUnpacker {
+2 -2
compiler-core/src/javascript.rs
··· 20 20 pretty::*, 21 21 }; 22 22 use camino::Utf8Path; 23 - use ecow::{eco_format, EcoString}; 23 + use ecow::{EcoString, eco_format}; 24 24 use expression::Context; 25 25 use itertools::Itertools; 26 26 ··· 530 530 // and the target support is not enforced. In this case we do not error, instead 531 531 // returning nothing which will cause no function to be generated. 532 532 Err(error) if error.is_unsupported() && !self.target_support.is_enforced() => { 533 - return None 533 + return None; 534 534 } 535 535 536 536 // Some other error case which will be returned to the user.
+64 -56
compiler-core/src/javascript/expression.rs
··· 143 143 TypedExpr::Int { value, .. } => Ok(int(value)), 144 144 TypedExpr::Float { value, .. } => Ok(float(value)), 145 145 146 - TypedExpr::List { elements, tail, .. } => self.not_in_tail_position(|gen| match tail { 147 - Some(tail) => { 148 - gen.tracker.prepend_used = true; 149 - let tail = gen.wrap_expression(tail)?; 150 - prepend(elements.iter().map(|e| gen.wrap_expression(e)), tail) 151 - } 152 - None => { 153 - gen.tracker.list_used = true; 154 - list(elements.iter().map(|e| gen.wrap_expression(e))) 155 - } 156 - }), 146 + TypedExpr::List { elements, tail, .. } => { 147 + self.not_in_tail_position(|r#gen| match tail { 148 + Some(tail) => { 149 + r#gen.tracker.prepend_used = true; 150 + let tail = r#gen.wrap_expression(tail)?; 151 + prepend(elements.iter().map(|e| r#gen.wrap_expression(e)), tail) 152 + } 153 + None => { 154 + r#gen.tracker.list_used = true; 155 + list(elements.iter().map(|e| r#gen.wrap_expression(e))) 156 + } 157 + }) 158 + } 157 159 158 160 TypedExpr::Tuple { elems, .. } => self.tuple(elems), 159 161 TypedExpr::TupleIndex { tuple, index, .. } => self.tuple_index(tuple, *index), ··· 223 225 } 224 226 225 227 fn negate_with<'a>(&mut self, with: &'static str, value: &'a TypedExpr) -> Output<'a> { 226 - self.not_in_tail_position(|gen| Ok(docvec![with, gen.wrap_expression(value)?])) 228 + self.not_in_tail_position(|r#gen| Ok(docvec![with, r#gen.wrap_expression(value)?])) 227 229 } 228 230 229 231 fn bit_array<'a>(&mut self, segments: &'a [TypedExprBitArraySegment]) -> Output<'a> { ··· 233 235 234 236 // Collect all the values used in segments. 235 237 let segments_array = array(segments.iter().map(|segment| { 236 - let value = self.not_in_tail_position(|gen| gen.wrap_expression(&segment.value))?; 238 + let value = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(&segment.value))?; 237 239 238 240 if segment.type_ == crate::type_::int() || segment.type_ == crate::type_::float() { 239 241 let details = self.sized_bit_array_segment_details(segment)?; ··· 373 375 374 376 ( 375 377 size_value, 376 - self.not_in_tail_position(|gen| gen.wrap_expression(size))?, 378 + self.not_in_tail_position(|r#gen| r#gen.wrap_expression(size))?, 377 379 ) 378 380 } 379 381 _ => { ··· 427 429 | TypedExpr::Case { .. } 428 430 | TypedExpr::Pipeline { .. } 429 431 | TypedExpr::RecordUpdate { .. } => self 430 - .immediately_invoked_function_expression(expression, |gen, expr| { 431 - gen.expression(expr) 432 + .immediately_invoked_function_expression(expression, |r#gen, expr| { 433 + r#gen.expression(expr) 432 434 }), 433 435 _ => self.expression(expression), 434 436 } ··· 515 517 .chain(assignments.iter().map(|(assignment, _kind)| assignment)); 516 518 517 519 for assignment in all_assignments { 518 - documents.push(self.not_in_tail_position(|gen| { 519 - gen.simple_variable_assignment(&assignment.name, &assignment.value) 520 + documents.push(self.not_in_tail_position(|r#gen| { 521 + r#gen.simple_variable_assignment(&assignment.name, &assignment.value) 520 522 })?); 521 523 documents.push(line()); 522 524 } ··· 548 550 Statement::Use(use_) => self.child_expression(&use_.call), 549 551 } 550 552 } else { 551 - self.immediately_invoked_function_expression(statements, |gen, statements| { 552 - gen.statements(statements) 553 + self.immediately_invoked_function_expression(statements, |r#gen, statements| { 554 + r#gen.statements(statements) 553 555 }) 554 556 } 555 557 } ··· 559 561 let mut documents = Vec::with_capacity(count * 3); 560 562 for (i, statement) in statements.iter().enumerate() { 561 563 if i + 1 < count { 562 - documents.push(self.not_in_tail_position(|gen| gen.statement(statement))?); 564 + documents.push(self.not_in_tail_position(|r#gen| r#gen.statement(statement))?); 563 565 if requires_semicolon(statement) { 564 566 documents.push(";".to_doc()); 565 567 } ··· 581 583 value: &'a TypedExpr, 582 584 ) -> Output<'a> { 583 585 // Subject must be rendered before the variable for variable numbering 584 - let subject = self.not_in_tail_position(|gen| gen.wrap_expression(value))?; 586 + let subject = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(value))?; 585 587 let js_name = self.next_local_var(name); 586 588 let assignment = docvec!["let ", js_name.clone(), " = ", subject, ";"]; 587 589 let assignment = if self.scope_position.is_tail() { ··· 611 613 // Otherwise we need to compile the patterns 612 614 let (subject, subject_assignment) = pattern::assign_subject(self, value); 613 615 // Value needs to be rendered before traversing pattern to have correctly incremented variables. 614 - let value = self.not_in_tail_position(|gen| gen.wrap_expression(value))?; 616 + let value = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(value))?; 615 617 let mut pattern_generator = pattern::Generator::new(self); 616 618 pattern_generator.traverse_pattern(&subject, pattern)?; 617 619 let compiled = pattern_generator.take_compiled(); ··· 649 651 pattern::assign_subjects(self, subject_values) 650 652 .into_iter() 651 653 .unzip(); 652 - let mut gen = pattern::Generator::new(self); 654 + let mut r#gen = pattern::Generator::new(self); 653 655 654 656 let mut doc = nil(); 655 657 ··· 670 672 671 673 // A clause can have many patterns `pattern, pattern ->...` 672 674 for multipatterns in multipatterns { 673 - let scope = gen.expression_generator.current_scope_vars.clone(); 674 - let mut compiled = gen.generate(&subjects, multipatterns, clause.guard.as_ref())?; 675 - let consequence = gen 675 + let scope = r#gen.expression_generator.current_scope_vars.clone(); 676 + let mut compiled = 677 + r#gen.generate(&subjects, multipatterns, clause.guard.as_ref())?; 678 + let consequence = r#gen 676 679 .expression_generator 677 680 .expression_flattening_blocks(&clause.then)?; 678 681 ··· 681 684 682 685 // Reset the scope now that this clause has finished, causing the 683 686 // variables to go out of scope. 684 - gen.expression_generator.current_scope_vars = scope; 687 + r#gen.expression_generator.current_scope_vars = scope; 685 688 686 689 // If the pattern assigns any variables we need to render assignments 687 690 let body = if compiled.has_assignments() { 688 - let assignments = gen 691 + let assignments = r#gen 689 692 .expression_generator 690 693 .pattern_take_assignments_doc(&mut compiled); 691 694 docvec![assignments, line(), consequence] ··· 719 722 " else if (" 720 723 }) 721 724 .append( 722 - gen.expression_generator 725 + r#gen 726 + .expression_generator 723 727 .pattern_take_checks_doc(&mut compiled, true), 724 728 ) 725 729 .append(") {") ··· 737 741 .zip(subject_values) 738 742 .flat_map(|(assignment_name, value)| assignment_name.map(|name| (name, value))) 739 743 .map(|(name, value)| { 740 - let value = self.not_in_tail_position(|gen| gen.wrap_expression(value))?; 744 + let value = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(value))?; 741 745 Ok(docvec!["let ", name, " = ", value, ";", line()]) 742 746 }) 743 747 .try_collect()?; ··· 752 756 message: Option<&'a TypedExpr>, 753 757 ) -> Output<'a> { 754 758 let message = match message { 755 - Some(m) => self.not_in_tail_position(|gen| gen.expression(m))?, 759 + Some(m) => self.not_in_tail_position(|r#gen| r#gen.expression(m))?, 756 760 None => string("Pattern match failed, no pattern matched the value."), 757 761 }; 758 762 ··· 760 764 } 761 765 762 766 fn tuple<'a>(&mut self, elements: &'a [TypedExpr]) -> Output<'a> { 763 - self.not_in_tail_position(|gen| { 764 - array(elements.iter().map(|element| gen.wrap_expression(element))) 767 + self.not_in_tail_position(|r#gen| { 768 + array( 769 + elements 770 + .iter() 771 + .map(|element| r#gen.wrap_expression(element)), 772 + ) 765 773 }) 766 774 } 767 775 768 776 fn call<'a>(&mut self, fun: &'a TypedExpr, arguments: &'a [TypedCallArg]) -> Output<'a> { 769 777 let arguments = arguments 770 778 .iter() 771 - .map(|element| self.not_in_tail_position(|gen| gen.wrap_expression(&element.value))) 779 + .map(|element| self.not_in_tail_position(|r#gen| r#gen.wrap_expression(&element.value))) 772 780 .try_collect()?; 773 781 774 782 self.call_with_doc_args(fun, arguments) ··· 845 853 } 846 854 847 855 _ => { 848 - let fun = self.not_in_tail_position(|gen| { 856 + let fun = self.not_in_tail_position(|r#gen| { 849 857 let is_fn_literal = matches!(fun, TypedExpr::Fn { .. }); 850 - let fun = gen.wrap_expression(fun)?; 858 + let fun = r#gen.wrap_expression(fun)?; 851 859 if is_fn_literal { 852 860 Ok(docvec!["(", fun, ")"]) 853 861 } else { ··· 902 910 } 903 911 904 912 fn record_access<'a>(&mut self, record: &'a TypedExpr, label: &'a str) -> Output<'a> { 905 - self.not_in_tail_position(|gen| { 906 - let record = gen.wrap_expression(record)?; 913 + self.not_in_tail_position(|r#gen| { 914 + let record = r#gen.wrap_expression(record)?; 907 915 Ok(docvec![record, ".", maybe_escape_property_doc(label)]) 908 916 }) 909 917 } ··· 915 923 args: &'a [TypedCallArg], 916 924 ) -> Output<'a> { 917 925 Ok(docvec![ 918 - self.not_in_tail_position(|gen| gen.assignment(record))?, 926 + self.not_in_tail_position(|r#gen| r#gen.assignment(record))?, 919 927 line(), 920 928 self.call(constructor, args)?, 921 929 ]) 922 930 } 923 931 924 932 fn tuple_index<'a>(&mut self, tuple: &'a TypedExpr, index: u64) -> Output<'a> { 925 - self.not_in_tail_position(|gen| { 926 - let tuple = gen.wrap_expression(tuple)?; 933 + self.not_in_tail_position(|r#gen| { 934 + let tuple = r#gen.wrap_expression(tuple)?; 927 935 Ok(docvec![tuple, eco_format!("[{index}]")]) 928 936 }) 929 937 } ··· 955 963 } 956 964 957 965 fn div_int<'a>(&mut self, left: &'a TypedExpr, right: &'a TypedExpr) -> Output<'a> { 958 - let left = self.not_in_tail_position(|gen| gen.child_expression(left))?; 959 - let right = self.not_in_tail_position(|gen| gen.child_expression(right))?; 966 + let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 967 + let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 960 968 self.tracker.int_division_used = true; 961 969 Ok(docvec!["divideInt", wrap_args([left, right])]) 962 970 } 963 971 964 972 fn remainder_int<'a>(&mut self, left: &'a TypedExpr, right: &'a TypedExpr) -> Output<'a> { 965 - let left = self.not_in_tail_position(|gen| gen.child_expression(left))?; 966 - let right = self.not_in_tail_position(|gen| gen.child_expression(right))?; 973 + let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 974 + let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 967 975 self.tracker.int_remainder_used = true; 968 976 Ok(docvec!["remainderInt", wrap_args([left, right])]) 969 977 } 970 978 971 979 fn div_float<'a>(&mut self, left: &'a TypedExpr, right: &'a TypedExpr) -> Output<'a> { 972 - let left = self.not_in_tail_position(|gen| gen.child_expression(left))?; 973 - let right = self.not_in_tail_position(|gen| gen.child_expression(right))?; 980 + let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 981 + let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 974 982 self.tracker.float_division_used = true; 975 983 Ok(docvec!["divideFloat", wrap_args([left, right])]) 976 984 } ··· 983 991 ) -> Output<'a> { 984 992 // If it is a simple scalar type then we can use JS' reference identity 985 993 if is_js_scalar(left.type_()) { 986 - let left_doc = self.not_in_tail_position(|gen| gen.child_expression(left))?; 987 - let right_doc = self.not_in_tail_position(|gen| gen.child_expression(right))?; 994 + let left_doc = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 995 + let right_doc = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 988 996 let operator = if should_be_equal { " === " } else { " !== " }; 989 997 return Ok(docvec![left_doc, operator, right_doc]); 990 998 } 991 999 992 1000 // Other types must be compared using structural equality 993 - let left = self.not_in_tail_position(|gen| gen.wrap_expression(left))?; 994 - let right = self.not_in_tail_position(|gen| gen.wrap_expression(right))?; 1001 + let left = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(left))?; 1002 + let right = self.not_in_tail_position(|r#gen| r#gen.wrap_expression(right))?; 995 1003 Ok(self.prelude_equal_call(should_be_equal, left, right)) 996 1004 } 997 1005 ··· 1019 1027 right: &'a TypedExpr, 1020 1028 op: &'a str, 1021 1029 ) -> Output<'a> { 1022 - let left = self.not_in_tail_position(|gen| gen.child_expression(left))?; 1023 - let right = self.not_in_tail_position(|gen| gen.child_expression(right))?; 1030 + let left = self.not_in_tail_position(|r#gen| r#gen.child_expression(left))?; 1031 + let right = self.not_in_tail_position(|r#gen| r#gen.child_expression(right))?; 1024 1032 Ok(docvec![left, " ", op, " ", right]) 1025 1033 } 1026 1034 1027 1035 fn todo<'a>(&mut self, message: Option<&'a TypedExpr>, location: &'a SrcSpan) -> Output<'a> { 1028 1036 let message = match message { 1029 - Some(m) => self.not_in_tail_position(|gen| gen.expression(m))?, 1037 + Some(m) => self.not_in_tail_position(|r#gen| r#gen.expression(m))?, 1030 1038 None => string("`todo` expression evaluated. This code has not yet been implemented."), 1031 1039 }; 1032 1040 let doc = self.throw_error("todo", &message, *location, vec![]); ··· 1036 1044 1037 1045 fn panic<'a>(&mut self, location: &'a SrcSpan, message: Option<&'a TypedExpr>) -> Output<'a> { 1038 1046 let message = match message { 1039 - Some(m) => self.not_in_tail_position(|gen| gen.expression(m))?, 1047 + Some(m) => self.not_in_tail_position(|r#gen| r#gen.expression(m))?, 1040 1048 None => string("`panic` expression evaluated."), 1041 1049 }; 1042 1050 let doc = self.throw_error("panic", &message, *location, vec![]);
+2 -2
compiler-core/src/javascript/import.rs
··· 5 5 6 6 use crate::{ 7 7 docvec, 8 - javascript::{JavaScriptCodegenTarget, INDENT}, 9 - pretty::{break_, concat, join, line, Document, Documentable}, 8 + javascript::{INDENT, JavaScriptCodegenTarget}, 9 + pretty::{Document, Documentable, break_, concat, join, line}, 10 10 }; 11 11 12 12 /// A collection of JavaScript import statements from Gleam imports and from
+1 -1
compiler-core/src/javascript/pattern.rs
··· 418 418 &mut self.assignments, 419 419 self.expression_generator.tracker, 420 420 constant, 421 - ) 421 + ); 422 422 } 423 423 }) 424 424 }
+8 -8
compiler-core/src/javascript/tests.rs
··· 51 51 52 52 #[macro_export] 53 53 macro_rules! assert_js { 54 - (($dep_package:expr, $dep_name:expr, $dep_src:expr), $src:expr $(,)?) => {{ 54 + (($dep_package:expr_2021, $dep_name:expr_2021, $dep_src:expr_2021), $src:expr_2021 $(,)?) => {{ 55 55 let compiled = 56 56 $crate::javascript::tests::compile_js($src, vec![($dep_package, $dep_name, $dep_src)]) 57 57 .expect("compilation failed"); ··· 62 62 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 63 63 }}; 64 64 65 - (($dep_package:expr, $dep_name:expr, $dep_src:expr), $src:expr, $js:expr $(,)?) => {{ 65 + (($dep_package:expr_2021, $dep_name:expr_2021, $dep_src:expr_2021), $src:expr_2021, $js:expr_2021 $(,)?) => {{ 66 66 let output = 67 67 $crate::javascript::tests::compile_js($src, Some(($dep_package, $dep_name, $dep_src))) 68 68 .expect("compilation failed"); 69 69 assert_eq!(($src, output), ($src, $js.to_string())); 70 70 }}; 71 71 72 - ($src:expr $(,)?) => {{ 72 + ($src:expr_2021 $(,)?) => {{ 73 73 let compiled = 74 74 $crate::javascript::tests::compile_js($src, vec![]).expect("compilation failed"); 75 75 let output = format!( ··· 79 79 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 80 80 }}; 81 81 82 - ($src:expr, $js:expr $(,)?) => {{ 82 + ($src:expr_2021, $js:expr_2021 $(,)?) => {{ 83 83 let output = 84 84 $crate::javascript::tests::compile_js($src, vec![]).expect("compilation failed"); 85 85 assert_eq!(($src, output), ($src, $js.to_string())); ··· 88 88 89 89 #[macro_export] 90 90 macro_rules! assert_js_error { 91 - ($src:expr $(,)?) => {{ 91 + ($src:expr_2021 $(,)?) => {{ 92 92 let error = $crate::javascript::tests::expect_js_error($src, vec![]); 93 93 let output = format!("----- SOURCE CODE\n{}\n\n----- ERROR\n{}", $src, error); 94 94 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 97 97 98 98 #[macro_export] 99 99 macro_rules! assert_ts_def { 100 - (($dep_1_package:expr, $dep_1_name:expr, $dep_1_src:expr), ($dep_2_package:expr, $dep_2_name:expr, $dep_2_src:expr), $src:expr $(,)?) => {{ 100 + (($dep_1_package:expr_2021, $dep_1_name:expr_2021, $dep_1_src:expr_2021), ($dep_2_package:expr_2021, $dep_2_name:expr_2021, $dep_2_src:expr_2021), $src:expr_2021 $(,)?) => {{ 101 101 let compiled = $crate::javascript::tests::compile_ts( 102 102 $src, 103 103 vec![ ··· 113 113 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 114 114 }}; 115 115 116 - (($dep_package:expr, $dep_name:expr, $dep_src:expr), $src:expr $(,)?) => {{ 116 + (($dep_package:expr_2021, $dep_name:expr_2021, $dep_src:expr_2021), $src:expr_2021 $(,)?) => {{ 117 117 let compiled = 118 118 $crate::javascript::tests::compile_ts($src, vec![($dep_package, $dep_name, $dep_src)]) 119 119 .expect("compilation failed"); ··· 124 124 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 125 125 }}; 126 126 127 - ($src:expr $(,)?) => {{ 127 + ($src:expr_2021 $(,)?) => {{ 128 128 let compiled = 129 129 $crate::javascript::tests::compile_ts($src, vec![]).expect("compilation failed"); 130 130 let output = format!(
+4 -4
compiler-core/src/javascript/typescript.rs
··· 12 12 //! <https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html> 13 13 14 14 use crate::ast::{AssignName, Publicity}; 15 - use crate::type_::{is_prelude_module, PRELUDE_MODULE_NAME}; 15 + use crate::type_::{PRELUDE_MODULE_NAME, is_prelude_module}; 16 16 use crate::{ 17 17 ast::{ 18 18 CustomType, Definition, Function, Import, ModuleConstant, TypeAlias, TypedArg, ··· 20 20 }, 21 21 docvec, 22 22 javascript::JavaScriptCodegenTarget, 23 - pretty::{break_, Document, Documentable}, 23 + pretty::{Document, Documentable, break_}, 24 24 type_::{Type, TypeVar}, 25 25 }; 26 - use ecow::{eco_format, EcoString}; 26 + use ecow::{EcoString, eco_format}; 27 27 use itertools::Itertools; 28 28 use std::{collections::HashMap, ops::Deref, sync::Arc}; 29 29 30 - use super::{import::Imports, join, line, lines, wrap_args, Output, INDENT}; 30 + use super::{INDENT, Output, import::Imports, join, line, lines, wrap_args}; 31 31 32 32 /// When rendering a type variable to an TypeScript type spec we need all type 33 33 /// variables with the same id to end up with the same name in the generated
+2 -2
compiler-core/src/language_server.rs
··· 18 18 pub use server::LanguageServer; 19 19 20 20 use crate::{ 21 - ast::SrcSpan, build::Target, line_numbers::LineNumbers, manifest::Manifest, 22 - paths::ProjectPaths, Result, 21 + Result, ast::SrcSpan, build::Target, line_numbers::LineNumbers, manifest::Manifest, 22 + paths::ProjectPaths, 23 23 }; 24 24 use camino::Utf8PathBuf; 25 25 use lsp_types::{Position, Range, TextEdit, Url};
+152 -133
compiler-core/src/language_server/code_action.rs
··· 1 1 use std::{collections::HashSet, iter, sync::Arc}; 2 2 3 3 use crate::{ 4 + Error, STDLIB_PACKAGE_NAME, 4 5 ast::{ 5 - self, 6 - visit::{visit_typed_call_arg, visit_typed_pattern_call_arg, Visit as _}, 7 - AssignName, AssignmentKind, CallArg, FunctionLiteralKind, ImplicitCallArgOrigin, Pattern, 8 - PipelineAssignmentKind, SrcSpan, TodoKind, TypedArg, TypedAssignment, TypedExpr, 6 + self, AssignName, AssignmentKind, CallArg, FunctionLiteralKind, ImplicitCallArgOrigin, 7 + Pattern, PipelineAssignmentKind, SrcSpan, TodoKind, TypedArg, TypedAssignment, TypedExpr, 9 8 TypedModuleConstant, TypedPattern, TypedPipelineAssignment, TypedRecordConstructor, 10 9 TypedStatement, TypedUse, 10 + visit::{Visit as _, visit_typed_call_arg, visit_typed_pattern_call_arg}, 11 11 }, 12 12 build::{Located, Module}, 13 13 io::{BeamCompiler, CommandExecutor, FileSystemReader, FileSystemWriter}, 14 14 line_numbers::LineNumbers, 15 15 parse::{extra::ModuleExtra, lexer::str_to_keyword}, 16 16 type_::{ 17 - self, 17 + self, FieldMap, ModuleValueConstructor, Type, TypeVar, TypedCallArg, ValueConstructor, 18 18 error::{ModuleSuggestion, VariableOrigin}, 19 19 printer::{Names, Printer}, 20 - FieldMap, ModuleValueConstructor, Type, TypeVar, TypedCallArg, ValueConstructor, 21 20 }, 22 - Error, STDLIB_PACKAGE_NAME, 23 21 }; 24 - use ecow::{eco_format, EcoString}; 22 + use ecow::{EcoString, eco_format}; 25 23 use heck::ToSnakeCase; 26 24 use im::HashMap; 27 25 use itertools::Itertools; 28 26 use lsp_types::{CodeAction, CodeActionKind, CodeActionParams, Position, Range, TextEdit, Url}; 29 - use vec1::{vec1, Vec1}; 27 + use vec1::{Vec1, vec1}; 30 28 31 29 use super::{ 30 + TextEdits, 32 31 compiler::LspProjectCompiler, 33 32 edits::{add_newlines_after_import, get_import_edit, position_of_first_definition_if_import}, 34 33 engine::{overlaps, within}, 35 34 rename::find_variable_references, 36 - src_span_to_lsp_range, TextEdits, 35 + src_span_to_lsp_range, 37 36 }; 38 37 39 38 #[derive(Debug)] ··· 867 866 )) 868 867 }; 869 868 870 - let title = if let Some(import) = &suggestion.import { 871 - &format!("Import `{import}`") 872 - } else { 873 - &format!("Did you mean `{}`", suggestion.name) 869 + let title = match &suggestion.import { 870 + Some(import) => &format!("Import `{import}`"), 871 + _ => &format!("Did you mean `{}`", suggestion.name), 874 872 }; 875 873 876 874 CodeActionBuilder::new(title) ··· 3190 3188 fn variable_name(&self) -> EcoString { 3191 3189 match self { 3192 3190 RecordLabel::Labeled(label) => (*label).into(), 3193 - RecordLabel::Unlabeled(mut index) => { 3191 + &RecordLabel::Unlabeled(mut index) => { 3194 3192 let mut characters = Vec::new(); 3195 3193 let alphabet_length = 26; 3196 3194 let alphabet_offset = b'a'; ··· 3231 3229 eco_format!("{module_name}.int") 3232 3230 } else if type_.is_string() { 3233 3231 eco_format!("{module_name}.string") 3234 - } else if let Some(types) = type_.tuple_types() { 3235 - let fields = types 3236 - .iter() 3237 - .enumerate() 3238 - .map(|(index, type_)| RecordField { 3239 - type_, 3240 - label: RecordLabel::Unlabeled(index), 3241 - }) 3242 - .collect_vec(); 3243 - let decoders = fields 3244 - .iter() 3245 - .map(|field| self.decode_field(field, indent + 2)) 3246 - .join("\n"); 3247 - let mut field_names = fields.iter().map(|field| field.label.variable_name()); 3232 + } else { 3233 + match type_.tuple_types() { 3234 + Some(types) => { 3235 + let fields = types 3236 + .iter() 3237 + .enumerate() 3238 + .map(|(index, type_)| RecordField { 3239 + type_, 3240 + label: RecordLabel::Unlabeled(index), 3241 + }) 3242 + .collect_vec(); 3243 + let decoders = fields 3244 + .iter() 3245 + .map(|field| self.decode_field(field, indent + 2)) 3246 + .join("\n"); 3247 + let mut field_names = fields.iter().map(|field| field.label.variable_name()); 3248 3248 3249 - eco_format!( 3250 - "{{ 3249 + eco_format!( 3250 + "{{ 3251 3251 {decoders} 3252 3252 3253 3253 {indent} {module_name}.success(#({fields})) 3254 3254 {indent}}}", 3255 - fields = field_names.join(", "), 3256 - indent = " ".repeat(indent) 3257 - ) 3258 - } else { 3259 - let type_information = type_.named_type_information(); 3260 - let type_information = type_information.as_ref().map(|(module, name, arguments)| { 3261 - (module.as_str(), name.as_str(), arguments.as_slice()) 3262 - }); 3263 - 3264 - match type_information { 3265 - Some(("gleam/dynamic", "Dynamic", _)) => eco_format!("{module_name}.dynamic"), 3266 - Some(("gleam", "List", [element])) => { 3267 - eco_format!("{module_name}.list({})", self.decoder_for(element, indent)) 3268 - } 3269 - Some(("gleam/option", "Option", [some])) => { 3270 - eco_format!("{module_name}.optional({})", self.decoder_for(some, indent)) 3271 - } 3272 - Some(("gleam/dict", "Dict", [key, value])) => { 3273 - eco_format!( 3274 - "{module_name}.dict({}, {})", 3275 - self.decoder_for(key, indent), 3276 - self.decoder_for(value, indent) 3255 + fields = field_names.join(", "), 3256 + indent = " ".repeat(indent) 3277 3257 ) 3278 3258 } 3279 - Some((module, name, _)) if module == self.type_module && name == self.type_name => { 3280 - eco_format!("{}_decoder()", name.to_snake_case()) 3259 + _ => { 3260 + let type_information = type_.named_type_information(); 3261 + let type_information = 3262 + type_information.as_ref().map(|(module, name, arguments)| { 3263 + (module.as_str(), name.as_str(), arguments.as_slice()) 3264 + }); 3265 + 3266 + match type_information { 3267 + Some(("gleam/dynamic", "Dynamic", _)) => { 3268 + eco_format!("{module_name}.dynamic") 3269 + } 3270 + Some(("gleam", "List", [element])) => { 3271 + eco_format!("{module_name}.list({})", self.decoder_for(element, indent)) 3272 + } 3273 + Some(("gleam/option", "Option", [some])) => { 3274 + eco_format!( 3275 + "{module_name}.optional({})", 3276 + self.decoder_for(some, indent) 3277 + ) 3278 + } 3279 + Some(("gleam/dict", "Dict", [key, value])) => { 3280 + eco_format!( 3281 + "{module_name}.dict({}, {})", 3282 + self.decoder_for(key, indent), 3283 + self.decoder_for(value, indent) 3284 + ) 3285 + } 3286 + Some((module, name, _)) 3287 + if module == self.type_module && name == self.type_name => 3288 + { 3289 + eco_format!("{}_decoder()", name.to_snake_case()) 3290 + } 3291 + _ => eco_format!( 3292 + r#"todo as "Decoder for {}""#, 3293 + self.printer.print_type(type_) 3294 + ), 3295 + } 3281 3296 } 3282 - _ => eco_format!( 3283 - r#"todo as "Decoder for {}""#, 3284 - self.printer.print_type(type_) 3285 - ), 3286 3297 } 3287 3298 } 3288 3299 } ··· 3508 3519 maybe_capture(eco_format!("{module_name}.int")) 3509 3520 } else if type_.is_string() { 3510 3521 maybe_capture(eco_format!("{module_name}.string")) 3511 - } else if let Some(types) = type_.tuple_types() { 3512 - let (tuple, new_indent) = if is_capture { 3513 - ("value", indent + 4) 3514 - } else { 3515 - (encoded_value, indent + 2) 3516 - }; 3522 + } else { 3523 + match type_.tuple_types() { 3524 + Some(types) => { 3525 + let (tuple, new_indent) = if is_capture { 3526 + ("value", indent + 4) 3527 + } else { 3528 + (encoded_value, indent + 2) 3529 + }; 3517 3530 3518 - let encoders = types 3519 - .iter() 3520 - .enumerate() 3521 - .map(|(index, type_)| { 3522 - self.encoder_for(&format!("{tuple}.{index}"), type_, new_indent) 3523 - }) 3524 - .collect_vec(); 3531 + let encoders = types 3532 + .iter() 3533 + .enumerate() 3534 + .map(|(index, type_)| { 3535 + self.encoder_for(&format!("{tuple}.{index}"), type_, new_indent) 3536 + }) 3537 + .collect_vec(); 3525 3538 3526 - if is_capture { 3527 - eco_format!( 3528 - "fn(value) {{ 3539 + if is_capture { 3540 + eco_format!( 3541 + "fn(value) {{ 3529 3542 {indent} {module_name}.preprocessed_array([ 3530 3543 {indent} {encoders}, 3531 3544 {indent} ]) 3532 3545 {indent}}}", 3533 - indent = " ".repeat(indent), 3534 - encoders = encoders.join(&format!(",\n{}", " ".repeat(new_indent))), 3535 - ) 3536 - } else { 3537 - eco_format!( 3538 - "{module_name}.preprocessed_array([ 3546 + indent = " ".repeat(indent), 3547 + encoders = encoders.join(&format!(",\n{}", " ".repeat(new_indent))), 3548 + ) 3549 + } else { 3550 + eco_format!( 3551 + "{module_name}.preprocessed_array([ 3539 3552 {indent} {encoders}, 3540 3553 {indent}])", 3541 - indent = " ".repeat(indent), 3542 - encoders = encoders.join(&format!(",\n{}", " ".repeat(new_indent))), 3543 - ) 3544 - } 3545 - } else { 3546 - let type_information = type_.named_type_information(); 3547 - let type_information: Option<(&str, &str, &[Arc<Type>])> = 3548 - type_information.as_ref().map(|(module, name, arguments)| { 3549 - (module.as_str(), name.as_str(), arguments.as_slice()) 3550 - }); 3554 + indent = " ".repeat(indent), 3555 + encoders = encoders.join(&format!(",\n{}", " ".repeat(new_indent))), 3556 + ) 3557 + } 3558 + } 3559 + _ => { 3560 + let type_information = type_.named_type_information(); 3561 + let type_information: Option<(&str, &str, &[Arc<Type>])> = 3562 + type_information.as_ref().map(|(module, name, arguments)| { 3563 + (module.as_str(), name.as_str(), arguments.as_slice()) 3564 + }); 3551 3565 3552 - match type_information { 3553 - Some(("gleam", "List", [element])) => { 3554 - eco_format!( 3555 - "{module_name}.array({encoded_value}, {map_function})", 3556 - map_function = self.encoder_for("_", element, indent) 3557 - ) 3558 - } 3559 - Some(("gleam/option", "Option", [some])) => { 3560 - eco_format!( 3561 - "case {encoded_value} {{ 3566 + match type_information { 3567 + Some(("gleam", "List", [element])) => { 3568 + eco_format!( 3569 + "{module_name}.array({encoded_value}, {map_function})", 3570 + map_function = self.encoder_for("_", element, indent) 3571 + ) 3572 + } 3573 + Some(("gleam/option", "Option", [some])) => { 3574 + eco_format!( 3575 + "case {encoded_value} {{ 3562 3576 {indent} {none} -> {module_name}.null() 3563 3577 {indent} {some}(value) -> {encoder} 3564 3578 {indent}}}", 3565 - indent = " ".repeat(indent), 3566 - none = self 3567 - .printer 3568 - .print_constructor(&"gleam/option".into(), &"None".into()), 3569 - some = self 3570 - .printer 3571 - .print_constructor(&"gleam/option".into(), &"Some".into()), 3572 - encoder = self.encoder_for("value", some, indent + 2) 3573 - ) 3574 - } 3575 - Some(("gleam/dict", "Dict", [key, value])) => { 3576 - let stringify_function = match key.named_type_information().as_ref().map( 3577 - |(module, name, arguments)| { 3578 - (module.as_str(), name.as_str(), arguments.as_slice()) 3579 - }, 3580 - ) { 3581 - Some(("gleam", "String", [])) => "fn(string) { string }", 3582 - _ => &format!( 3583 - r#"todo as "Function to stringify {}""#, 3584 - self.printer.print_type(key) 3579 + indent = " ".repeat(indent), 3580 + none = self 3581 + .printer 3582 + .print_constructor(&"gleam/option".into(), &"None".into()), 3583 + some = self 3584 + .printer 3585 + .print_constructor(&"gleam/option".into(), &"Some".into()), 3586 + encoder = self.encoder_for("value", some, indent + 2) 3587 + ) 3588 + } 3589 + Some(("gleam/dict", "Dict", [key, value])) => { 3590 + let stringify_function = match key 3591 + .named_type_information() 3592 + .as_ref() 3593 + .map(|(module, name, arguments)| { 3594 + (module.as_str(), name.as_str(), arguments.as_slice()) 3595 + }) { 3596 + Some(("gleam", "String", [])) => "fn(string) { string }", 3597 + _ => &format!( 3598 + r#"todo as "Function to stringify {}""#, 3599 + self.printer.print_type(key) 3600 + ), 3601 + }; 3602 + eco_format!( 3603 + "{module_name}.dict({encoded_value}, {stringify_function}, {})", 3604 + self.encoder_for("_", value, indent) 3605 + ) 3606 + } 3607 + Some((module, name, _)) 3608 + if module == self.type_module && name == self.type_name => 3609 + { 3610 + maybe_capture(eco_format!("encode_{}", name.to_snake_case())) 3611 + } 3612 + _ => eco_format!( 3613 + r#"todo as "Encoder for {}""#, 3614 + self.printer.print_type(type_) 3585 3615 ), 3586 - }; 3587 - eco_format!( 3588 - "{module_name}.dict({encoded_value}, {stringify_function}, {})", 3589 - self.encoder_for("_", value, indent) 3590 - ) 3616 + } 3591 3617 } 3592 - Some((module, name, _)) if module == self.type_module && name == self.type_name => { 3593 - maybe_capture(eco_format!("encode_{}", name.to_snake_case())) 3594 - } 3595 - _ => eco_format!( 3596 - r#"todo as "Encoder for {}""#, 3597 - self.printer.print_type(type_) 3598 - ), 3599 3618 } 3600 3619 } 3601 3620 }
+1 -1
compiler-core/src/language_server/compiler.rs
··· 3 3 use itertools::Itertools; 4 4 5 5 use crate::{ 6 + Error, Result, Warning, 6 7 analyse::TargetSupport, 7 8 build::{self, Mode, Module, NullTelemetry, Outcome, ProjectCompiler}, 8 9 config::PackageConfig, ··· 13 14 paths::ProjectPaths, 14 15 type_::ModuleInterface, 15 16 warning::VectorWarningEmitterIO, 16 - Error, Result, Warning, 17 17 }; 18 18 use std::{collections::HashMap, rc::Rc}; 19 19
+7 -7
compiler-core/src/language_server/completer.rs
··· 11 11 use vec1::Vec1; 12 12 13 13 use crate::{ 14 + Result, 14 15 ast::{ 15 16 self, Arg, CallArg, Definition, Function, FunctionLiteralKind, Pattern, Publicity, 16 17 TypedExpr, ··· 19 20 io::{BeamCompiler, CommandExecutor, FileSystemReader, FileSystemWriter}, 20 21 line_numbers::LineNumbers, 21 22 type_::{ 22 - self, collapse_links, error::VariableOrigin, pretty::Printer, FieldMap, ModuleInterface, 23 - PreludeType, RecordAccessor, Type, TypeConstructor, ValueConstructorVariant, 24 - PRELUDE_MODULE_NAME, 23 + self, FieldMap, ModuleInterface, PRELUDE_MODULE_NAME, PreludeType, RecordAccessor, Type, 24 + TypeConstructor, ValueConstructorVariant, collapse_links, error::VariableOrigin, 25 + pretty::Printer, 25 26 }, 26 - Result, 27 27 }; 28 28 29 29 use super::{ 30 + DownloadDependencies, MakeLocker, 30 31 compiler::LspProjectCompiler, 31 32 edits::{ 32 - add_newlines_after_import, get_import, get_import_edit, 33 - position_of_first_definition_if_import, Newlines, 33 + Newlines, add_newlines_after_import, get_import, get_import_edit, 34 + position_of_first_definition_if_import, 34 35 }, 35 36 files::FileSystemProxy, 36 - DownloadDependencies, MakeLocker, 37 37 }; 38 38 39 39 // Represents the kind/specificity of completion that is being requested.
+14 -12
compiler-core/src/language_server/engine.rs
··· 1 1 use crate::{ 2 + Error, Result, Warning, 2 3 analyse::name::correct_name_case, 3 4 ast::{ 4 5 ArgNames, CustomType, Definition, DefinitionLocation, ModuleConstant, Pattern, SrcSpan, 5 6 TypedArg, TypedExpr, TypedFunction, TypedModule, TypedPattern, 6 7 }, 7 - build::{type_constructor_from_modules, Located, Module, UnqualifiedImport}, 8 + build::{Located, Module, UnqualifiedImport, type_constructor_from_modules}, 8 9 config::PackageConfig, 9 10 io::{BeamCompiler, CommandExecutor, FileSystemReader, FileSystemWriter}, 10 11 language_server::{ ··· 13 14 line_numbers::LineNumbers, 14 15 paths::ProjectPaths, 15 16 type_::{ 16 - self, error::VariableOrigin, printer::Printer, Deprecation, ModuleInterface, Type, 17 - TypeConstructor, ValueConstructor, ValueConstructorVariant, 17 + self, Deprecation, ModuleInterface, Type, TypeConstructor, ValueConstructor, 18 + ValueConstructorVariant, error::VariableOrigin, printer::Printer, 18 19 }, 19 - Error, Result, Warning, 20 20 }; 21 21 use camino::Utf8PathBuf; 22 22 use ecow::EcoString; ··· 30 30 use std::sync::Arc; 31 31 32 32 use super::{ 33 + DownloadDependencies, MakeLocker, 33 34 code_action::{ 34 - code_action_add_missing_patterns, code_action_convert_qualified_constructor_to_unqualified, 35 + AddAnnotations, CodeActionBuilder, ConvertFromUse, ConvertToFunctionCall, ConvertToPipe, 36 + ConvertToUse, ExpandFunctionCapture, ExtractVariable, FillInMissingLabelledArgs, 37 + GenerateDynamicDecoder, GenerateFunction, GenerateJsonEncoder, InlineVariable, 38 + InterpolateString, LetAssertToCase, PatternMatchOnValue, RedundantTupleInCaseSubject, 39 + UseLabelShorthandSyntax, code_action_add_missing_patterns, 40 + code_action_convert_qualified_constructor_to_unqualified, 35 41 code_action_convert_unqualified_constructor_to_qualified, code_action_import_module, 36 - code_action_inexhaustive_let_to_case, AddAnnotations, CodeActionBuilder, ConvertFromUse, 37 - ConvertToFunctionCall, ConvertToPipe, ConvertToUse, ExpandFunctionCapture, ExtractVariable, 38 - FillInMissingLabelledArgs, GenerateDynamicDecoder, GenerateFunction, GenerateJsonEncoder, 39 - InlineVariable, InterpolateString, LetAssertToCase, PatternMatchOnValue, 40 - RedundantTupleInCaseSubject, UseLabelShorthandSyntax, 42 + code_action_inexhaustive_let_to_case, 41 43 }, 42 44 completer::Completer, 43 - rename::{rename_local_variable, VariableRenameKind}, 44 - signature_help, src_span_to_lsp_range, DownloadDependencies, MakeLocker, 45 + rename::{VariableRenameKind, rename_local_variable}, 46 + signature_help, src_span_to_lsp_range, 45 47 }; 46 48 47 49 #[derive(Debug, PartialEq, Eq)]
+1 -1
compiler-core/src/language_server/feedback.rs
··· 1 - use crate::{diagnostic::Diagnostic, Error, Warning}; 1 + use crate::{Error, Warning, diagnostic::Diagnostic}; 2 2 use std::collections::{HashMap, HashSet}; 3 3 4 4 use camino::Utf8PathBuf;
+3 -3
compiler-core/src/language_server/files.rs
··· 4 4 use debug_ignore::DebugIgnore; 5 5 6 6 use crate::{ 7 + Result, 7 8 error::Error, 8 9 io::{ 9 - memory::InMemoryFileSystem, BeamCompiler, Command, CommandExecutor, FileSystemReader, 10 - FileSystemWriter, ReadDir, Stdio, WrappedReader, 10 + BeamCompiler, Command, CommandExecutor, FileSystemReader, FileSystemWriter, ReadDir, Stdio, 11 + WrappedReader, memory::InMemoryFileSystem, 11 12 }, 12 - Result, 13 13 }; 14 14 15 15 use camino::{Utf8Path, Utf8PathBuf};
+2 -2
compiler-core/src/language_server/rename.rs
··· 5 5 6 6 use crate::{ 7 7 analyse::name, 8 - ast::{self, visit::Visit, SrcSpan, TypedModule}, 8 + ast::{self, SrcSpan, TypedModule, visit::Visit}, 9 9 build::Module, 10 10 line_numbers::LineNumbers, 11 - type_::{error::Named, ValueConstructor, ValueConstructorVariant}, 11 + type_::{ValueConstructor, ValueConstructorVariant, error::Named}, 12 12 }; 13 13 14 14 use super::TextEdits;
+5 -5
compiler-core/src/language_server/router.rs
··· 1 1 use crate::{ 2 + Error, Result, 2 3 build::SourceFingerprint, 3 4 error::{FileIoAction, FileKind}, 4 5 io::{BeamCompiler, CommandExecutor, FileSystemReader, FileSystemWriter}, 5 6 language_server::{ 6 - engine::LanguageServerEngine, files::FileSystemProxy, progress::ProgressReporter, 7 - DownloadDependencies, MakeLocker, 7 + DownloadDependencies, MakeLocker, engine::LanguageServerEngine, files::FileSystemProxy, 8 + progress::ProgressReporter, 8 9 }, 9 10 paths::ProjectPaths, 10 - Error, Result, 11 11 }; 12 12 use std::{ 13 - collections::{hash_map::Entry, HashMap}, 13 + collections::{HashMap, hash_map::Entry}, 14 14 time::SystemTime, 15 15 }; 16 16 ··· 194 194 #[cfg(test)] 195 195 mod find_gleam_project_parent_tests { 196 196 use super::*; 197 - use crate::io::{memory::InMemoryFileSystem, FileSystemWriter}; 197 + use crate::io::{FileSystemWriter, memory::InMemoryFileSystem}; 198 198 199 199 #[test] 200 200 fn root() {
+12 -10
compiler-core/src/language_server/server.rs
··· 3 3 progress::ConnectionProgressReporter, 4 4 }; 5 5 use crate::{ 6 + Result, 6 7 diagnostic::{Diagnostic, Level}, 7 8 io::{BeamCompiler, CommandExecutor, FileSystemReader, FileSystemWriter}, 8 9 language_server::{ 10 + DownloadDependencies, MakeLocker, 9 11 engine::{self, LanguageServerEngine}, 10 12 feedback::{Feedback, FeedbackBookKeeper}, 11 13 files::FileSystemProxy, 12 14 router::Router, 13 - src_span_to_lsp_range, DownloadDependencies, MakeLocker, 15 + src_span_to_lsp_range, 14 16 }, 15 17 line_numbers::LineNumbers, 16 - Result, 17 18 }; 18 19 use camino::{Utf8Path, Utf8PathBuf}; 19 20 use debug_ignore::DebugIgnore; ··· 509 510 .iter() 510 511 .map(|extra| { 511 512 let message = extra.label.text.clone().unwrap_or_default(); 512 - let location = if let Some((src, path)) = &extra.src_info { 513 - let line_numbers = LineNumbers::new(src); 514 - lsp::Location { 515 - uri: path_to_uri(path.clone()), 516 - range: src_span_to_lsp_range(extra.label.span, &line_numbers), 513 + let location = match &extra.src_info { 514 + Some((src, path)) => { 515 + let line_numbers = LineNumbers::new(src); 516 + lsp::Location { 517 + uri: path_to_uri(path.clone()), 518 + range: src_span_to_lsp_range(extra.label.span, &line_numbers), 519 + } 517 520 } 518 - } else { 519 - lsp::Location { 521 + _ => lsp::Location { 520 522 uri: path.clone(), 521 523 range: src_span_to_lsp_range(extra.label.span, &line_numbers), 522 - } 524 + }, 523 525 }; 524 526 lsp::DiagnosticRelatedInformation { location, message } 525 527 })
+1 -1
compiler-core/src/language_server/signature_help.rs
··· 11 11 12 12 use crate::{ 13 13 ast::{CallArg, ImplicitCallArgOrigin, TypedExpr}, 14 - type_::{pretty::Printer, FieldMap, ModuleValueConstructor, Type}, 14 + type_::{FieldMap, ModuleValueConstructor, Type, pretty::Printer}, 15 15 }; 16 16 17 17 pub fn for_expression(expr: &TypedExpr) -> Option<SignatureHelp> {
+5 -5
compiler-core/src/language_server/tests.rs
··· 21 21 use lsp_types::{Position, TextDocumentIdentifier, TextDocumentPositionParams, Url}; 22 22 23 23 use crate::{ 24 + Result, 24 25 config::PackageConfig, 25 26 io::{ 26 - memory::InMemoryFileSystem, BeamCompiler, Command, CommandExecutor, FileSystemReader, 27 - FileSystemWriter, ReadDir, WrappedReader, 27 + BeamCompiler, Command, CommandExecutor, FileSystemReader, FileSystemWriter, ReadDir, 28 + WrappedReader, memory::InMemoryFileSystem, 28 29 }, 29 30 language_server::{ 30 - engine::LanguageServerEngine, files::FileSystemProxy, progress::ProgressReporter, 31 - DownloadDependencies, LockGuard, Locker, MakeLocker, 31 + DownloadDependencies, LockGuard, Locker, MakeLocker, engine::LanguageServerEngine, 32 + files::FileSystemProxy, progress::ProgressReporter, 32 33 }, 33 34 line_numbers::LineNumbers, 34 35 manifest::{Base16Checksum, Manifest, ManifestPackage, ManifestPackageSource}, 35 36 paths::ProjectPaths, 36 37 requirement::Requirement, 37 - Result, 38 38 }; 39 39 40 40 pub const LSP_TEST_ROOT_PACKAGE_NAME: &str = "app";
+6 -6
compiler-core/src/language_server/tests/action.rs
··· 81 81 const INTERPOLATE_STRING: &str = "Interpolate string"; 82 82 83 83 macro_rules! assert_code_action { 84 - ($title:expr, $code:literal, $range:expr $(,)?) => { 84 + ($title:expr_2021, $code:literal, $range:expr_2021 $(,)?) => { 85 85 let project = TestProject::for_source($code); 86 86 assert_code_action!($title, project, $range); 87 87 }; 88 88 89 - ($title:expr, $project:expr, $range:expr $(,)?) => { 89 + ($title:expr_2021, $project:expr_2021, $range:expr_2021 $(,)?) => { 90 90 let src = $project.src; 91 91 let range = $range.find_range(src); 92 92 let result = apply_code_action($title, $project, range); ··· 100 100 } 101 101 102 102 macro_rules! assert_no_code_actions { 103 - ($title:ident $(| $titles:ident)*, $code:literal, $range:expr $(,)?) => { 103 + ($title:ident $(| $titles:ident)*, $code:literal, $range:expr_2021 $(,)?) => { 104 104 let project = TestProject::for_source($code); 105 105 assert_no_code_actions!($title $(| $titles)*, project, $range); 106 106 }; 107 107 108 - ($title:ident $(| $titles:ident)*, $project:expr, $range:expr $(,)?) => { 108 + ($title:ident $(| $titles:ident)*, $project:expr_2021, $range:expr_2021 $(,)?) => { 109 109 let src = $project.src; 110 110 let range = $range.find_range(src); 111 111 let all_titles = vec![$title $(, $titles)*]; ··· 4613 4613 } 4614 4614 4615 4615 #[test] 4616 - fn pattern_match_on_argument_with_multiple_constructors_is_nicely_formatted_in_function_with_empty_body( 4617 - ) { 4616 + fn pattern_match_on_argument_with_multiple_constructors_is_nicely_formatted_in_function_with_empty_body() 4617 + { 4618 4618 assert_code_action!( 4619 4619 PATTERN_MATCH_ON_ARGUMENT, 4620 4620 "
+14 -10
compiler-core/src/language_server/tests/completion.rs
··· 37 37 38 38 #[macro_export] 39 39 macro_rules! assert_apply_completion { 40 - ($project:expr, $name:literal, $position:expr) => { 40 + ($project:expr_2021, $name:literal, $position:expr_2021) => { 41 41 let src = $project.src; 42 42 let completions = completion($project, $position); 43 43 let output = format!( ··· 51 51 52 52 #[macro_export] 53 53 macro_rules! assert_completion { 54 - ($project:expr) => { 54 + ($project:expr_2021) => { 55 55 let src = $project.src; 56 56 let result = completion_with_prefix($project, ""); 57 57 let output = format!( ··· 61 61 ); 62 62 insta::assert_snapshot!(insta::internals::AutoName, output, src); 63 63 }; 64 - ($project:expr, $position:expr) => { 64 + ($project:expr_2021, $position:expr_2021) => { 65 65 let src = $project.src; 66 66 let result = completion($project, $position); 67 67 let output = format!( ··· 75 75 76 76 #[macro_export] 77 77 macro_rules! assert_completion_with_prefix { 78 - ($project:expr, $prefix:expr) => { 78 + ($project:expr_2021, $prefix:expr_2021) => { 79 79 let src = $project.src; 80 80 let result = completion_with_prefix($project, $prefix); 81 81 let line = 1 + $prefix.lines().count(); ··· 332 332 } 333 333 "; 334 334 335 - assert_completion!(TestProject::for_source(code) 336 - .add_module("dep", dep) 337 - .add_module("dep2", dep2)); 335 + assert_completion!( 336 + TestProject::for_source(code) 337 + .add_module("dep", dep) 338 + .add_module("dep2", dep2) 339 + ); 338 340 } 339 341 340 342 #[test] ··· 393 395 let dep = "pub fn wobble() {\nNil\n}"; 394 396 let code = "\nimport dep2\n"; // "code" goes after "fn typing_in_here() {}". 395 397 396 - assert_completion!(TestProject::for_source(code) 397 - .add_module("dep", dep) 398 - .add_module("dep2", "")); 398 + assert_completion!( 399 + TestProject::for_source(code) 400 + .add_module("dep", dep) 401 + .add_module("dep2", "") 402 + ); 399 403 } 400 404 401 405 #[test]
+5 -5
compiler-core/src/language_server/tests/definition.rs
··· 1 1 use lsp_types::{ 2 - request::GotoTypeDefinitionParams, GotoDefinitionParams, Location, Position, Range, Url, 2 + GotoDefinitionParams, Location, Position, Range, Url, request::GotoTypeDefinitionParams, 3 3 }; 4 4 5 5 use super::*; ··· 94 94 95 95 #[macro_export] 96 96 macro_rules! assert_goto { 97 - ($src:literal, $position:expr) => { 97 + ($src:literal, $position:expr_2021) => { 98 98 let project = TestProject::for_source($src); 99 99 assert_goto!(project, $position); 100 100 }; 101 - ($project:expr, $position:expr) => { 101 + ($project:expr_2021, $position:expr_2021) => { 102 102 let output = pretty_definition($project, $position); 103 103 insta::assert_snapshot!(insta::internals::AutoName, output); 104 104 }; ··· 106 106 107 107 #[macro_export] 108 108 macro_rules! assert_goto_type { 109 - ($src:literal, $position:expr) => { 109 + ($src:literal, $position:expr_2021) => { 110 110 let project = TestProject::for_source($src); 111 111 assert_goto_type!(project, $position); 112 112 }; 113 - ($project:expr, $position:expr) => { 113 + ($project:expr_2021, $position:expr_2021) => { 114 114 let output = pretty_type_definition($project, $position); 115 115 insta::assert_snapshot!(insta::internals::AutoName, output); 116 116 };
+2 -2
compiler-core/src/language_server/tests/hover.rs
··· 51 51 52 52 #[macro_export] 53 53 macro_rules! assert_hover { 54 - ($code:literal, $position:expr $(,)?) => { 54 + ($code:literal, $position:expr_2021 $(,)?) => { 55 55 let project = TestProject::for_source($code); 56 56 assert_hover!(project, $position); 57 57 }; 58 58 59 - ($project:expr, $position:expr $(,)?) => { 59 + ($project:expr_2021, $position:expr_2021 $(,)?) => { 60 60 let src = $project.src; 61 61 let position = $position.find_position(src); 62 62 let result = hover($project, position).expect("no hover produced");
+5 -5
compiler-core/src/language_server/tests/rename.rs
··· 2 2 3 3 use lsp_types::{Position, RenameParams, TextDocumentPositionParams, Url, WorkDoneProgressParams}; 4 4 5 - use crate::language_server::tests::{find_position_of, TestProject}; 5 + use crate::language_server::tests::{TestProject, find_position_of}; 6 6 7 7 use super::hover; 8 8 ··· 50 50 } 51 51 52 52 macro_rules! assert_rename { 53 - ($code:literal, $new_name:literal, $range:expr $(,)?) => { 53 + ($code:literal, $new_name:literal, $range:expr_2021 $(,)?) => { 54 54 let project = TestProject::for_source($code); 55 55 assert_rename!(project, $new_name, $range); 56 56 }; 57 57 58 - ($project:expr, $new_name:literal, $range:expr $(,)?) => { 58 + ($project:expr_2021, $new_name:literal, $range:expr_2021 $(,)?) => { 59 59 let src = $project.src; 60 60 let range = $range.find_range(src); 61 61 let result = apply_rename($project, $new_name, range.start); ··· 69 69 } 70 70 71 71 macro_rules! assert_no_rename { 72 - ($code:literal, $new_name:literal, $range:expr $(,)?) => { 72 + ($code:literal, $new_name:literal, $range:expr_2021 $(,)?) => { 73 73 let project = TestProject::for_source($code); 74 74 assert_no_rename!(project, $new_name, $range); 75 75 }; 76 76 77 - ($project:expr, $new_name:literal, $range:expr $(,)?) => { 77 + ($project:expr_2021, $new_name:literal, $range:expr_2021 $(,)?) => { 78 78 let src = $project.src; 79 79 let range = $range.find_range(src); 80 80 let result = rename($project, $new_name, range.start);
+4 -4
compiler-core/src/language_server/tests/signature_help.rs
··· 62 62 63 63 #[macro_export] 64 64 macro_rules! assert_signature_help { 65 - ($code:literal, $position:expr $(,)?) => { 65 + ($code:literal, $position:expr_2021 $(,)?) => { 66 66 let project = TestProject::for_source($code); 67 67 assert_signature_help!(project, $position); 68 68 }; 69 69 70 - ($project:expr, $position:expr $(,)?) => { 70 + ($project:expr_2021, $position:expr_2021 $(,)?) => { 71 71 let src = $project.src; 72 72 let position = $position.find_position(src); 73 73 let result = signature_help($project, position).expect("no signature help produced"); ··· 96 96 97 97 #[macro_export] 98 98 macro_rules! assert_no_signature_help { 99 - ($code:literal, $position:expr $(,)?) => { 99 + ($code:literal, $position:expr_2021 $(,)?) => { 100 100 let project = TestProject::for_source($code); 101 101 assert_no_signature_help!(project, $position); 102 102 }; 103 103 104 - ($project:expr, $position:expr $(,)?) => { 104 + ($project:expr_2021, $position:expr_2021 $(,)?) => { 105 105 let src = $project.src; 106 106 let position = $position.find_position(src); 107 107 let result = signature_help($project, position);
+1 -1
compiler-core/src/manifest.rs
··· 1 1 use std::collections::HashMap; 2 2 3 + use crate::Result; 3 4 use crate::io::{make_relative, ordered_map}; 4 5 use crate::requirement::Requirement; 5 - use crate::Result; 6 6 use camino::{Utf8Path, Utf8PathBuf}; 7 7 use ecow::EcoString; 8 8 use hexpm::version::Version;
+6 -6
compiler-core/src/metadata/module_decoder.rs
··· 5 5 use itertools::Itertools; 6 6 7 7 use crate::{ 8 + Result, 8 9 ast::{ 9 10 BitArrayOption, BitArraySegment, CallArg, Constant, Publicity, SrcSpan, TypedConstant, 10 11 TypedConstantBitArraySegment, TypedConstantBitArraySegmentOption, ··· 13 14 line_numbers::LineNumbers, 14 15 schema_capnp::{self as schema, *}, 15 16 type_::{ 16 - self, expression::Implementations, AccessorsMap, Deprecation, FieldMap, ModuleInterface, 17 - RecordAccessor, Type, TypeConstructor, TypeValueConstructor, TypeValueConstructorField, 18 - TypeVariantConstructors, ValueConstructor, ValueConstructorVariant, 17 + self, AccessorsMap, Deprecation, FieldMap, ModuleInterface, RecordAccessor, Type, 18 + TypeConstructor, TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, 19 + ValueConstructor, ValueConstructorVariant, expression::Implementations, 19 20 }, 20 21 uid::UniqueIdGenerator, 21 - Result, 22 22 }; 23 23 use std::{collections::HashMap, io::BufRead, sync::Arc}; 24 24 25 25 macro_rules! read_vec { 26 - ($reader:expr, $self:expr, $method:ident) => {{ 26 + ($reader:expr_2021, $self:expr_2021, $method:ident) => {{ 27 27 let reader = $reader; 28 28 let mut vec = Vec::with_capacity(reader.len() as usize); 29 29 for reader in reader.into_iter() { ··· 35 35 } 36 36 37 37 macro_rules! read_hashmap { 38 - ($reader:expr, $self:expr, $method:ident) => {{ 38 + ($reader:expr_2021, $self:expr_2021, $method:ident) => {{ 39 39 let reader = $reader; 40 40 let mut map = HashMap::with_capacity(reader.len() as usize); 41 41 for prop in reader.into_iter() {
+3 -3
compiler-core/src/metadata/module_encoder.rs
··· 7 7 }, 8 8 schema_capnp::{self as schema, *}, 9 9 type_::{ 10 - self, expression::Implementations, AccessorsMap, Deprecation, FieldMap, RecordAccessor, 11 - Type, TypeConstructor, TypeValueConstructor, TypeVar, TypeVariantConstructors, 12 - ValueConstructor, ValueConstructorVariant, 10 + self, AccessorsMap, Deprecation, FieldMap, RecordAccessor, Type, TypeConstructor, 11 + TypeValueConstructor, TypeVar, TypeVariantConstructors, ValueConstructor, 12 + ValueConstructorVariant, expression::Implementations, 13 13 }, 14 14 }; 15 15 use std::{collections::HashMap, ops::Deref, sync::Arc};
+16 -15
compiler-core/src/metadata/tests.rs
··· 11 11 build::Origin, 12 12 line_numbers::LineNumbers, 13 13 type_::{ 14 - self, expression::Implementations, Deprecation, ModuleInterface, Type, TypeConstructor, 15 - TypeValueConstructor, TypeValueConstructorField, TypeVariantConstructors, ValueConstructor, 16 - ValueConstructorVariant, 14 + self, Deprecation, ModuleInterface, Type, TypeConstructor, TypeValueConstructor, 15 + TypeValueConstructorField, TypeVariantConstructors, ValueConstructor, 16 + ValueConstructorVariant, expression::Implementations, 17 17 }, 18 18 uid::UniqueIdGenerator, 19 19 }; ··· 697 697 name: "one".into(), 698 698 module: "themodule".into(), 699 699 field_map: None, 700 - arity: random.gen(), 701 - variants_count: random.gen(), 700 + arity: random.r#gen(), 701 + variants_count: random.r#gen(), 702 702 location: SrcSpan { 703 - start: random.gen(), 704 - end: random.gen(), 703 + start: random.r#gen(), 704 + end: random.r#gen(), 705 705 }, 706 - variant_index: random.gen(), 706 + variant_index: random.r#gen(), 707 707 }, 708 708 }, 709 709 )] ··· 740 740 module: "themodule".into(), 741 741 name: "one".into(), 742 742 field_map: Some(FieldMap { 743 - arity: random.gen(), 744 - fields: [("ok".into(), random.gen()), ("ko".into(), random.gen())].into(), 743 + arity: random.r#gen(), 744 + fields: [("ok".into(), random.r#gen()), ("ko".into(), random.r#gen())] 745 + .into(), 745 746 }), 746 - arity: random.gen(), 747 - variants_count: random.gen(), 748 - variant_index: random.gen(), 747 + arity: random.r#gen(), 748 + variants_count: random.r#gen(), 749 + variant_index: random.r#gen(), 749 750 location: SrcSpan { 750 - start: random.gen(), 751 - end: random.gen(), 751 + start: random.r#gen(), 752 + end: random.r#gen(), 752 753 }, 753 754 }, 754 755 },
+1 -1
compiler-core/src/package_interface.rs
··· 10 10 use crate::{ 11 11 ast::{CustomType, Definition, Function, ModuleConstant, Publicity, TypeAlias}, 12 12 io::ordered_map, 13 - type_::{expression::Implementations, Deprecation, Type, TypeVar}, 13 + type_::{Deprecation, Type, TypeVar, expression::Implementations}, 14 14 }; 15 15 16 16 use crate::build::{Module, Package};
+9 -7
compiler-core/src/package_interface/tests.rs
··· 19 19 20 20 #[macro_export] 21 21 macro_rules! assert_package_interface_with_name { 22 - ($module_name:expr, $src:expr) => { 22 + ($module_name:expr_2021, $src:expr_2021) => { 23 23 let output = 24 24 $crate::package_interface::tests::compile_package(Some($module_name), $src, None); 25 25 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 28 28 29 29 #[macro_export] 30 30 macro_rules! assert_package_interface { 31 - (($dep_package:expr, $dep_name:expr, $dep_src:expr), $src:expr $(,)?) => {{ 31 + (($dep_package:expr_2021, $dep_name:expr_2021, $dep_src:expr_2021), $src:expr_2021 $(,)?) => {{ 32 32 let output = $crate::package_interface::tests::compile_package( 33 33 None, 34 34 $src, ··· 37 37 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 38 38 }}; 39 39 40 - (($dep_package:expr, $dep_name:expr, $dep_src:expr), $src:expr $(,)?) => {{ 40 + (($dep_package:expr_2021, $dep_name:expr_2021, $dep_src:expr_2021), $src:expr_2021 $(,)?) => {{ 41 41 let output = $crate::package_interface::tests::compile_package( 42 42 None, 43 43 $src, ··· 46 46 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 47 47 }}; 48 48 49 - ($src:expr) => {{ 49 + ($src:expr_2021) => {{ 50 50 let output = $crate::package_interface::tests::compile_package(None, $src, None); 51 51 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 52 52 }}; ··· 167 167 erlang: ErlangConfig::default(), 168 168 javascript: JavaScriptConfig::default(), 169 169 target: Target::Erlang, 170 - internal_modules: Some(vec![GlobBuilder::new("internals/*") 171 - .build() 172 - .expect("internals glob")]), 170 + internal_modules: Some(vec![ 171 + GlobBuilder::new("internals/*") 172 + .build() 173 + .expect("internals glob"), 174 + ]), 173 175 }, 174 176 modules: vec![module], 175 177 }
+699 -631
compiler-core/src/parse.rs
··· 54 54 pub mod lexer; 55 55 mod token; 56 56 57 + use crate::Warning; 57 58 use crate::analyse::Inferred; 58 59 use crate::ast::{ 59 60 Arg, ArgNames, AssignName, Assignment, AssignmentKind, BinOp, BitArrayOption, BitArraySegment, 60 - CallArg, Clause, ClauseGuard, Constant, CustomType, Definition, Function, FunctionLiteralKind, 61 - HasLocation, Import, Module, ModuleConstant, Pattern, Publicity, RecordBeingUpdated, 62 - RecordConstructor, RecordConstructorArg, SrcSpan, Statement, TargetedDefinition, TodoKind, 63 - TypeAlias, TypeAst, TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, 64 - UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedConstant, 65 - UntypedDefinition, UntypedExpr, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, 66 - UntypedStatement, UntypedUseAssignment, Use, UseAssignment, CAPTURE_VARIABLE, 61 + CAPTURE_VARIABLE, CallArg, Clause, ClauseGuard, Constant, CustomType, Definition, Function, 62 + FunctionLiteralKind, HasLocation, Import, Module, ModuleConstant, Pattern, Publicity, 63 + RecordBeingUpdated, RecordConstructor, RecordConstructorArg, SrcSpan, Statement, 64 + TargetedDefinition, TodoKind, TypeAlias, TypeAst, TypeAstConstructor, TypeAstFn, TypeAstHole, 65 + TypeAstTuple, TypeAstVar, UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, 66 + UntypedConstant, UntypedDefinition, UntypedExpr, UntypedModule, UntypedPattern, 67 + UntypedRecordUpdateArg, UntypedStatement, UntypedUseAssignment, Use, UseAssignment, 67 68 }; 68 69 use crate::build::Target; 69 70 use crate::error::wrap; 70 71 use crate::parse::extra::ModuleExtra; 72 + use crate::type_::Deprecation; 71 73 use crate::type_::error::VariableOrigin; 72 74 use crate::type_::expression::Implementations; 73 - use crate::type_::Deprecation; 74 75 use crate::warning::{DeprecatedSyntaxWarning, WarningEmitter}; 75 - use crate::Warning; 76 76 use camino::Utf8PathBuf; 77 77 use ecow::EcoString; 78 78 use error::{LexicalError, ParseError, ParseErrorType}; ··· 82 82 use std::collections::VecDeque; 83 83 use std::str::FromStr; 84 84 use token::Token; 85 - use vec1::{vec1, Vec1}; 85 + use vec1::{Vec1, vec1}; 86 86 87 87 #[cfg(test)] 88 88 mod tests; ··· 181 181 let mut parser = Parser::new(lex); 182 182 let expr = parser.parse_statement_seq(); 183 183 let expr = parser.ensure_no_errors_or_remaining_input(expr)?; 184 - if let Some((e, _)) = expr { 185 - Ok(e) 186 - } else { 187 - parse_error(ParseErrorType::ExpectedExpr, SrcSpan { start: 0, end: 0 }) 184 + match expr { 185 + Some((e, _)) => Ok(e), 186 + _ => parse_error(ParseErrorType::ExpectedExpr, SrcSpan { start: 0, end: 0 }), 188 187 } 189 188 } 190 189 ··· 197 196 let mut parser = Parser::new(lex); 198 197 let expr = parser.parse_const_value(); 199 198 let expr = parser.ensure_no_errors_or_remaining_input(expr)?; 200 - if let Some(e) = expr { 201 - Ok(e) 202 - } else { 203 - parse_error(ParseErrorType::ExpectedExpr, SrcSpan { start: 0, end: 0 }) 199 + match expr { 200 + Some(e) => Ok(e), 201 + _ => parse_error(ParseErrorType::ExpectedExpr, SrcSpan { start: 0, end: 0 }), 204 202 } 205 203 } 206 204 ··· 420 418 } 421 419 } 422 420 423 - if let Some((op_s, t, op_e)) = self.tok0.take() { 424 - if let Some(p) = precedence(&t) { 425 - // Is Op 426 - self.advance(); 427 - last_op_start = op_s; 428 - last_op_end = op_e; 429 - let _ = handle_op( 430 - Some(((op_s, t, op_e), p)), 431 - &mut opstack, 432 - &mut estack, 433 - &do_reduce_expression, 434 - ); 435 - } else { 436 - // Is not Op 437 - self.tok0 = Some((op_s, t, op_e)); 421 + match self.tok0.take() { 422 + Some((op_s, t, op_e)) => { 423 + match precedence(&t) { 424 + Some(p) => { 425 + // Is Op 426 + self.advance(); 427 + last_op_start = op_s; 428 + last_op_end = op_e; 429 + let _ = handle_op( 430 + Some(((op_s, t, op_e), p)), 431 + &mut opstack, 432 + &mut estack, 433 + &do_reduce_expression, 434 + ); 435 + } 436 + _ => { 437 + // Is not Op 438 + self.tok0 = Some((op_s, t, op_e)); 439 + break; 440 + } 441 + } 442 + } 443 + _ => { 438 444 break; 439 445 } 440 - } else { 441 - break; 442 446 } 443 447 } 444 448 ··· 758 762 return parse_error( 759 763 ParseErrorType::ExpectedExpr, 760 764 SrcSpan { start, end: start }, 761 - ) 765 + ); 762 766 } 763 767 } 764 768 } ··· 778 782 return parse_error( 779 783 ParseErrorType::ExpectedExpr, 780 784 SrcSpan { start, end: start }, 781 - ) 785 + ); 782 786 } 783 787 } 784 788 } ··· 791 795 792 796 // field access and call can stack up 793 797 loop { 794 - if let Some((dot_start, _)) = self.maybe_one(&Token::Dot) { 795 - let start = expr.location().start; 796 - // field access 797 - match self.tok0.take() { 798 - // tuple access 799 - Some(( 800 - _, 801 - Token::Int { 802 - value, 803 - int_value: _, 804 - }, 805 - end, 806 - )) => { 807 - self.advance(); 808 - let v = value.replace("_", ""); 809 - if let Ok(index) = u64::from_str(&v) { 810 - expr = UntypedExpr::TupleIndex { 798 + match self.maybe_one(&Token::Dot) { 799 + Some((dot_start, _)) => { 800 + let start = expr.location().start; 801 + // field access 802 + match self.tok0.take() { 803 + // tuple access 804 + Some(( 805 + _, 806 + Token::Int { 807 + value, 808 + int_value: _, 809 + }, 810 + end, 811 + )) => { 812 + self.advance(); 813 + let v = value.replace("_", ""); 814 + match u64::from_str(&v) { 815 + Ok(index) => { 816 + expr = UntypedExpr::TupleIndex { 817 + location: SrcSpan { start, end }, 818 + index, 819 + tuple: Box::new(expr), 820 + } 821 + } 822 + _ => { 823 + return parse_error( 824 + ParseErrorType::InvalidTupleAccess, 825 + SrcSpan { start, end }, 826 + ); 827 + } 828 + } 829 + } 830 + 831 + Some((label_start, Token::Name { name: label }, end)) => { 832 + self.advance(); 833 + expr = UntypedExpr::FieldAccess { 811 834 location: SrcSpan { start, end }, 812 - index, 813 - tuple: Box::new(expr), 835 + label_location: SrcSpan { 836 + start: label_start, 837 + end, 838 + }, 839 + label, 840 + container: Box::new(expr), 814 841 } 815 - } else { 816 - return parse_error( 817 - ParseErrorType::InvalidTupleAccess, 818 - SrcSpan { start, end }, 819 - ); 820 842 } 821 - } 822 843 823 - Some((label_start, Token::Name { name: label }, end)) => { 824 - self.advance(); 825 - expr = UntypedExpr::FieldAccess { 826 - location: SrcSpan { start, end }, 827 - label_location: SrcSpan { 828 - start: label_start, 829 - end, 830 - }, 831 - label, 832 - container: Box::new(expr), 844 + Some((label_start, Token::UpName { name: label }, end)) => { 845 + self.advance(); 846 + expr = UntypedExpr::FieldAccess { 847 + location: SrcSpan { start, end }, 848 + label_location: SrcSpan { 849 + start: label_start, 850 + end, 851 + }, 852 + label, 853 + container: Box::new(expr), 854 + } 833 855 } 834 - } 835 856 836 - Some((label_start, Token::UpName { name: label }, end)) => { 837 - self.advance(); 838 - expr = UntypedExpr::FieldAccess { 839 - location: SrcSpan { start, end }, 840 - label_location: SrcSpan { 841 - start: label_start, 842 - end, 843 - }, 844 - label, 845 - container: Box::new(expr), 857 + t0 => { 858 + // parse a field access with no label 859 + self.tok0 = t0; 860 + let end = dot_start + 1; 861 + expr = UntypedExpr::FieldAccess { 862 + location: SrcSpan { start, end }, 863 + label_location: SrcSpan { 864 + start: dot_start, 865 + end, 866 + }, 867 + label: "".into(), 868 + container: Box::new(expr), 869 + }; 870 + return Ok(Some(expr)); 846 871 } 847 872 } 848 - 849 - t0 => { 850 - // parse a field access with no label 851 - self.tok0 = t0; 852 - let end = dot_start + 1; 853 - expr = UntypedExpr::FieldAccess { 854 - location: SrcSpan { start, end }, 855 - label_location: SrcSpan { 856 - start: dot_start, 857 - end, 858 - }, 859 - label: "".into(), 860 - container: Box::new(expr), 861 - }; 862 - return Ok(Some(expr)); 863 - } 864 873 } 865 - } else if self.maybe_one(&Token::LeftParen).is_some() { 866 - let start = expr.location().start; 867 - if let Some((dot_s, _)) = self.maybe_one(&Token::DotDot) { 868 - // Record update 869 - let base = self.expect_expression()?; 870 - let base_e = base.location().end; 871 - let record = RecordBeingUpdated { 872 - base: Box::new(base), 873 - location: SrcSpan { 874 - start: dot_s, 875 - end: base_e, 876 - }, 877 - }; 878 - let mut args = vec![]; 879 - if self.maybe_one(&Token::Comma).is_some() { 880 - args = Parser::series_of( 881 - self, 882 - &Parser::parse_record_update_arg, 883 - Some(&Token::Comma), 884 - )?; 885 - } 886 - let (_, end) = self.expect_one(&Token::RightParen)?; 874 + _ => { 875 + if self.maybe_one(&Token::LeftParen).is_some() { 876 + let start = expr.location().start; 877 + match self.maybe_one(&Token::DotDot) { 878 + Some((dot_s, _)) => { 879 + // Record update 880 + let base = self.expect_expression()?; 881 + let base_e = base.location().end; 882 + let record = RecordBeingUpdated { 883 + base: Box::new(base), 884 + location: SrcSpan { 885 + start: dot_s, 886 + end: base_e, 887 + }, 888 + }; 889 + let mut args = vec![]; 890 + if self.maybe_one(&Token::Comma).is_some() { 891 + args = Parser::series_of( 892 + self, 893 + &Parser::parse_record_update_arg, 894 + Some(&Token::Comma), 895 + )?; 896 + } 897 + let (_, end) = self.expect_one(&Token::RightParen)?; 887 898 888 - expr = UntypedExpr::RecordUpdate { 889 - location: SrcSpan { start, end }, 890 - constructor: Box::new(expr), 891 - record, 892 - arguments: args, 893 - }; 894 - } else { 895 - // Call 896 - let args = self.parse_fn_args()?; 897 - let (_, end) = self.expect_one(&Token::RightParen)?; 898 - expr = make_call(expr, args, start, end)?; 899 + expr = UntypedExpr::RecordUpdate { 900 + location: SrcSpan { start, end }, 901 + constructor: Box::new(expr), 902 + record, 903 + arguments: args, 904 + }; 905 + } 906 + _ => { 907 + // Call 908 + let args = self.parse_fn_args()?; 909 + let (_, end) = self.expect_one(&Token::RightParen)?; 910 + expr = make_call(expr, args, start, end)?; 911 + } 912 + } 913 + } else { 914 + // done 915 + break; 916 + } 899 917 } 900 - } else { 901 - // done 902 - break; 903 918 } 904 919 } 905 920 ··· 914 929 // use a, b, c <- function(a, b) 915 930 // use a, b, c, <- function(a, b) 916 931 fn parse_use(&mut self, start: u32, end: u32) -> Result<UntypedStatement, ParseError> { 917 - let assignments = if let Some((_, Token::LArrow, _)) = self.tok0 { 918 - vec![] 919 - } else { 920 - Parser::series_of(self, &Parser::parse_use_assignment, Some(&Token::Comma))? 932 + let assignments = match self.tok0 { 933 + Some((_, Token::LArrow, _)) => { 934 + vec![] 935 + } 936 + _ => Parser::series_of(self, &Parser::parse_use_assignment, Some(&Token::Comma))?, 921 937 }; 922 938 923 939 _ = self.expect_one_following_series(&Token::LArrow, "a use variable assignment")?; ··· 963 979 964 980 // An assignment, with `Let` already consumed 965 981 fn parse_assignment(&mut self, start: u32) -> Result<UntypedStatement, ParseError> { 966 - let mut kind = if let Some((assert_start, Token::Assert, assert_end)) = self.tok0 { 967 - _ = self.next_tok(); 968 - AssignmentKind::Assert { 969 - location: SrcSpan::new(assert_start, assert_end), 970 - message: None, 982 + let mut kind = match self.tok0 { 983 + Some((assert_start, Token::Assert, assert_end)) => { 984 + _ = self.next_tok(); 985 + AssignmentKind::Assert { 986 + location: SrcSpan::new(assert_start, assert_end), 987 + message: None, 988 + } 971 989 } 972 - } else { 973 - AssignmentKind::Let 990 + _ => AssignmentKind::Let, 974 991 }; 975 - let pattern = if let Some(p) = self.parse_pattern()? { 976 - p 977 - } else { 978 - // DUPE: 62884 979 - return self.next_tok_unexpected(vec!["A pattern".into()])?; 992 + let pattern = match self.parse_pattern()? { 993 + Some(p) => p, 994 + _ => { 995 + // DUPE: 62884 996 + return self.next_tok_unexpected(vec!["A pattern".into()])?; 997 + } 980 998 }; 981 999 let annotation = self.parse_type_annotation(&Token::Colon)?; 982 1000 let (eq_s, eq_e) = self.maybe_one(&Token::Equal).ok_or(ParseError { ··· 1125 1143 return parse_error( 1126 1144 ParseErrorType::InvalidModuleTypePattern, 1127 1145 SrcSpan { start, end }, 1128 - ) 1146 + ); 1129 1147 } 1130 1148 } 1131 1149 } else { ··· 1134 1152 return parse_error( 1135 1153 ParseErrorType::LowcaseBooleanPattern, 1136 1154 SrcSpan { start, end }, 1137 - ) 1155 + ); 1138 1156 } 1139 1157 _ => Pattern::Variable { 1140 1158 origin: VariableOrigin::Variable(name.clone()), ··· 1304 1322 1305 1323 let mut elements_after_tail = None; 1306 1324 let mut dot_dot_location = None; 1307 - let tail = if let Some((dot_dot_start, Token::DotDot, dot_dot_end)) = self.tok0 { 1308 - dot_dot_location = Some((dot_dot_start, dot_dot_end)); 1309 - if !elements.is_empty() && !elements_end_with_comma { 1310 - self.warnings 1311 - .push(DeprecatedSyntaxWarning::DeprecatedListPattern { 1312 - location: SrcSpan { 1313 - start: dot_dot_start, 1314 - end: dot_dot_end, 1315 - }, 1316 - }); 1317 - } 1325 + let tail = match self.tok0 { 1326 + Some((dot_dot_start, Token::DotDot, dot_dot_end)) => { 1327 + dot_dot_location = Some((dot_dot_start, dot_dot_end)); 1328 + if !elements.is_empty() && !elements_end_with_comma { 1329 + self.warnings 1330 + .push(DeprecatedSyntaxWarning::DeprecatedListPattern { 1331 + location: SrcSpan { 1332 + start: dot_dot_start, 1333 + end: dot_dot_end, 1334 + }, 1335 + }); 1336 + } 1318 1337 1319 - self.advance(); 1320 - let pat = self.parse_pattern()?; 1321 - if self.maybe_one(&Token::Comma).is_some() { 1322 - // See if there's a list of items after the tail, 1323 - // like `[..wibble, wobble, wabble]` 1324 - let elements = 1325 - Parser::series_of(self, &Parser::parse_pattern, Some(&Token::Comma)); 1326 - match elements { 1327 - Err(_) => {} 1328 - Ok(elements) => { 1329 - elements_after_tail = Some(elements); 1330 - } 1338 + self.advance(); 1339 + let pat = self.parse_pattern()?; 1340 + if self.maybe_one(&Token::Comma).is_some() { 1341 + // See if there's a list of items after the tail, 1342 + // like `[..wibble, wobble, wabble]` 1343 + let elements = Parser::series_of( 1344 + self, 1345 + &Parser::parse_pattern, 1346 + Some(&Token::Comma), 1347 + ); 1348 + match elements { 1349 + Err(_) => {} 1350 + Ok(elements) => { 1351 + elements_after_tail = Some(elements); 1352 + } 1353 + }; 1331 1354 }; 1332 - }; 1333 - Some(pat) 1334 - } else { 1335 - None 1355 + Some(pat) 1356 + } 1357 + _ => None, 1336 1358 }; 1337 1359 1338 1360 let (end, rsqb_e) = ··· 1361 1383 } 1362 1384 // There is a tail and but it has no content, implicit discard 1363 1385 Some(Some(pat)) => { 1364 - return parse_error(ParseErrorType::InvalidTailPattern, pat.location()) 1386 + return parse_error(ParseErrorType::InvalidTailPattern, pat.location()); 1365 1387 } 1366 1388 Some(None) => Some(Pattern::Discard { 1367 1389 location: SrcSpan { ··· 1397 1419 } 1398 1420 }; 1399 1421 1400 - if let Some((_, Token::As, _)) = self.tok0 { 1401 - self.advance(); 1402 - let (start, name, end) = self.expect_name()?; 1403 - Ok(Some(Pattern::Assign { 1404 - name, 1405 - location: SrcSpan { start, end }, 1406 - pattern: Box::new(pattern), 1407 - })) 1408 - } else { 1409 - Ok(Some(pattern)) 1422 + match self.tok0 { 1423 + Some((_, Token::As, _)) => { 1424 + self.advance(); 1425 + let (start, name, end) = self.expect_name()?; 1426 + Ok(Some(Pattern::Assign { 1427 + name, 1428 + location: SrcSpan { start, end }, 1429 + pattern: Box::new(pattern), 1430 + })) 1431 + } 1432 + _ => Ok(Some(pattern)), 1410 1433 } 1411 1434 } 1412 1435 ··· 1423 1446 // pattern, pattern | pattern, pattern if -> expr 1424 1447 fn parse_case_clause(&mut self) -> Result<Option<UntypedClause>, ParseError> { 1425 1448 let patterns = self.parse_patterns()?; 1426 - if let Some(lead) = &patterns.first() { 1427 - let mut alternative_patterns = vec![]; 1428 - loop { 1429 - if self.maybe_one(&Token::Vbar).is_none() { 1430 - break; 1431 - } 1432 - alternative_patterns.push(self.parse_patterns()?); 1433 - } 1434 - let guard = self.parse_case_clause_guard(false)?; 1435 - let (arr_s, arr_e) = self 1436 - .expect_one(&Token::RArrow) 1437 - .map_err(|e| self.add_multi_line_clause_hint(e))?; 1438 - let then = self.parse_expression()?; 1439 - if let Some(then) = then { 1440 - Ok(Some(Clause { 1441 - location: SrcSpan { 1442 - start: lead.location().start, 1443 - end: then.location().end, 1444 - }, 1445 - pattern: patterns, 1446 - alternative_patterns, 1447 - guard, 1448 - then, 1449 - })) 1450 - } else { 1451 - match self.tok0 { 1452 - Some((start, Token::DiscardName { .. }, end)) => { 1453 - parse_error(ParseErrorType::IncorrectName, SrcSpan { start, end }) 1449 + match &patterns.first() { 1450 + Some(lead) => { 1451 + let mut alternative_patterns = vec![]; 1452 + loop { 1453 + if self.maybe_one(&Token::Vbar).is_none() { 1454 + break; 1454 1455 } 1455 - _ => parse_error( 1456 - ParseErrorType::ExpectedExpr, 1457 - SrcSpan { 1458 - start: arr_s, 1459 - end: arr_e, 1456 + alternative_patterns.push(self.parse_patterns()?); 1457 + } 1458 + let guard = self.parse_case_clause_guard(false)?; 1459 + let (arr_s, arr_e) = self 1460 + .expect_one(&Token::RArrow) 1461 + .map_err(|e| self.add_multi_line_clause_hint(e))?; 1462 + let then = self.parse_expression()?; 1463 + match then { 1464 + Some(then) => Ok(Some(Clause { 1465 + location: SrcSpan { 1466 + start: lead.location().start, 1467 + end: then.location().end, 1460 1468 }, 1461 - ), 1469 + pattern: patterns, 1470 + alternative_patterns, 1471 + guard, 1472 + then, 1473 + })), 1474 + _ => match self.tok0 { 1475 + Some((start, Token::DiscardName { .. }, end)) => { 1476 + parse_error(ParseErrorType::IncorrectName, SrcSpan { start, end }) 1477 + } 1478 + _ => parse_error( 1479 + ParseErrorType::ExpectedExpr, 1480 + SrcSpan { 1481 + start: arr_s, 1482 + end: arr_e, 1483 + }, 1484 + ), 1485 + }, 1462 1486 } 1463 1487 } 1464 - } else { 1465 - Ok(None) 1488 + _ => Ok(None), 1466 1489 } 1467 1490 } 1468 1491 fn parse_patterns(&mut self) -> Result<Vec<UntypedPattern>, ParseError> { ··· 1483 1506 let mut last_op_start = 0; 1484 1507 let mut last_op_end = 0; 1485 1508 loop { 1486 - if let Some(unit) = self.parse_case_clause_guard_unit()? { 1487 - estack.push(unit) 1488 - } else if estack.is_empty() { 1489 - return Ok(None); 1490 - } else { 1491 - return parse_error( 1492 - ParseErrorType::OpNakedRight, 1493 - SrcSpan { 1494 - start: last_op_start, 1495 - end: last_op_end, 1496 - }, 1497 - ); 1509 + match self.parse_case_clause_guard_unit()? { 1510 + Some(unit) => estack.push(unit), 1511 + _ => { 1512 + if estack.is_empty() { 1513 + return Ok(None); 1514 + } else { 1515 + return parse_error( 1516 + ParseErrorType::OpNakedRight, 1517 + SrcSpan { 1518 + start: last_op_start, 1519 + end: last_op_end, 1520 + }, 1521 + ); 1522 + } 1523 + } 1498 1524 } 1499 1525 1500 1526 if let Some((op_s, t, op_e)) = self.tok0.take() { 1501 - if let Some(p) = t.guard_precedence() { 1502 - // Is Op 1503 - self.advance(); 1504 - last_op_start = op_s; 1505 - last_op_end = op_e; 1506 - let _ = handle_op( 1507 - Some(((op_s, t, op_e), p)), 1508 - &mut opstack, 1509 - &mut estack, 1510 - &do_reduce_clause_guard, 1511 - ); 1512 - } else { 1513 - // Is not Op 1514 - self.tok0 = Some((op_s, t, op_e)); 1515 - break; 1527 + match t.guard_precedence() { 1528 + Some(p) => { 1529 + // Is Op 1530 + self.advance(); 1531 + last_op_start = op_s; 1532 + last_op_end = op_e; 1533 + let _ = handle_op( 1534 + Some(((op_s, t, op_e), p)), 1535 + &mut opstack, 1536 + &mut estack, 1537 + &do_reduce_clause_guard, 1538 + ); 1539 + } 1540 + _ => { 1541 + // Is not Op 1542 + self.tok0 = Some((op_s, t, op_e)); 1543 + break; 1544 + } 1516 1545 } 1517 1546 } 1518 1547 } ··· 1586 1615 1587 1616 self.parse_function_call_in_clause_guard(start)?; 1588 1617 1589 - let mut unit = if let Some(record) = 1590 - self.parse_record_in_clause_guard(&name, SrcSpan { start, end })? 1591 - { 1592 - record 1593 - } else { 1594 - ClauseGuard::Var { 1595 - location: SrcSpan { start, end }, 1596 - type_: (), 1597 - name, 1598 - definition_location: SrcSpan::default(), 1599 - } 1600 - }; 1618 + let mut unit = 1619 + match self.parse_record_in_clause_guard(&name, SrcSpan { start, end })? { 1620 + Some(record) => record, 1621 + _ => ClauseGuard::Var { 1622 + location: SrcSpan { start, end }, 1623 + type_: (), 1624 + name, 1625 + definition_location: SrcSpan::default(), 1626 + }, 1627 + }; 1601 1628 1602 1629 loop { 1603 1630 let dot_s = match self.maybe_one(&Token::Dot) { ··· 1615 1642 int_e, 1616 1643 )) => { 1617 1644 let v = value.replace("_", ""); 1618 - if let Ok(index) = u64::from_str(&v) { 1619 - unit = ClauseGuard::TupleIndex { 1620 - location: SrcSpan { 1621 - start: dot_s, 1622 - end: int_e, 1623 - }, 1624 - index, 1625 - type_: (), 1626 - tuple: Box::new(unit), 1627 - }; 1628 - } else { 1629 - return parse_error( 1630 - ParseErrorType::InvalidTupleAccess, 1631 - SrcSpan { start, end }, 1632 - ); 1645 + match u64::from_str(&v) { 1646 + Ok(index) => { 1647 + unit = ClauseGuard::TupleIndex { 1648 + location: SrcSpan { 1649 + start: dot_s, 1650 + end: int_e, 1651 + }, 1652 + index, 1653 + type_: (), 1654 + tuple: Box::new(unit), 1655 + }; 1656 + } 1657 + _ => { 1658 + return parse_error( 1659 + ParseErrorType::InvalidTupleAccess, 1660 + SrcSpan { start, end }, 1661 + ); 1662 + } 1633 1663 } 1634 1664 } 1635 1665 ··· 1652 1682 return parse_error( 1653 1683 ParseErrorType::IncorrectName, 1654 1684 SrcSpan { start, end }, 1655 - ) 1685 + ); 1656 1686 } 1657 1687 1658 1688 _ => return self.next_tok_unexpected(vec!["A positive integer".into()]), ··· 1668 1698 } 1669 1699 t0 => { 1670 1700 self.tok0 = t0; 1671 - if let Some(const_val) = self.parse_const_value()? { 1672 - // Constant 1673 - Ok(Some(ClauseGuard::Constant(const_val))) 1674 - } else { 1675 - Ok(None) 1701 + match self.parse_const_value()? { 1702 + Some(const_val) => { 1703 + // Constant 1704 + Ok(Some(ClauseGuard::Constant(const_val))) 1705 + } 1706 + _ => Ok(None), 1676 1707 } 1677 1708 } 1678 1709 } ··· 1697 1728 } 1698 1729 }; 1699 1730 1700 - if let Some(record) = self.parse_const_record_finish( 1731 + match self.parse_const_record_finish( 1701 1732 module_location.start, 1702 1733 Some((module.clone(), module_location)), 1703 1734 name, 1704 1735 end, 1705 1736 )? { 1706 - Ok(Some(ClauseGuard::Constant(record))) 1707 - } else { 1708 - Ok(None) 1737 + Some(record) => Ok(Some(ClauseGuard::Constant(record))), 1738 + _ => Ok(None), 1709 1739 } 1710 1740 } 1711 1741 ··· 1776 1806 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => { 1777 1807 self.advance(); 1778 1808 self.advance(); 1779 - if let Some(value) = self.parse_pattern()? { 1780 - Ok(Some(CallArg { 1809 + match self.parse_pattern()? { 1810 + Some(value) => Ok(Some(CallArg { 1781 1811 implicit: None, 1782 1812 location: SrcSpan { 1783 1813 start, ··· 1785 1815 }, 1786 1816 label: Some(name), 1787 1817 value, 1788 - })) 1789 - } else { 1790 - // Argument supplied with a label shorthand. 1791 - Ok(Some(CallArg { 1792 - implicit: None, 1793 - location: SrcSpan { start, end }, 1794 - label: Some(name.clone()), 1795 - value: UntypedPattern::Variable { 1796 - origin: VariableOrigin::LabelShorthand(name.clone()), 1797 - name, 1818 + })), 1819 + _ => { 1820 + // Argument supplied with a label shorthand. 1821 + Ok(Some(CallArg { 1822 + implicit: None, 1798 1823 location: SrcSpan { start, end }, 1799 - type_: (), 1800 - }, 1801 - })) 1824 + label: Some(name.clone()), 1825 + value: UntypedPattern::Variable { 1826 + origin: VariableOrigin::LabelShorthand(name.clone()), 1827 + name, 1828 + location: SrcSpan { start, end }, 1829 + type_: (), 1830 + }, 1831 + })) 1832 + } 1802 1833 } 1803 1834 } 1804 1835 // unnamed arg 1805 1836 (t0, t1) => { 1806 1837 self.tok0 = t0; 1807 1838 self.tok1 = t1; 1808 - if let Some(value) = self.parse_pattern()? { 1809 - Ok(Some(CallArg { 1839 + match self.parse_pattern()? { 1840 + Some(value) => Ok(Some(CallArg { 1810 1841 implicit: None, 1811 1842 location: value.location(), 1812 1843 label: None, 1813 1844 value, 1814 - })) 1815 - } else { 1816 - Ok(None) 1845 + })), 1846 + _ => Ok(None), 1817 1847 } 1818 1848 } 1819 1849 } ··· 1823 1853 // a: expr 1824 1854 // a: 1825 1855 fn parse_record_update_arg(&mut self) -> Result<Option<UntypedRecordUpdateArg>, ParseError> { 1826 - if let Some((start, label, _)) = self.maybe_name() { 1827 - let (_, end) = self.expect_one(&Token::Colon)?; 1828 - let value = self.parse_expression()?; 1829 - if let Some(value) = value { 1830 - Ok(Some(UntypedRecordUpdateArg { 1831 - label, 1832 - location: SrcSpan { 1833 - start, 1834 - end: value.location().end, 1835 - }, 1836 - value, 1837 - })) 1838 - } else { 1839 - // Argument supplied with a label shorthand. 1840 - Ok(Some(UntypedRecordUpdateArg { 1841 - label: label.clone(), 1842 - location: SrcSpan { start, end }, 1843 - value: UntypedExpr::Var { 1844 - name: label, 1845 - location: SrcSpan { start, end }, 1846 - }, 1847 - })) 1856 + match self.maybe_name() { 1857 + Some((start, label, _)) => { 1858 + let (_, end) = self.expect_one(&Token::Colon)?; 1859 + let value = self.parse_expression()?; 1860 + match value { 1861 + Some(value) => Ok(Some(UntypedRecordUpdateArg { 1862 + label, 1863 + location: SrcSpan { 1864 + start, 1865 + end: value.location().end, 1866 + }, 1867 + value, 1868 + })), 1869 + _ => { 1870 + // Argument supplied with a label shorthand. 1871 + Ok(Some(UntypedRecordUpdateArg { 1872 + label: label.clone(), 1873 + location: SrcSpan { start, end }, 1874 + value: UntypedExpr::Var { 1875 + name: label, 1876 + location: SrcSpan { start, end }, 1877 + }, 1878 + })) 1879 + } 1880 + } 1848 1881 } 1849 - } else { 1850 - Ok(None) 1882 + _ => Ok(None), 1851 1883 } 1852 1884 } 1853 1885 ··· 2087 2119 return Ok(None); 2088 2120 } 2089 2121 }; 2090 - let annotation = if let Some(a) = self.parse_type_annotation(&Token::Colon)? { 2091 - end = a.location().end; 2092 - Some(a) 2093 - } else { 2094 - None 2122 + let annotation = match self.parse_type_annotation(&Token::Colon)? { 2123 + Some(a) => { 2124 + end = a.location().end; 2125 + Some(a) 2126 + } 2127 + _ => None, 2095 2128 }; 2096 2129 Ok(Some(Arg { 2097 2130 location: SrcSpan { start, end }, ··· 2134 2167 } 2135 2168 }; 2136 2169 2137 - if let Some(value) = self.parse_expression()? { 2138 - let arg = if let Some((start, label, _)) = label { 2139 - CallArg { 2140 - implicit: None, 2141 - label: Some(label), 2142 - location: SrcSpan { 2143 - start, 2144 - end: value.location().end, 2170 + match self.parse_expression()? { 2171 + Some(value) => { 2172 + let arg = match label { 2173 + Some((start, label, _)) => CallArg { 2174 + implicit: None, 2175 + label: Some(label), 2176 + location: SrcSpan { 2177 + start, 2178 + end: value.location().end, 2179 + }, 2180 + value, 2145 2181 }, 2146 - value, 2147 - } 2148 - } else { 2149 - CallArg { 2150 - implicit: None, 2151 - label: None, 2152 - location: value.location(), 2153 - value, 2154 - } 2155 - }; 2156 - Ok(Some(ParserArg::Arg(Box::new(arg)))) 2157 - } else if let Some((name_start, name, name_end)) = self.maybe_discard_name() { 2158 - let arg = if let Some((label_start, label, _)) = label { 2159 - ParserArg::Hole { 2160 - label: Some(label), 2161 - arg_location: SrcSpan { 2162 - start: label_start, 2163 - end: name_end, 2164 - }, 2165 - discard_location: SrcSpan { 2166 - start: name_start, 2167 - end: name_end, 2168 - }, 2169 - name, 2170 - } 2171 - } else { 2172 - ParserArg::Hole { 2173 - label: None, 2174 - arg_location: SrcSpan { 2175 - start: name_start, 2176 - end: name_end, 2177 - }, 2178 - discard_location: SrcSpan { 2179 - start: name_start, 2180 - end: name_end, 2182 + _ => CallArg { 2183 + implicit: None, 2184 + label: None, 2185 + location: value.location(), 2186 + value, 2181 2187 }, 2182 - name, 2183 - } 2184 - }; 2188 + }; 2189 + Ok(Some(ParserArg::Arg(Box::new(arg)))) 2190 + } 2191 + _ => { 2192 + match self.maybe_discard_name() { 2193 + Some((name_start, name, name_end)) => { 2194 + let arg = match label { 2195 + Some((label_start, label, _)) => ParserArg::Hole { 2196 + label: Some(label), 2197 + arg_location: SrcSpan { 2198 + start: label_start, 2199 + end: name_end, 2200 + }, 2201 + discard_location: SrcSpan { 2202 + start: name_start, 2203 + end: name_end, 2204 + }, 2205 + name, 2206 + }, 2207 + _ => ParserArg::Hole { 2208 + label: None, 2209 + arg_location: SrcSpan { 2210 + start: name_start, 2211 + end: name_end, 2212 + }, 2213 + discard_location: SrcSpan { 2214 + start: name_start, 2215 + end: name_end, 2216 + }, 2217 + name, 2218 + }, 2219 + }; 2185 2220 2186 - Ok(Some(arg)) 2187 - } else if let Some((start, label, end)) = label { 2188 - // Argument supplied with a label shorthand. 2189 - Ok(Some(ParserArg::Arg(Box::new(CallArg { 2190 - implicit: None, 2191 - label: Some(label.clone()), 2192 - location: SrcSpan { start, end }, 2193 - value: UntypedExpr::Var { 2194 - name: label, 2195 - location: SrcSpan { start, end }, 2196 - }, 2197 - })))) 2198 - } else { 2199 - Ok(None) 2221 + Ok(Some(arg)) 2222 + } 2223 + _ => { 2224 + match label { 2225 + Some((start, label, end)) => { 2226 + // Argument supplied with a label shorthand. 2227 + Ok(Some(ParserArg::Arg(Box::new(CallArg { 2228 + implicit: None, 2229 + label: Some(label.clone()), 2230 + location: SrcSpan { start, end }, 2231 + value: UntypedExpr::Var { 2232 + name: label, 2233 + location: SrcSpan { start, end }, 2234 + }, 2235 + })))) 2236 + } 2237 + _ => Ok(None), 2238 + } 2239 + } 2240 + } 2241 + } 2200 2242 } 2201 2243 } 2202 2244 ··· 2242 2284 } 2243 2285 } 2244 2286 2245 - if let Some((c_s, c_n, c_e)) = Parser::maybe_upname(p) { 2246 - let documentation = p.take_documentation(c_s); 2247 - let (args, args_e) = Parser::parse_type_constructor_args(p)?; 2248 - let end = args_e.max(c_e); 2249 - Ok(Some(RecordConstructor { 2250 - location: SrcSpan { start: c_s, end }, 2251 - name_location: SrcSpan { 2252 - start: c_s, 2253 - end: c_e, 2254 - }, 2255 - name: c_n, 2256 - arguments: args, 2257 - documentation, 2258 - deprecation: attributes.deprecated, 2259 - })) 2260 - } else { 2261 - Ok(None) 2287 + match Parser::maybe_upname(p) { 2288 + Some((c_s, c_n, c_e)) => { 2289 + let documentation = p.take_documentation(c_s); 2290 + let (args, args_e) = Parser::parse_type_constructor_args(p)?; 2291 + let end = args_e.max(c_e); 2292 + Ok(Some(RecordConstructor { 2293 + location: SrcSpan { start: c_s, end }, 2294 + name_location: SrcSpan { 2295 + start: c_s, 2296 + end: c_e, 2297 + }, 2298 + name: c_n, 2299 + arguments: args, 2300 + documentation, 2301 + deprecation: attributes.deprecated, 2302 + })) 2303 + } 2304 + _ => Ok(None), 2262 2305 } 2263 2306 }, 2264 2307 // No separator ··· 2266 2309 )?; 2267 2310 let (_, close_end) = self.expect_custom_type_close(&name, public, opaque)?; 2268 2311 (constructors, close_end) 2269 - } else if let Some((eq_s, eq_e)) = self.maybe_one(&Token::Equal) { 2270 - // Type Alias 2271 - if opaque { 2272 - return parse_error(ParseErrorType::OpaqueTypeAlias, SrcSpan { start, end }); 2273 - } 2312 + } else { 2313 + match self.maybe_one(&Token::Equal) { 2314 + Some((eq_s, eq_e)) => { 2315 + // Type Alias 2316 + if opaque { 2317 + return parse_error( 2318 + ParseErrorType::OpaqueTypeAlias, 2319 + SrcSpan { start, end }, 2320 + ); 2321 + } 2274 2322 2275 - if let Some(t) = self.parse_type()? { 2276 - let type_end = t.location().end; 2277 - return Ok(Some(Definition::TypeAlias(TypeAlias { 2278 - documentation, 2279 - location: SrcSpan::new(start, type_end), 2280 - publicity: self.publicity(public, attributes.internal)?, 2281 - alias: name, 2282 - name_location, 2283 - parameters, 2284 - type_ast: t, 2285 - type_: (), 2286 - deprecation: std::mem::take(&mut attributes.deprecated), 2287 - }))); 2288 - } else { 2289 - return parse_error(ParseErrorType::ExpectedType, SrcSpan::new(eq_s, eq_e)); 2323 + match self.parse_type()? { 2324 + Some(t) => { 2325 + let type_end = t.location().end; 2326 + return Ok(Some(Definition::TypeAlias(TypeAlias { 2327 + documentation, 2328 + location: SrcSpan::new(start, type_end), 2329 + publicity: self.publicity(public, attributes.internal)?, 2330 + alias: name, 2331 + name_location, 2332 + parameters, 2333 + type_ast: t, 2334 + type_: (), 2335 + deprecation: std::mem::take(&mut attributes.deprecated), 2336 + }))); 2337 + } 2338 + _ => { 2339 + return parse_error( 2340 + ParseErrorType::ExpectedType, 2341 + SrcSpan::new(eq_s, eq_e), 2342 + ); 2343 + } 2344 + } 2345 + } 2346 + _ => (vec![], end), 2290 2347 } 2291 - } else { 2292 - (vec![], end) 2293 2348 }; 2294 2349 2295 2350 Ok(Some(Definition::CustomType(CustomType { ··· 2314 2369 &mut self, 2315 2370 ) -> Result<(u32, EcoString, Vec<SpannedString>, u32, u32), ParseError> { 2316 2371 let (start, upname, end) = self.expect_upname()?; 2317 - if let Some((par_s, _)) = self.maybe_one(&Token::LeftParen) { 2318 - let args = 2319 - Parser::series_of(self, &|p| Ok(Parser::maybe_name(p)), Some(&Token::Comma))?; 2320 - let (_, par_e) = self.expect_one_following_series(&Token::RightParen, "a name")?; 2321 - if args.is_empty() { 2322 - return parse_error( 2323 - ParseErrorType::TypeDefinitionNoArguments, 2324 - SrcSpan::new(par_s, par_e), 2325 - ); 2372 + match self.maybe_one(&Token::LeftParen) { 2373 + Some((par_s, _)) => { 2374 + let args = 2375 + Parser::series_of(self, &|p| Ok(Parser::maybe_name(p)), Some(&Token::Comma))?; 2376 + let (_, par_e) = self.expect_one_following_series(&Token::RightParen, "a name")?; 2377 + if args.is_empty() { 2378 + return parse_error( 2379 + ParseErrorType::TypeDefinitionNoArguments, 2380 + SrcSpan::new(par_s, par_e), 2381 + ); 2382 + } 2383 + let args2 = args 2384 + .into_iter() 2385 + .map(|(start, name, end)| (SrcSpan { start, end }, name)) 2386 + .collect(); 2387 + Ok((start, upname, args2, par_e, end)) 2326 2388 } 2327 - let args2 = args 2328 - .into_iter() 2329 - .map(|(start, name, end)| (SrcSpan { start, end }, name)) 2330 - .collect(); 2331 - Ok((start, upname, args2, par_e, end)) 2332 - } else { 2333 - Ok((start, upname, vec![], end, end)) 2389 + _ => Ok((start, upname, vec![], end, end)), 2334 2390 } 2335 2391 } 2336 2392 ··· 2453 2509 let _ = self.expect_one_following_series(&Token::RightParen, "a type")?; 2454 2510 let (arr_s, arr_e) = self.expect_one(&Token::RArrow)?; 2455 2511 let retrn = self.parse_type()?; 2456 - if let Some(retrn) = retrn { 2457 - Ok(Some(TypeAst::Fn(TypeAstFn { 2512 + match retrn { 2513 + Some(retrn) => Ok(Some(TypeAst::Fn(TypeAstFn { 2458 2514 location: SrcSpan { 2459 2515 start, 2460 2516 end: retrn.location().end, 2461 2517 }, 2462 2518 return_: Box::new(retrn), 2463 2519 arguments: args, 2464 - }))) 2465 - } else { 2466 - parse_error( 2520 + }))), 2521 + _ => parse_error( 2467 2522 ParseErrorType::ExpectedType, 2468 2523 SrcSpan { 2469 2524 start: arr_s, 2470 2525 end: arr_e, 2471 2526 }, 2472 - ) 2527 + ), 2473 2528 } 2474 2529 } 2475 2530 ··· 2513 2568 name: EcoString, 2514 2569 end: u32, 2515 2570 ) -> Result<Option<TypeAst>, ParseError> { 2516 - if let Some((par_s, _)) = self.maybe_one(&Token::LeftParen) { 2517 - let args = self.parse_types()?; 2518 - let (_, par_e) = self.expect_one(&Token::RightParen)?; 2519 - if args.is_empty() { 2520 - return parse_error( 2521 - ParseErrorType::TypeConstructorNoArguments, 2522 - SrcSpan::new(par_s, par_e), 2523 - ); 2571 + match self.maybe_one(&Token::LeftParen) { 2572 + Some((par_s, _)) => { 2573 + let args = self.parse_types()?; 2574 + let (_, par_e) = self.expect_one(&Token::RightParen)?; 2575 + if args.is_empty() { 2576 + return parse_error( 2577 + ParseErrorType::TypeConstructorNoArguments, 2578 + SrcSpan::new(par_s, par_e), 2579 + ); 2580 + } 2581 + Ok(Some(TypeAst::Constructor(TypeAstConstructor { 2582 + location: SrcSpan { start, end: par_e }, 2583 + module, 2584 + name, 2585 + arguments: args, 2586 + }))) 2524 2587 } 2525 - Ok(Some(TypeAst::Constructor(TypeAstConstructor { 2526 - location: SrcSpan { start, end: par_e }, 2527 - module, 2528 - name, 2529 - arguments: args, 2530 - }))) 2531 - } else { 2532 - Ok(Some(TypeAst::Constructor(TypeAstConstructor { 2588 + _ => Ok(Some(TypeAst::Constructor(TypeAstConstructor { 2533 2589 location: SrcSpan { start, end }, 2534 2590 module, 2535 2591 name, 2536 2592 arguments: vec![], 2537 - }))) 2593 + }))), 2538 2594 } 2539 2595 } 2540 2596 ··· 2720 2776 let annotation = self.parse_type_annotation(&Token::Colon)?; 2721 2777 2722 2778 let (eq_s, eq_e) = self.expect_one(&Token::Equal)?; 2723 - if let Some(value) = self.parse_const_value()? { 2724 - Ok(Some(Definition::ModuleConstant(ModuleConstant { 2725 - documentation, 2726 - location: SrcSpan { 2727 - start, 2779 + match self.parse_const_value()? { 2780 + Some(value) => { 2781 + Ok(Some(Definition::ModuleConstant(ModuleConstant { 2782 + documentation, 2783 + location: SrcSpan { 2784 + start, 2728 2785 2729 - // End after the type annotation if it's there, otherwise after the name 2730 - end: annotation 2731 - .as_ref() 2732 - .map(|annotation| annotation.location().end) 2733 - .unwrap_or(0) 2734 - .max(name_end), 2735 - }, 2736 - publicity: self.publicity(public, attributes.internal)?, 2737 - name, 2738 - name_location: SrcSpan::new(name_start, name_end), 2739 - annotation, 2740 - value: Box::new(value), 2741 - type_: (), 2742 - deprecation: attributes.deprecated.clone(), 2743 - implementations: Implementations { 2744 - gleam: true, 2745 - can_run_on_erlang: true, 2746 - can_run_on_javascript: true, 2747 - uses_erlang_externals: false, 2748 - uses_javascript_externals: false, 2749 - }, 2750 - }))) 2751 - } else { 2752 - parse_error( 2786 + // End after the type annotation if it's there, otherwise after the name 2787 + end: annotation 2788 + .as_ref() 2789 + .map(|annotation| annotation.location().end) 2790 + .unwrap_or(0) 2791 + .max(name_end), 2792 + }, 2793 + publicity: self.publicity(public, attributes.internal)?, 2794 + name, 2795 + name_location: SrcSpan::new(name_start, name_end), 2796 + annotation, 2797 + value: Box::new(value), 2798 + type_: (), 2799 + deprecation: attributes.deprecated.clone(), 2800 + implementations: Implementations { 2801 + gleam: true, 2802 + can_run_on_erlang: true, 2803 + can_run_on_javascript: true, 2804 + uses_erlang_externals: false, 2805 + uses_javascript_externals: false, 2806 + }, 2807 + }))) 2808 + } 2809 + _ => parse_error( 2753 2810 ParseErrorType::NoValueAfterEqual, 2754 2811 SrcSpan { 2755 2812 start: eq_s, 2756 2813 end: eq_e, 2757 2814 }, 2758 - ) 2815 + ), 2759 2816 } 2760 2817 } 2761 2818 ··· 2767 2824 // foo <> "bar" 2768 2825 fn parse_const_value(&mut self) -> Result<Option<UntypedConstant>, ParseError> { 2769 2826 let constant_result = self.parse_const_value_unit(); 2770 - if let Ok(Some(constant)) = constant_result { 2771 - self.parse_const_maybe_concatenation(constant) 2772 - } else { 2773 - constant_result 2827 + match constant_result { 2828 + Ok(Some(constant)) => self.parse_const_maybe_concatenation(constant), 2829 + _ => constant_result, 2774 2830 } 2775 2831 } 2776 2832 ··· 2945 3001 Some((op_start, Token::LtGt, op_end)) => { 2946 3002 self.advance(); 2947 3003 2948 - if let Ok(Some(right_constant_value)) = self.parse_const_value() { 2949 - Ok(Some(Constant::StringConcatenation { 3004 + match self.parse_const_value() { 3005 + Ok(Some(right_constant_value)) => Ok(Some(Constant::StringConcatenation { 2950 3006 location: SrcSpan { 2951 3007 start: left.location().start, 2952 3008 end: right_constant_value.location().end, 2953 3009 }, 2954 3010 left: Box::new(left), 2955 3011 right: Box::new(right_constant_value), 2956 - })) 2957 - } else { 2958 - parse_error( 3012 + })), 3013 + _ => parse_error( 2959 3014 ParseErrorType::OpNakedRight, 2960 3015 SrcSpan { 2961 3016 start: op_start, 2962 3017 end: op_end, 2963 3018 }, 2964 - ) 3019 + ), 2965 3020 } 2966 3021 } 2967 3022 t0 => { ··· 2979 3034 name: EcoString, 2980 3035 end: u32, 2981 3036 ) -> Result<Option<UntypedConstant>, ParseError> { 2982 - if let Some((par_s, _)) = self.maybe_one(&Token::LeftParen) { 2983 - let args = 2984 - Parser::series_of(self, &Parser::parse_const_record_arg, Some(&Token::Comma))?; 2985 - let (_, par_e) = 2986 - self.expect_one_following_series(&Token::RightParen, "a constant record argument")?; 2987 - if args.is_empty() { 2988 - return parse_error( 2989 - ParseErrorType::ConstantRecordConstructorNoArguments, 2990 - SrcSpan::new(par_s, par_e), 2991 - ); 3037 + match self.maybe_one(&Token::LeftParen) { 3038 + Some((par_s, _)) => { 3039 + let args = 3040 + Parser::series_of(self, &Parser::parse_const_record_arg, Some(&Token::Comma))?; 3041 + let (_, par_e) = self.expect_one_following_series( 3042 + &Token::RightParen, 3043 + "a constant record argument", 3044 + )?; 3045 + if args.is_empty() { 3046 + return parse_error( 3047 + ParseErrorType::ConstantRecordConstructorNoArguments, 3048 + SrcSpan::new(par_s, par_e), 3049 + ); 3050 + } 3051 + Ok(Some(Constant::Record { 3052 + location: SrcSpan { start, end: par_e }, 3053 + module, 3054 + name, 3055 + args, 3056 + tag: (), 3057 + type_: (), 3058 + field_map: None, 3059 + })) 2992 3060 } 2993 - Ok(Some(Constant::Record { 2994 - location: SrcSpan { start, end: par_e }, 2995 - module, 2996 - name, 2997 - args, 2998 - tag: (), 2999 - type_: (), 3000 - field_map: None, 3001 - })) 3002 - } else { 3003 - Ok(Some(Constant::Record { 3061 + _ => Ok(Some(Constant::Record { 3004 3062 location: SrcSpan { start, end }, 3005 3063 module, 3006 3064 name, ··· 3008 3066 tag: (), 3009 3067 type_: (), 3010 3068 field_map: None, 3011 - })) 3069 + })), 3012 3070 } 3013 3071 } 3014 3072 ··· 3033 3091 } 3034 3092 }; 3035 3093 3036 - if let Some(value) = self.parse_const_value()? { 3037 - if let Some((start, label, _)) = label { 3038 - Ok(Some(CallArg { 3094 + match self.parse_const_value()? { 3095 + Some(value) => match label { 3096 + Some((start, label, _)) => Ok(Some(CallArg { 3039 3097 implicit: None, 3040 3098 location: SrcSpan { 3041 3099 start, ··· 3043 3101 }, 3044 3102 value, 3045 3103 label: Some(label), 3046 - })) 3047 - } else { 3048 - Ok(Some(CallArg { 3104 + })), 3105 + _ => Ok(Some(CallArg { 3049 3106 implicit: None, 3050 3107 location: value.location(), 3051 3108 value, 3052 3109 label: None, 3053 - })) 3110 + })), 3111 + }, 3112 + _ => { 3113 + match label { 3114 + Some((start, label, end)) => { 3115 + // Argument supplied with a label shorthand. 3116 + Ok(Some(CallArg { 3117 + implicit: None, 3118 + location: SrcSpan { start, end }, 3119 + label: Some(label.clone()), 3120 + value: UntypedConstant::Var { 3121 + location: SrcSpan { start, end }, 3122 + constructor: None, 3123 + module: None, 3124 + name: label, 3125 + type_: (), 3126 + }, 3127 + })) 3128 + } 3129 + _ => Ok(None), 3130 + } 3054 3131 } 3055 - } else if let Some((start, label, end)) = label { 3056 - // Argument supplied with a label shorthand. 3057 - Ok(Some(CallArg { 3058 - implicit: None, 3059 - location: SrcSpan { start, end }, 3060 - label: Some(label.clone()), 3061 - value: UntypedConstant::Var { 3062 - location: SrcSpan { start, end }, 3063 - constructor: None, 3064 - module: None, 3065 - name: label, 3066 - type_: (), 3067 - }, 3068 - })) 3069 - } else { 3070 - Ok(None) 3071 3132 } 3072 3133 } 3073 3134 ··· 3088 3149 where 3089 3150 A: HasLocation + std::fmt::Debug, 3090 3151 { 3091 - if let Some(value) = value_parser(self)? { 3092 - let options = if self.maybe_one(&Token::Colon).is_some() { 3093 - Parser::series_of( 3094 - self, 3095 - &|s| Parser::parse_bit_array_option(s, &arg_parser, &to_int_segment), 3096 - Some(&Token::Minus), 3097 - )? 3098 - } else { 3099 - vec![] 3100 - }; 3101 - let end = options 3102 - .last() 3103 - .map(|o| o.location().end) 3104 - .unwrap_or_else(|| value.location().end); 3105 - Ok(Some(BitArraySegment { 3106 - location: SrcSpan { 3107 - start: value.location().start, 3108 - end, 3109 - }, 3110 - value: Box::new(value), 3111 - type_: (), 3112 - options, 3113 - })) 3114 - } else { 3115 - Ok(None) 3152 + match value_parser(self)? { 3153 + Some(value) => { 3154 + let options = if self.maybe_one(&Token::Colon).is_some() { 3155 + Parser::series_of( 3156 + self, 3157 + &|s| Parser::parse_bit_array_option(s, &arg_parser, &to_int_segment), 3158 + Some(&Token::Minus), 3159 + )? 3160 + } else { 3161 + vec![] 3162 + }; 3163 + let end = options 3164 + .last() 3165 + .map(|o| o.location().end) 3166 + .unwrap_or_else(|| value.location().end); 3167 + Ok(Some(BitArraySegment { 3168 + location: SrcSpan { 3169 + start: value.location().start, 3170 + end, 3171 + }, 3172 + value: Box::new(value), 3173 + type_: (), 3174 + options, 3175 + })) 3176 + } 3177 + _ => Ok(None), 3116 3178 } 3117 3179 } 3118 3180 ··· 3132 3194 if self.maybe_one(&Token::LeftParen).is_some() { 3133 3195 // named function segment 3134 3196 match name.as_str() { 3135 - "unit" => { 3136 - if let Some((int_s, Token::Int { value, .. }, int_e)) = self.next_tok() 3137 - { 3197 + "unit" => match self.next_tok() { 3198 + Some((int_s, Token::Int { value, .. }, int_e)) => { 3138 3199 let (_, end) = self.expect_one(&Token::RightParen)?; 3139 3200 let v = value.replace("_", ""); 3140 3201 match u8::from_str(&v) { ··· 3151 3212 }, 3152 3213 }), 3153 3214 } 3154 - } else { 3155 - self.next_tok_unexpected(vec!["positive integer".into()]) 3156 3215 } 3157 - } 3216 + _ => self.next_tok_unexpected(vec!["positive integer".into()]), 3217 + }, 3158 3218 3159 3219 "size" => { 3160 3220 let value = arg_parser(self)?; ··· 3222 3282 } 3223 3283 3224 3284 fn expect_expression(&mut self) -> Result<UntypedExpr, ParseError> { 3225 - if let Some(e) = self.parse_expression()? { 3226 - Ok(e) 3227 - } else { 3228 - self.next_tok_unexpected(vec!["An expression".into()]) 3285 + match self.parse_expression()? { 3286 + Some(e) => Ok(e), 3287 + _ => self.next_tok_unexpected(vec!["An expression".into()]), 3229 3288 } 3230 3289 } 3231 3290 3232 3291 fn expect_expression_unit(&mut self) -> Result<UntypedExpr, ParseError> { 3233 - if let Some(e) = self.parse_expression_unit()? { 3234 - Ok(e) 3235 - } else { 3236 - self.next_tok_unexpected(vec!["An expression".into()]) 3292 + match self.parse_expression_unit()? { 3293 + Some(e) => Ok(e), 3294 + _ => self.next_tok_unexpected(vec!["An expression".into()]), 3237 3295 } 3238 3296 } 3239 3297 ··· 3360 3418 fn expect_upname(&mut self) -> Result<(u32, EcoString, u32), ParseError> { 3361 3419 let t = self.next_tok(); 3362 3420 match t { 3363 - Some((start, tok, end)) => { 3364 - if let Token::Name { .. } = tok { 3365 - parse_error(ParseErrorType::IncorrectUpName, SrcSpan { start, end }) 3366 - } else if let Token::UpName { name } = tok { 3367 - Ok((start, name, end)) 3368 - } else if let Token::DiscardName { .. } = tok { 3421 + Some((start, tok, end)) => match tok { 3422 + Token::Name { .. } => { 3369 3423 parse_error(ParseErrorType::IncorrectUpName, SrcSpan { start, end }) 3370 - } else { 3371 - parse_error(ParseErrorType::ExpectedUpName, SrcSpan { start, end }) 3372 3424 } 3373 - } 3425 + _ => match tok { 3426 + Token::UpName { name } => Ok((start, name, end)), 3427 + _ => match tok { 3428 + Token::DiscardName { .. } => { 3429 + parse_error(ParseErrorType::IncorrectUpName, SrcSpan { start, end }) 3430 + } 3431 + _ => parse_error(ParseErrorType::ExpectedUpName, SrcSpan { start, end }), 3432 + }, 3433 + }, 3434 + }, 3374 3435 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }), 3375 3436 } 3376 3437 } ··· 3380 3441 let (start, t, end) = match self.next_tok() { 3381 3442 Some(t) => t, 3382 3443 None => { 3383 - return parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }) 3444 + return parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }); 3384 3445 } 3385 3446 }; 3386 3447 match t { ··· 3777 3838 let mut next_op = next_op; 3778 3839 loop { 3779 3840 match (opstack.pop(), next_op.take()) { 3780 - (None, None) => { 3781 - if let Some(fin) = estack.pop() { 3841 + (None, None) => match estack.pop() { 3842 + Some(fin) => { 3782 3843 if estack.is_empty() { 3783 3844 return Some(fin); 3784 3845 } else { 3785 3846 panic!("Expression not fully reduced.") 3786 3847 } 3787 - } else { 3848 + } 3849 + _ => { 3788 3850 return None; 3789 3851 } 3790 - } 3852 + }, 3791 3853 3792 3854 (None, Some(op)) => { 3793 3855 opstack.push(op); ··· 3873 3935 3874 3936 fn expr_op_reduction((_, token, _): Spanned, l: UntypedExpr, r: UntypedExpr) -> UntypedExpr { 3875 3937 if token == Token::Pipe { 3876 - let expressions = if let UntypedExpr::PipeLine { mut expressions } = l { 3877 - expressions.push(r); 3878 - expressions 3879 - } else { 3880 - vec1![l, r] 3938 + let expressions = match l { 3939 + UntypedExpr::PipeLine { mut expressions } => { 3940 + expressions.push(r); 3941 + expressions 3942 + } 3943 + _ => { 3944 + vec1![l, r] 3945 + } 3881 3946 }; 3882 3947 UntypedExpr::PipeLine { expressions } 3883 - } else if let Some(bin_op) = tok_to_binop(&token) { 3884 - UntypedExpr::BinOp { 3885 - location: SrcSpan { 3886 - start: l.location().start, 3887 - end: r.location().end, 3948 + } else { 3949 + match tok_to_binop(&token) { 3950 + Some(bin_op) => UntypedExpr::BinOp { 3951 + location: SrcSpan { 3952 + start: l.location().start, 3953 + end: r.location().end, 3954 + }, 3955 + name: bin_op, 3956 + left: Box::new(l), 3957 + right: Box::new(r), 3888 3958 }, 3889 - name: bin_op, 3890 - left: Box::new(l), 3891 - right: Box::new(r), 3959 + _ => { 3960 + panic!("Token could not be converted to binop.") 3961 + } 3892 3962 } 3893 - } else { 3894 - panic!("Token could not be converted to binop.") 3895 3963 } 3896 3964 } 3897 3965
+12 -10
compiler-core/src/parse/lexer.rs
··· 477 477 478 478 let end_pos = self.get_pos(); 479 479 480 - if let Some(tok) = str_to_keyword(&name) { 481 - Ok((start_pos, tok, end_pos)) 482 - } else if name.starts_with('_') { 483 - Ok((start_pos, Token::DiscardName { name: name.into() }, end_pos)) 484 - } else { 485 - Ok((start_pos, Token::Name { name: name.into() }, end_pos)) 480 + match str_to_keyword(&name) { 481 + Some(tok) => Ok((start_pos, tok, end_pos)), 482 + _ => { 483 + if name.starts_with('_') { 484 + Ok((start_pos, Token::DiscardName { name: name.into() }, end_pos)) 485 + } else { 486 + Ok((start_pos, Token::Name { name: name.into() }, end_pos)) 487 + } 488 + } 486 489 } 487 490 } 488 491 // A type name or constructor ··· 496 499 497 500 let end_pos = self.get_pos(); 498 501 499 - if let Some(tok) = str_to_keyword(&name) { 500 - Ok((start_pos, tok, end_pos)) 501 - } else { 502 - Ok((start_pos, Token::UpName { name: name.into() }, end_pos)) 502 + match str_to_keyword(&name) { 503 + Some(tok) => Ok((start_pos, tok, end_pos)), 504 + _ => Ok((start_pos, Token::UpName { name: name.into() }, end_pos)), 503 505 } 504 506 } 505 507
+5 -5
compiler-core/src/parse/tests.rs
··· 12 12 use pretty_assertions::assert_eq; 13 13 14 14 macro_rules! assert_error { 15 - ($src:expr, $error:expr $(,)?) => { 15 + ($src:expr_2021, $error:expr_2021 $(,)?) => { 16 16 let result = crate::parse::parse_statement_sequence($src).expect_err("should not parse"); 17 17 assert_eq!(($src, $error), ($src, result),); 18 18 }; 19 - ($src:expr) => { 19 + ($src:expr_2021) => { 20 20 let error = $crate::parse::tests::expect_error($src); 21 21 let output = format!("----- SOURCE CODE\n{}\n\n----- ERROR\n{}", $src, error); 22 22 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 24 24 } 25 25 26 26 macro_rules! assert_module_error { 27 - ($src:expr) => { 27 + ($src:expr_2021) => { 28 28 let error = $crate::parse::tests::expect_module_error($src); 29 29 let output = format!("----- SOURCE CODE\n{}\n\n----- ERROR\n{}", $src, error); 30 30 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 32 32 } 33 33 34 34 macro_rules! assert_parse_module { 35 - ($src:expr) => { 35 + ($src:expr_2021) => { 36 36 let result = crate::parse::parse_module( 37 37 camino::Utf8PathBuf::from("test/path"), 38 38 $src, ··· 44 44 } 45 45 46 46 macro_rules! assert_parse { 47 - ($src:expr) => { 47 + ($src:expr_2021) => { 48 48 let result = crate::parse::parse_statement_sequence($src).expect("should parse"); 49 49 insta::assert_snapshot!(insta::internals::AutoName, &format!("{:#?}", result), $src); 50 50 };
+4 -2
compiler-core/src/paths.rs
··· 166 166 .ends_with("hex/hexpm/packages/gleam_stdlib-0.17.1.tar") 167 167 ); 168 168 169 - assert!(global_package_cache_package_tarball("elli", "1.0.0") 170 - .ends_with("hex/hexpm/packages/elli-1.0.0.tar")); 169 + assert!( 170 + global_package_cache_package_tarball("elli", "1.0.0") 171 + .ends_with("hex/hexpm/packages/elli-1.0.0.tar") 172 + ); 171 173 }
+3 -3
compiler-core/src/pretty.rs
··· 16 16 #[cfg(test)] 17 17 mod tests; 18 18 19 - use ecow::{eco_format, EcoString}; 19 + use ecow::{EcoString, eco_format}; 20 20 use itertools::Itertools; 21 21 use unicode_segmentation::UnicodeSegmentation; 22 22 23 - use crate::{io::Utf8Writer, Result}; 23 + use crate::{Result, io::Utf8Writer}; 24 24 25 25 #[macro_export] 26 26 macro_rules! docvec { ··· 28 28 Document::Vec(Vec::new()) 29 29 }; 30 30 31 - ($($x:expr),+ $(,)?) => { 31 + ($($x:expr_2021),+ $(,)?) => { 32 32 Document::Vec(vec![$($x.to_doc()),+]) 33 33 }; 34 34 }
+1 -1
compiler-core/src/requirement.rs
··· 6 6 use camino::{Utf8Path, Utf8PathBuf}; 7 7 use ecow::EcoString; 8 8 use hexpm::version::Range; 9 + use serde::Deserialize; 9 10 use serde::de::{self, Deserializer, MapAccess, Visitor}; 10 11 use serde::ser::{Serialize, SerializeMap, Serializer}; 11 - use serde::Deserialize; 12 12 13 13 #[derive(Deserialize, Debug, PartialEq, Eq, Clone)] 14 14 #[serde(untagged, remote = "Self")]
+3 -3
compiler-core/src/type_/environment.rs
··· 2 2 3 3 use crate::{ 4 4 analyse::TargetSupport, 5 - ast::{Publicity, PIPE_VARIABLE}, 5 + ast::{PIPE_VARIABLE, Publicity}, 6 6 build::Target, 7 7 error::edit_distance, 8 8 uid::UniqueIdGenerator, ··· 540 540 Type::Var { type_ } => { 541 541 match type_.borrow().deref() { 542 542 TypeVar::Link { type_ } => { 543 - return self.instantiate(type_.clone(), ids, hydrator) 543 + return self.instantiate(type_.clone(), ids, hydrator); 544 544 } 545 545 546 546 TypeVar::Unbound { .. } => { 547 547 return Arc::new(Type::Var { 548 548 type_: type_.clone(), 549 - }) 549 + }); 550 550 } 551 551 552 552 TypeVar::Generic { id } => match ids.get(id) {
+1 -1
compiler-core/src/type_/error.rs
··· 1 1 use super::{ 2 - expression::{ArgumentKind, CallKind}, 3 2 FieldAccessUsage, 3 + expression::{ArgumentKind, CallKind}, 4 4 }; 5 5 use crate::{ 6 6 ast::{BinOp, Layer, SrcSpan, TodoKind},
+65 -57
compiler-core/src/type_/expression.rs
··· 4 4 ast::{ 5 5 Arg, Assignment, AssignmentKind, BinOp, BitArrayOption, BitArraySegment, CallArg, Clause, 6 6 ClauseGuard, Constant, FunctionLiteralKind, HasLocation, ImplicitCallArgOrigin, Layer, 7 - RecordBeingUpdated, SrcSpan, Statement, TodoKind, TypeAst, TypedArg, TypedAssignment, 8 - TypedClause, TypedClauseGuard, TypedConstant, TypedExpr, TypedMultiPattern, TypedStatement, 9 - UntypedArg, UntypedAssignment, UntypedClause, UntypedClauseGuard, UntypedConstant, 10 - UntypedConstantBitArraySegment, UntypedExpr, UntypedExprBitArraySegment, 11 - UntypedMultiPattern, UntypedStatement, UntypedUse, UntypedUseAssignment, Use, 12 - UseAssignment, RECORD_UPDATE_VARIABLE, USE_ASSIGNMENT_VARIABLE, 7 + RECORD_UPDATE_VARIABLE, RecordBeingUpdated, SrcSpan, Statement, TodoKind, TypeAst, 8 + TypedArg, TypedAssignment, TypedClause, TypedClauseGuard, TypedConstant, TypedExpr, 9 + TypedMultiPattern, TypedStatement, USE_ASSIGNMENT_VARIABLE, UntypedArg, UntypedAssignment, 10 + UntypedClause, UntypedClauseGuard, UntypedConstant, UntypedConstantBitArraySegment, 11 + UntypedExpr, UntypedExprBitArraySegment, UntypedMultiPattern, UntypedStatement, UntypedUse, 12 + UntypedUseAssignment, Use, UseAssignment, 13 13 }, 14 14 build::Target, 15 15 exhaustiveness::{self, Reachability}, ··· 1713 1713 1714 1714 ValueConstructorVariant::ModuleConstant { literal, .. } 1715 1715 | ValueConstructorVariant::LocalConstant { literal } => { 1716 - return Ok(ClauseGuard::Constant(literal.clone())) 1716 + return Ok(ClauseGuard::Constant(literal.clone())); 1717 1717 } 1718 1718 }; 1719 1719 ··· 2569 2569 self.track_feature_usage(FeatureKind::LabelShorthandSyntax, *location); 2570 2570 } 2571 2571 2572 - if let Some(index) = fields.remove(label) { 2573 - unify(variant.arg_type(index), value.type_()) 2574 - .map_err(|e| convert_unify_error(e, *location))?; 2572 + match fields.remove(label) { 2573 + Some(index) => { 2574 + unify(variant.arg_type(index), value.type_()) 2575 + .map_err(|e| convert_unify_error(e, *location))?; 2575 2576 2576 - Ok(( 2577 - index, 2578 - CallArg { 2579 - label: Some(label.clone()), 2580 - location: *location, 2581 - value, 2582 - implicit: None, 2583 - }, 2584 - )) 2585 - } else if variant.has_field(label) { 2586 - Err(Error::DuplicateArgument { 2587 - location: *location, 2588 - label: label.clone(), 2589 - }) 2590 - } else { 2591 - Err(self.unknown_field_error( 2592 - variant.field_names(), 2593 - record_type.clone(), 2594 - *location, 2595 - label.clone(), 2596 - FieldAccessUsage::RecordUpdate, 2597 - )) 2577 + Ok(( 2578 + index, 2579 + CallArg { 2580 + label: Some(label.clone()), 2581 + location: *location, 2582 + value, 2583 + implicit: None, 2584 + }, 2585 + )) 2586 + } 2587 + _ => { 2588 + if variant.has_field(label) { 2589 + Err(Error::DuplicateArgument { 2590 + location: *location, 2591 + label: label.clone(), 2592 + }) 2593 + } else { 2594 + Err(self.unknown_field_error( 2595 + variant.field_names(), 2596 + record_type.clone(), 2597 + *location, 2598 + label.clone(), 2599 + FieldAccessUsage::RecordUpdate, 2600 + )) 2601 + } 2602 + } 2598 2603 } 2599 2604 }, 2600 2605 ) ··· 2675 2680 _ => { 2676 2681 return Err(Error::RecordUpdateInvalidConstructor { 2677 2682 location: constructor.location(), 2678 - }) 2683 + }); 2679 2684 } 2680 2685 }; 2681 2686 ··· 2703 2708 _ => { 2704 2709 return Err(Error::RecordUpdateInvalidConstructor { 2705 2710 location: constructor.location(), 2706 - }) 2711 + }); 2707 2712 } 2708 2713 }; 2709 2714 ··· 2985 2990 2986 2991 ValueConstructorVariant::ModuleFn { .. } 2987 2992 | ValueConstructorVariant::LocalVariable { .. } => { 2988 - return Err(Error::NonLocalClauseGuardVariable { location, name }) 2993 + return Err(Error::NonLocalClauseGuardVariable { location, name }); 2989 2994 } 2990 2995 2991 2996 // TODO: remove this clone. Could use an rc instead 2992 2997 ValueConstructorVariant::ModuleConstant { literal, .. } 2993 2998 | ValueConstructorVariant::LocalConstant { literal } => { 2994 - return Ok(literal.clone()) 2999 + return Ok(literal.clone()); 2995 3000 } 2996 3001 }; 2997 3002 ··· 3029 3034 3030 3035 ValueConstructorVariant::ModuleFn { .. } 3031 3036 | ValueConstructorVariant::LocalVariable { .. } => { 3032 - return Err(Error::NonLocalClauseGuardVariable { location, name }) 3037 + return Err(Error::NonLocalClauseGuardVariable { location, name }); 3033 3038 } 3034 3039 3035 3040 // TODO: remove this clone. Could be an rc instead 3036 3041 ValueConstructorVariant::ModuleConstant { literal, .. } 3037 3042 | ValueConstructorVariant::LocalConstant { literal } => { 3038 - return Ok(literal.clone()) 3043 + return Ok(literal.clone()); 3039 3044 } 3040 3045 }; 3041 3046 ··· 3225 3230 // Type annotation and inferred value are valid. Ensure they are unifiable. 3226 3231 // NOTE: if the types are not unifiable we use the annotated type. 3227 3232 (Some(Ok(const_ann)), Ok(inferred)) => { 3228 - if let Err(e) = unify(const_ann.clone(), inferred.type_()) 3233 + match unify(const_ann.clone(), inferred.type_()) 3229 3234 .map_err(|e| convert_unify_error(e, inferred.location())) 3230 3235 { 3231 - self.problems.error(e); 3232 - Constant::Invalid { 3233 - location: loc, 3234 - type_: const_ann, 3236 + Err(e) => { 3237 + self.problems.error(e); 3238 + Constant::Invalid { 3239 + location: loc, 3240 + type_: const_ann, 3241 + } 3235 3242 } 3236 - } else { 3237 - inferred 3243 + _ => inferred, 3238 3244 } 3239 3245 } 3240 3246 // Type annotation is valid but not the inferred value. Place a placeholder constant with the annotation type. ··· 3427 3433 } 3428 3434 }); 3429 3435 if let Err(e) = field_map { 3430 - if let Error::IncorrectArity { 3431 - expected, 3432 - given, 3433 - labels, 3434 - location, 3435 - } = e 3436 - { 3437 - labelled_arity_error = true; 3438 - self.problems.error(Error::IncorrectArity { 3436 + match e { 3437 + Error::IncorrectArity { 3439 3438 expected, 3440 3439 given, 3441 3440 labels, 3442 3441 location, 3443 - }); 3444 - } else { 3445 - self.problems.error(e); 3442 + } => { 3443 + labelled_arity_error = true; 3444 + self.problems.error(Error::IncorrectArity { 3445 + expected, 3446 + given, 3447 + labels, 3448 + location, 3449 + }); 3450 + } 3451 + _ => { 3452 + self.problems.error(e); 3453 + } 3446 3454 } 3447 3455 } 3448 3456
+16 -11
compiler-core/src/type_/pattern.rs
··· 8 8 /// 9 9 use super::*; 10 10 use crate::{ 11 - analyse::{name::check_name_case, Inferred}, 11 + analyse::{Inferred, name::check_name_case}, 12 12 ast::{ 13 13 AssignName, BitArrayOption, ImplicitCallArgOrigin, Layer, UntypedPatternBitArraySegment, 14 14 }, ··· 464 464 } 465 465 466 466 // The right hand side may assign a variable, which is the suffix of the string 467 - if let AssignName::Variable(right) = &right_side_assignment { 468 - self.insert_variable( 469 - right.as_ref(), 470 - string(), 471 - right_location, 472 - VariableOrigin::Variable(right.clone()), 473 - ) 474 - .map_err(|e| convert_unify_error(e, location))?; 475 - } else if let AssignName::Discard(right) = &right_side_assignment { 476 - self.check_name_case(right_location, right, Named::Discard); 467 + match &right_side_assignment { 468 + AssignName::Variable(right) => { 469 + self.insert_variable( 470 + right.as_ref(), 471 + string(), 472 + right_location, 473 + VariableOrigin::Variable(right.clone()), 474 + ) 475 + .map_err(|e| convert_unify_error(e, location))?; 476 + } 477 + AssignName::Discard(_) => { 478 + if let AssignName::Discard(right) = &right_side_assignment { 479 + self.check_name_case(right_location, right, Named::Discard); 480 + } 481 + } 477 482 }; 478 483 479 484 Ok(Pattern::StringPrefix {
+2 -2
compiler-core/src/type_/pipe.rs
··· 2 2 3 3 use super::*; 4 4 use crate::ast::{ 5 - FunctionLiteralKind, ImplicitCallArgOrigin, PipelineAssignmentKind, Statement, 6 - TypedPipelineAssignment, UntypedExpr, PIPE_VARIABLE, 5 + FunctionLiteralKind, ImplicitCallArgOrigin, PIPE_VARIABLE, PipelineAssignmentKind, Statement, 6 + TypedPipelineAssignment, UntypedExpr, 7 7 }; 8 8 use vec1::Vec1; 9 9
+2 -2
compiler-core/src/type_/pretty.rs
··· 97 97 98 98 fn type_var_doc<'a>(&mut self, type_: &TypeVar) -> Document<'a> { 99 99 match type_ { 100 - TypeVar::Link { ref type_, .. } => self.print(type_), 100 + TypeVar::Link { type_, .. } => self.print(type_), 101 101 TypeVar::Unbound { id, .. } | TypeVar::Generic { id, .. } => self.generic_type_var(*id), 102 102 } 103 103 } ··· 246 246 #[test] 247 247 fn pretty_print_test() { 248 248 macro_rules! assert_string { 249 - ($src:expr, $type_:expr $(,)?) => { 249 + ($src:expr_2021, $type_:expr_2021 $(,)?) => { 250 250 let mut printer = Printer::new(); 251 251 assert_eq!($type_.to_string(), printer.pretty_print(&$src, 0),); 252 252 };
+4 -5
compiler-core/src/type_/printer.rs
··· 1 1 use bimap::BiMap; 2 - use ecow::{eco_format, EcoString}; 2 + use ecow::{EcoString, eco_format}; 3 3 use im::HashMap; 4 4 use std::{collections::HashSet, sync::Arc}; 5 5 ··· 321 321 } 322 322 323 323 pub fn print_module(&self, module: &str) -> EcoString { 324 - if let Some(module) = self.names.imported_modules.get(module) { 325 - module.clone() 326 - } else { 327 - module.split("/").last().unwrap_or(module).into() 324 + match self.names.imported_modules.get(module) { 325 + Some(module) => module.clone(), 326 + _ => module.split("/").last().unwrap_or(module).into(), 328 327 } 329 328 } 330 329
+27 -27
compiler-core/src/type_/tests.rs
··· 38 38 39 39 #[macro_export] 40 40 macro_rules! assert_infer { 41 - ($src:expr, $type_:expr $(,)?) => { 41 + ($src:expr_2021, $type_:expr_2021 $(,)?) => { 42 42 let t = $crate::type_::tests::infer($src); 43 43 assert_eq!(($src, t), ($src, $type_.to_string()),); 44 44 }; ··· 47 47 #[macro_export] 48 48 macro_rules! assert_infer_with_module { 49 49 ( 50 - ($name1:expr, $module_src1:literal), 51 - ($name2:expr, $module_src2:literal), 52 - $src:expr, $module:expr $(,)? 50 + ($name1:expr_2021, $module_src1:literal), 51 + ($name2:expr_2021, $module_src2:literal), 52 + $src:expr_2021, $module:expr_2021 $(,)? 53 53 ) => { 54 54 let constructors = $crate::type_::tests::infer_module( 55 55 $src, ··· 62 62 63 63 assert_eq!(($src, constructors), ($src, expected)); 64 64 }; 65 - (($name:expr, $module_src:literal), $src:expr, $module:expr $(,)?) => { 65 + (($name:expr_2021, $module_src:literal), $src:expr_2021, $module:expr_2021 $(,)?) => { 66 66 let constructors = 67 67 $crate::type_::tests::infer_module($src, vec![("thepackage", $name, $module_src)]); 68 68 let expected = $crate::type_::tests::stringify_tuple_strs($module); ··· 73 73 74 74 #[macro_export] 75 75 macro_rules! assert_module_infer { 76 - ($src:expr, $module:expr $(,)?) => {{ 76 + ($src:expr_2021, $module:expr_2021 $(,)?) => {{ 77 77 let constructors = $crate::type_::tests::infer_module($src, vec![]); 78 78 let expected = $crate::type_::tests::stringify_tuple_strs($module); 79 79 assert_eq!(($src, constructors), ($src, expected)); ··· 82 82 83 83 #[macro_export] 84 84 macro_rules! assert_js_module_infer { 85 - ($src:expr, $module:expr $(,)?) => {{ 85 + ($src:expr_2021, $module:expr_2021 $(,)?) => {{ 86 86 let constructors = $crate::type_::tests::infer_module_with_target( 87 87 "test_module", 88 88 $src, ··· 96 96 97 97 #[macro_export] 98 98 macro_rules! assert_module_error { 99 - ($src:expr) => { 99 + ($src:expr_2021) => { 100 100 let error = $crate::type_::tests::module_error($src, vec![]); 101 101 let output = format!("----- SOURCE CODE\n{}\n\n----- ERROR\n{}", $src, error); 102 102 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 105 105 106 106 #[macro_export] 107 107 macro_rules! assert_internal_module_error { 108 - ($src:expr) => { 108 + ($src:expr_2021) => { 109 109 let error = $crate::type_::tests::internal_module_error($src, vec![]); 110 110 let output = format!("----- SOURCE CODE\n{}\n\n----- ERROR\n{}", $src, error); 111 111 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 114 114 115 115 #[macro_export] 116 116 macro_rules! assert_js_module_error { 117 - ($src:expr) => { 117 + ($src:expr_2021) => { 118 118 let error = $crate::type_::tests::module_error_with_target( 119 119 $src, 120 120 vec![], ··· 127 127 128 128 #[macro_export] 129 129 macro_rules! assert_module_syntax_error { 130 - ($src:expr) => { 130 + ($src:expr_2021) => { 131 131 let error = $crate::type_::tests::syntax_error($src); 132 132 let output = format!("----- SOURCE CODE\n{}\n\n----- ERROR\n{}", $src, error); 133 133 insta::assert_snapshot!(insta::internals::AutoName, output, $src); ··· 136 136 137 137 #[macro_export] 138 138 macro_rules! assert_error { 139 - ($src:expr, $error:expr $(,)?) => { 139 + ($src:expr_2021, $error:expr_2021 $(,)?) => { 140 140 let result = $crate::type_::tests::compile_statement_sequence($src) 141 141 .expect_err("should infer an error"); 142 142 assert_eq!(($src, sort_options($error)), ($src, sort_options(result)),); 143 143 }; 144 144 145 - ($src:expr) => { 145 + ($src:expr_2021) => { 146 146 let (error, names) = $crate::type_::tests::compile_statement_sequence($src) 147 147 .expect_err("should infer an error"); 148 148 let error = $crate::error::Error::Type { ··· 162 162 163 163 #[macro_export] 164 164 macro_rules! assert_with_module_error { 165 - (($name:expr, $module_src:literal), $src:expr $(,)?) => { 165 + (($name:expr_2021, $module_src:literal), $src:expr_2021 $(,)?) => { 166 166 let error = 167 167 $crate::type_::tests::module_error($src, vec![("thepackage", $name, $module_src)]); 168 168 let output = format!( ··· 181 181 }; 182 182 183 183 ( 184 - ($name:expr, $module_src:literal), 185 - ($name2:expr, $module_src2:literal), 186 - $src:expr $(,)? 184 + ($name:expr_2021, $module_src:literal), 185 + ($name2:expr_2021, $module_src2:literal), 186 + $src:expr_2021 $(,)? 187 187 ) => { 188 188 let error = $crate::type_::tests::module_error( 189 189 $src, ··· 271 271 272 272 #[macro_export] 273 273 macro_rules! assert_warning { 274 - ($src:expr) => { 274 + ($src:expr_2021) => { 275 275 let warning = $crate::type_::tests::get_printed_warnings($src, vec![], crate::build::Target::Erlang, None); 276 276 assert!(!warning.is_empty()); 277 277 let output = format!("----- SOURCE CODE\n{}\n\n----- WARNING\n{}", $src, warning); 278 278 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 279 279 }; 280 280 281 - ($(($name:expr, $module_src:literal)),+, $src:expr) => { 281 + ($(($name:expr_2021, $module_src:literal)),+, $src:expr_2021) => { 282 282 let warning = $crate::type_::tests::get_printed_warnings( 283 283 $src, 284 284 vec![$(("thepackage", $name, $module_src)),*], ··· 290 290 insta::assert_snapshot!(insta::internals::AutoName, output, $src); 291 291 }; 292 292 293 - ($(($package:expr, $name:expr, $module_src:literal)),+, $src:expr) => { 293 + ($(($package:expr_2021, $name:expr_2021, $module_src:literal)),+, $src:expr_2021) => { 294 294 let warning = $crate::type_::tests::get_printed_warnings( 295 295 $src, 296 296 vec![$(($package, $name, $module_src)),*], ··· 305 305 306 306 #[macro_export] 307 307 macro_rules! assert_js_warning { 308 - ($src:expr) => { 308 + ($src:expr_2021) => { 309 309 let warning = $crate::type_::tests::get_printed_warnings( 310 310 $src, 311 311 vec![], ··· 320 320 321 321 #[macro_export] 322 322 macro_rules! assert_js_no_warnings { 323 - ($src:expr) => { 323 + ($src:expr_2021) => { 324 324 let warning = $crate::type_::tests::get_printed_warnings( 325 325 $src, 326 326 vec![], ··· 333 333 334 334 #[macro_export] 335 335 macro_rules! assert_warnings_with_gleam_version { 336 - ($gleam_version:expr, $src:expr$(,)?) => { 336 + ($gleam_version:expr_2021, $src:expr_2021$(,)?) => { 337 337 let warning = $crate::type_::tests::get_printed_warnings( 338 338 $src, 339 339 vec![], ··· 348 348 349 349 #[macro_export] 350 350 macro_rules! assert_js_warnings_with_gleam_version { 351 - ($gleam_version:expr, $src:expr$(,)?) => { 351 + ($gleam_version:expr_2021, $src:expr_2021$(,)?) => { 352 352 let warning = $crate::type_::tests::get_printed_warnings( 353 353 $src, 354 354 vec![], ··· 363 363 364 364 #[macro_export] 365 365 macro_rules! assert_js_no_warnings_with_gleam_version { 366 - ($gleam_version:expr, $src:expr$(,)?) => { 366 + ($gleam_version:expr_2021, $src:expr_2021$(,)?) => { 367 367 let warning = $crate::type_::tests::get_printed_warnings( 368 368 $src, 369 369 vec![], ··· 376 376 377 377 #[macro_export] 378 378 macro_rules! assert_no_warnings { 379 - ($src:expr $(,)?) => { 379 + ($src:expr_2021 $(,)?) => { 380 380 let warnings = $crate::type_::tests::get_warnings($src, vec![], crate::build::Target::Erlang, None); 381 381 assert_eq!(warnings, vec![]); 382 382 }; 383 - ($(($package:expr, $name:expr, $module_src:literal)),+, $src:expr $(,)?) => { 383 + ($(($package:expr_2021, $name:expr_2021, $module_src:literal)),+, $src:expr_2021 $(,)?) => { 384 384 let warnings = $crate::type_::tests::get_warnings( 385 385 $src, 386 386 vec![$(($package, $name, $module_src)),*],
+1 -1
compiler-core/src/type_/tests/pretty.rs
··· 1 1 use std::sync::Arc; 2 2 3 3 use crate::type_::{ 4 + Type, 4 5 prelude::{bool, int, tuple}, 5 6 pretty::Printer, 6 - Type, 7 7 }; 8 8 9 9 use super::Publicity;
+1 -1
compiler-core/src/type_/tests/target_implementations.rs
··· 8 8 use super::compile_module_with_opts; 9 9 10 10 macro_rules! assert_targets { 11 - ($src:expr, $implementations:expr $(,)?) => { 11 + ($src:expr_2021, $implementations:expr_2021 $(,)?) => { 12 12 let result = $crate::type_::tests::target_implementations::implementations($src); 13 13 let expected = $implementations 14 14 .iter()
+1 -1
compiler-core/src/uid.rs
··· 1 1 use std::sync::{ 2 - atomic::{AtomicU64, Ordering}, 3 2 Arc, 3 + atomic::{AtomicU64, Ordering}, 4 4 }; 5 5 6 6 /// A generator of unique ids. Only one should be used per compilation run to
+10 -7
compiler-core/src/warning.rs
··· 17 17 use ecow::EcoString; 18 18 use std::{ 19 19 io::Write, 20 - sync::{atomic::Ordering, Arc}, 20 + sync::{Arc, atomic::Ordering}, 21 21 }; 22 22 use std::{rc::Rc, sync::atomic::AtomicUsize}; 23 23 use termcolor::Buffer; ··· 1002 1002 panic_position: unreachable_code_kind, 1003 1003 } => { 1004 1004 let text = match unreachable_code_kind { 1005 - PanicPosition::PreviousExpression => 1006 - "This code is unreachable because it comes after a `panic`.", 1007 - PanicPosition::PreviousFunctionArgument => 1005 + PanicPosition::PreviousExpression => { 1006 + "This code is unreachable because it comes after a `panic`." 1007 + } 1008 + PanicPosition::PreviousFunctionArgument => { 1008 1009 "This argument is unreachable because the previous one always panics. \ 1009 - Your code will crash before reaching this point.", 1010 - PanicPosition::LastFunctionArgument => 1010 + Your code will crash before reaching this point." 1011 + } 1012 + PanicPosition::LastFunctionArgument => { 1011 1013 "This function call is unreachable because its last argument always panics. \ 1012 - Your code will crash before reaching this point.", 1014 + Your code will crash before reaching this point." 1015 + } 1013 1016 }; 1014 1017 1015 1018 Diagnostic {
+1 -1
compiler-wasm/Cargo.toml
··· 2 2 name = "gleam-wasm" 3 3 version = "1.8.1" 4 4 authors = ["Louis Pilfold <louis@lpil.uk>"] 5 - edition = "2021" 5 + edition = "2024" 6 6 license-file = "LICENCE" 7 7 8 8 [lib]
+1 -1
compiler-wasm/src/lib.rs
··· 5 5 6 6 use camino::Utf8PathBuf; 7 7 use gleam_core::{ 8 + Error, 8 9 analyse::TargetSupport, 9 10 build::{ 10 11 Mode, NullTelemetry, PackageCompiler, StaleTracker, Target, TargetCodegenConfiguration, ··· 13 14 io::{FileSystemReader, FileSystemWriter}, 14 15 uid::UniqueIdGenerator, 15 16 warning::{VectorWarningEmitterIO, WarningEmitter}, 16 - Error, 17 17 }; 18 18 use hexpm::version::Version; 19 19 use im::HashMap;
+5 -3
compiler-wasm/src/tests.rs
··· 87 87 "#, 88 88 ); 89 89 90 - assert!(compile_package(0, "javascript") 91 - .unwrap_err() 92 - .contains("Unsupported feature for compilation target")); 90 + assert!( 91 + compile_package(0, "javascript") 92 + .unwrap_err() 93 + .contains("Unsupported feature for compilation target") 94 + ); 93 95 } 94 96 95 97 #[wasm_bindgen_test]
+3 -3
compiler-wasm/src/wasm_filesystem.rs
··· 1 1 use camino::{Utf8Path, Utf8PathBuf}; 2 2 use gleam_core::{ 3 + Error, Result, 3 4 io::{ 4 - memory::InMemoryFileSystem, BeamCompiler, Command, CommandExecutor, FileSystemReader, 5 - FileSystemWriter, ReadDir, Stdio, WrappedReader, 5 + BeamCompiler, Command, CommandExecutor, FileSystemReader, FileSystemWriter, ReadDir, Stdio, 6 + WrappedReader, memory::InMemoryFileSystem, 6 7 }, 7 - Error, Result, 8 8 }; 9 9 use std::collections::HashSet; 10 10
+1 -1
test-helpers-rs/Cargo.toml
··· 1 1 [package] 2 2 name = "test-helpers-rs" 3 3 version = "0.1.0" 4 - edition = "2021" 4 + edition = "2024" 5 5 license = "Apache-2.0" 6 6 7 7 [dependencies]
+1 -1
test-helpers-rs/src/lib.rs
··· 1 1 use camino::{Utf8Path, Utf8PathBuf}; 2 2 use gleam_core::{ 3 - io::{memory::InMemoryFileSystem, Content, FileSystemWriter}, 3 + io::{Content, FileSystemWriter, memory::InMemoryFileSystem}, 4 4 version::COMPILER_VERSION, 5 5 }; 6 6 use itertools::Itertools;
+1 -1
test-package-compiler/Cargo.toml
··· 2 2 name = "test-package-compiler" 3 3 version = "1.8.1" 4 4 authors = ["Louis Pilfold <louis@lpil.uk>"] 5 - edition = "2021" 5 + edition = "2024" 6 6 license = "Apache-2.0" 7 7 8 8 [dependencies]
+1 -1
test-project-compiler/Cargo.toml
··· 2 2 name = "test-project-compiler" 3 3 version = "1.8.1" 4 4 authors = ["Louis Pilfold <louis@lpil.uk>"] 5 - edition = "2021" 5 + edition = "2024" 6 6 license = "Apache-2.0" 7 7 8 8 [dependencies]