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

Configure Feed

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

allow unannotated constant float segments in bit arrays

+277 -53
+30
compiler-core/src/ast.rs
··· 2231 2231 } 2232 2232 } 2233 2233 2234 + impl<Value, Type> BitArraySegment<Value, Type> { 2235 + #[must_use] 2236 + pub(crate) fn has_type_option(&self) -> bool { 2237 + self.options.iter().any(|option| option.is_type_option()) 2238 + } 2239 + } 2240 + 2234 2241 impl TypedExprBitArraySegment { 2235 2242 pub fn find_node(&self, byte_index: u32) -> Option<Located<'_>> { 2236 2243 self.value.find_node(byte_index) ··· 2372 2379 BitArrayOption::Native { .. } => "native".into(), 2373 2380 BitArrayOption::Size { .. } => "size".into(), 2374 2381 BitArrayOption::Unit { .. } => "unit".into(), 2382 + } 2383 + } 2384 + 2385 + fn is_type_option(&self) -> bool { 2386 + match self { 2387 + BitArrayOption::Bytes { .. } 2388 + | BitArrayOption::Int { .. } 2389 + | BitArrayOption::Float { .. } 2390 + | BitArrayOption::Bits { .. } 2391 + | BitArrayOption::Utf8 { .. } 2392 + | BitArrayOption::Utf16 { .. } 2393 + | BitArrayOption::Utf32 { .. } 2394 + | BitArrayOption::Utf8Codepoint { .. } 2395 + | BitArrayOption::Utf16Codepoint { .. } 2396 + | BitArrayOption::Utf32Codepoint { .. } => true, 2397 + 2398 + BitArrayOption::Signed { .. } 2399 + | BitArrayOption::Unsigned { .. } 2400 + | BitArrayOption::Big { .. } 2401 + | BitArrayOption::Little { .. } 2402 + | BitArrayOption::Native { .. } 2403 + | BitArrayOption::Size { .. } 2404 + | BitArrayOption::Unit { .. } => false, 2375 2405 } 2376 2406 } 2377 2407 }
+2
compiler-core/src/type_/error.rs
··· 930 930 ConstantStringConcatenation, 931 931 ArithmeticInGuards, 932 932 UnannotatedUtf8StringSegment, 933 + UnannotatedFloatSegment, 933 934 NestedTupleAccess, 934 935 InternalAnnotation, 935 936 AtInJavascriptModules, ··· 965 966 } 966 967 967 968 FeatureKind::JavaScriptUnalignedBitArray => Version::new(1, 9, 0), 969 + FeatureKind::UnannotatedFloatSegment => Version::new(1, 10, 0), 968 970 } 969 971 } 970 972 }
+72 -28
compiler-core/src/type_/expression.rs
··· 1204 1204 ) -> Result<TypedExpr, Error> { 1205 1205 let segments = segments 1206 1206 .into_iter() 1207 - .map(|s| { 1208 - let options = match s.value.as_ref() { 1209 - UntypedExpr::String { location, .. } if s.options.is_empty() => { 1210 - self.track_feature_usage( 1211 - FeatureKind::UnannotatedUtf8StringSegment, 1212 - *location, 1213 - ); 1214 - vec![BitArrayOption::Utf8 { 1215 - location: SrcSpan::default(), 1216 - }] 1207 + .map(|mut segment| { 1208 + // If the segment doesn't have an explicit type option we add a default 1209 + // one ourselves if the pattern is unambiguous: literal strings are 1210 + // implicitly considered utf-8 encoded strings, while floats are 1211 + // implicitly given the float type option. 1212 + if !segment.has_type_option() { 1213 + match segment.value.as_ref() { 1214 + UntypedExpr::String { location, .. } => { 1215 + self.track_feature_usage( 1216 + FeatureKind::UnannotatedUtf8StringSegment, 1217 + *location, 1218 + ); 1219 + segment.options.push(BitArrayOption::Utf8 { 1220 + location: SrcSpan::default(), 1221 + }); 1222 + } 1223 + 1224 + UntypedExpr::Float { location, .. } => { 1225 + self.track_feature_usage( 1226 + FeatureKind::UnannotatedFloatSegment, 1227 + *location, 1228 + ); 1229 + segment.options.push(BitArrayOption::Float { 1230 + location: SrcSpan::default(), 1231 + }) 1232 + } 1233 + 1234 + _ => (), 1217 1235 } 1218 - _ => s.options, 1219 - }; 1220 - self.infer_bit_segment(*s.value, options, s.location, |env, expr| env.infer(expr)) 1236 + } 1237 + 1238 + self.infer_bit_segment( 1239 + *segment.value, 1240 + segment.options, 1241 + segment.location, 1242 + |env, expr| env.infer(expr), 1243 + ) 1221 1244 }) 1222 1245 .try_collect()?; 1223 1246 ··· 1235 1258 ) -> Result<TypedConstant, Error> { 1236 1259 let segments = segments 1237 1260 .into_iter() 1238 - .map(|s| { 1239 - let options = match s.value.as_ref() { 1240 - Constant::String { location, .. } if s.options.is_empty() => { 1241 - self.track_feature_usage( 1242 - FeatureKind::UnannotatedUtf8StringSegment, 1243 - *location, 1244 - ); 1245 - vec![BitArrayOption::Utf8 { 1246 - location: SrcSpan::default(), 1247 - }] 1261 + .map(|mut segment| { 1262 + // If the segment doesn't have an explicit type option we add a default 1263 + // one ourselves if the pattern is unambiguous: literal strings are 1264 + // implicitly considered utf-8 encoded strings, while floats are 1265 + // implicitly given the float type option. 1266 + if !segment.has_type_option() { 1267 + match segment.value.as_ref() { 1268 + Constant::String { location, .. } => { 1269 + self.track_feature_usage( 1270 + FeatureKind::UnannotatedUtf8StringSegment, 1271 + *location, 1272 + ); 1273 + segment.options.push(BitArrayOption::Utf8 { 1274 + location: SrcSpan::default(), 1275 + }); 1276 + } 1277 + 1278 + Constant::Float { location, .. } => { 1279 + self.track_feature_usage( 1280 + FeatureKind::UnannotatedFloatSegment, 1281 + *location, 1282 + ); 1283 + segment.options.push(BitArrayOption::Float { 1284 + location: SrcSpan::default(), 1285 + }) 1286 + } 1287 + 1288 + _ => (), 1248 1289 } 1249 - _ => s.options, 1250 - }; 1251 - self.infer_bit_segment(*s.value, options, s.location, |env, expr| { 1252 - Ok(env.infer_const(&None, expr)) 1253 - }) 1290 + } 1291 + 1292 + self.infer_bit_segment( 1293 + *segment.value, 1294 + segment.options, 1295 + segment.location, 1296 + |env, expr| Ok(env.infer_const(&None, expr)), 1297 + ) 1254 1298 }) 1255 1299 .try_collect()?; 1256 1300
+28 -20
compiler-core/src/type_/pattern.rs
··· 261 261 262 262 fn infer_pattern_segment( 263 263 &mut self, 264 - segment: UntypedPatternBitArraySegment, 264 + mut segment: UntypedPatternBitArraySegment, 265 265 is_last_segment: bool, 266 266 ) -> Result<TypedPatternBitArraySegment, Error> { 267 - let UntypedPatternBitArraySegment { 268 - location, 269 - options, 270 - value, 271 - .. 272 - } = segment; 267 + // If the segment doesn't have an explicit type option we add a default 268 + // one ourselves if the pattern is unambiguous: literal strings are 269 + // implicitly considered utf-8 encoded strings, while floats are 270 + // implicitly given the float type option. 271 + if !segment.has_type_option() { 272 + match segment.value.as_ref() { 273 + Pattern::String { location, .. } => { 274 + self.track_feature_usage(FeatureKind::UnannotatedUtf8StringSegment, *location); 275 + segment.options.push(BitArrayOption::Utf8 { 276 + location: SrcSpan::default(), 277 + }); 278 + } 273 279 274 - let options = match value.as_ref() { 275 - Pattern::String { location, .. } if options.is_empty() => { 276 - self.track_feature_usage(FeatureKind::UnannotatedUtf8StringSegment, *location); 277 - vec![BitArrayOption::Utf8 { 278 - location: SrcSpan::default(), 279 - }] 280 + Pattern::Float { location, .. } => { 281 + self.track_feature_usage(FeatureKind::UnannotatedFloatSegment, *location); 282 + segment.options.push(BitArrayOption::Float { 283 + location: SrcSpan::default(), 284 + }) 285 + } 286 + 287 + _ => (), 280 288 } 281 - _ => options, 282 - }; 289 + } 283 290 284 - let options: Vec<_> = options 291 + let options: Vec<_> = segment 292 + .options 285 293 .into_iter() 286 294 .map(|o| { 287 295 crate::analyse::infer_bit_array_option(o, |value, type_| { ··· 334 342 } 335 343 336 344 let type_ = { 337 - match value.deref() { 345 + match segment.value.deref() { 338 346 Pattern::Variable { .. } if segment_type == string() => { 339 347 Err(Error::BitArraySegmentError { 340 348 error: bit_array::ErrorType::VariableUtfSegmentInPattern, 341 - location, 349 + location: segment.location, 342 350 }) 343 351 } 344 352 _ => Ok(segment_type), 345 353 } 346 354 }?; 347 - let typed_value = self.unify(*value, type_.clone(), None)?; 355 + let typed_value = self.unify(*segment.value, type_.clone(), None)?; 348 356 349 357 Ok(BitArraySegment { 350 - location, 358 + location: segment.location, 351 359 value: Box::new(typed_value), 352 360 options, 353 361 type_,
-5
compiler-core/src/type_/tests/errors.rs
··· 30 30 } 31 31 32 32 #[test] 33 - fn bit_array() { 34 - assert_error!("case <<1>> { <<2.0, a>> -> 1 _ -> 2 }"); 35 - } 36 - 37 - #[test] 38 33 fn bit_array_float() { 39 34 assert_error!("case <<1>> { <<a:float>> if a > 1 -> 1 _ -> 2 }"); 40 35 }
+21
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__missing_float_option_in_bit_array_constant_segment_requires_v1_10.snap
··· 1 + --- 2 + source: compiler-core/src/type_/tests/warnings.rs 3 + expression: pub const bits = <<1.2>> 4 + --- 5 + ----- SOURCE CODE 6 + pub const bits = <<1.2>> 7 + 8 + ----- WARNING 9 + warning: Incompatible gleam version range 10 + ┌─ /src/warning/wrn.gleam:1:20 11 + 12 + 1 │ pub const bits = <<1.2>> 13 + │ ^^^ This requires a Gleam version >= 1.10.0 14 + 15 + The ability to omit the `float` annotation for segments was introduced in 16 + version v1.10.0. But the Gleam version range specified in your `gleam.toml` 17 + would allow this code to run on an earlier version like v1.0.0, resulting 18 + in compilation errors! 19 + Hint: Remove the version constraint from your `gleam.toml` or update it to be: 20 + 21 + gleam = ">= 1.10.0"
+28
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__missing_float_option_in_bit_array_pattern_segment_requires_v1_10.snap
··· 1 + --- 2 + source: compiler-core/src/type_/tests/warnings.rs 3 + expression: "\npub fn main(a) {\n case a {\n <<1.2>> -> Nil\n _ -> Nil\n }\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + 7 + pub fn main(a) { 8 + case a { 9 + <<1.2>> -> Nil 10 + _ -> Nil 11 + } 12 + } 13 + 14 + 15 + ----- WARNING 16 + warning: Incompatible gleam version range 17 + ┌─ /src/warning/wrn.gleam:4:7 18 + 19 + 4 │ <<1.2>> -> Nil 20 + │ ^^^ This requires a Gleam version >= 1.10.0 21 + 22 + The ability to omit the `float` annotation for segments was introduced in 23 + version v1.10.0. But the Gleam version range specified in your `gleam.toml` 24 + would allow this code to run on an earlier version like v1.0.0, resulting 25 + in compilation errors! 26 + Hint: Remove the version constraint from your `gleam.toml` or update it to be: 27 + 28 + gleam = ">= 1.10.0"
+25
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__missing_float_option_in_bit_array_segment_requires_v1_10.snap
··· 1 + --- 2 + source: compiler-core/src/type_/tests/warnings.rs 3 + expression: "\npub fn main() {\n <<1.2>>\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + 7 + pub fn main() { 8 + <<1.2>> 9 + } 10 + 11 + 12 + ----- WARNING 13 + warning: Incompatible gleam version range 14 + ┌─ /src/warning/wrn.gleam:3:5 15 + 16 + 3 │ <<1.2>> 17 + │ ^^^ This requires a Gleam version >= 1.10.0 18 + 19 + The ability to omit the `float` annotation for segments was introduced in 20 + version v1.10.0. But the Gleam version range specified in your `gleam.toml` 21 + would allow this code to run on an earlier version like v1.0.0, resulting 22 + in compilation errors! 23 + Hint: Remove the version constraint from your `gleam.toml` or update it to be: 24 + 25 + gleam = ">= 1.10.0"
+33
compiler-core/src/type_/tests/version_inference.rs
··· 300 300 } 301 301 302 302 #[test] 303 + fn missing_float_option_in_bit_array_segment_requires_v1_10() { 304 + let version = infer_version( 305 + " 306 + pub fn main() { 307 + <<1.2>> 308 + } 309 + ", 310 + ); 311 + assert_eq!(version, Version::new(1, 10, 0)); 312 + } 313 + 314 + #[test] 315 + fn missing_float_option_in_bit_array_constant_segment_requires_v1_10() { 316 + let version = infer_version("const bits = <<1.2>>"); 317 + assert_eq!(version, Version::new(1, 10, 0)); 318 + } 319 + 320 + #[test] 321 + fn missing_float_option_in_bit_array_pattern_segment_requires_v1_10() { 322 + let version = infer_version( 323 + " 324 + pub fn main() { 325 + case todo { 326 + <<1.11>> -> todo 327 + _ -> todo 328 + } 329 + } 330 + ", 331 + ); 332 + assert_eq!(version, Version::new(1, 10, 0)); 333 + } 334 + 335 + #[test] 303 336 fn inference_picks_the_bigger_of_two_versions() { 304 337 let version = infer_version( 305 338 "
+35
compiler-core/src/type_/tests/warnings.rs
··· 2480 2480 } 2481 2481 2482 2482 #[test] 2483 + fn missing_float_option_in_bit_array_segment_requires_v1_10() { 2484 + assert_warnings_with_gleam_version!( 2485 + Range::higher_than(Version::new(1, 0, 0)), 2486 + " 2487 + pub fn main() { 2488 + <<1.2>> 2489 + } 2490 + ", 2491 + ); 2492 + } 2493 + 2494 + #[test] 2495 + fn missing_float_option_in_bit_array_constant_segment_requires_v1_10() { 2496 + assert_warnings_with_gleam_version!( 2497 + Range::higher_than(Version::new(1, 0, 0)), 2498 + "pub const bits = <<1.2>>" 2499 + ); 2500 + } 2501 + 2502 + #[test] 2503 + fn missing_float_option_in_bit_array_pattern_segment_requires_v1_10() { 2504 + assert_warnings_with_gleam_version!( 2505 + Range::higher_than(Version::new(1, 0, 0)), 2506 + " 2507 + pub fn main(a) { 2508 + case a { 2509 + <<1.2>> -> Nil 2510 + _ -> Nil 2511 + } 2512 + } 2513 + ", 2514 + ); 2515 + } 2516 + 2517 + #[test] 2483 2518 fn record_update_variant_inference_requires_v1_6() { 2484 2519 assert_warnings_with_gleam_version!( 2485 2520 Range::higher_than(Version::new(1, 0, 0)),
+3
compiler-core/src/warning.rs
··· 1092 1092 FeatureKind::UnannotatedUtf8StringSegment => { 1093 1093 "The ability to omit the `utf8` annotation for string segments was" 1094 1094 } 1095 + FeatureKind::UnannotatedFloatSegment => { 1096 + "The ability to omit the `float` annotation for segments was" 1097 + } 1095 1098 FeatureKind::NestedTupleAccess => { 1096 1099 "The ability to access nested tuple fields was" 1097 1100 }