diff --git a/sway-core/src/language/ty/declaration/abi.rs b/sway-core/src/language/ty/declaration/abi.rs index 219d71882de..8a8ba64857b 100644 --- a/sway-core/src/language/ty/declaration/abi.rs +++ b/sway-core/src/language/ty/declaration/abi.rs @@ -1,6 +1,5 @@ use super::{TyDeclParsedType, TyTraitInterfaceItem, TyTraitItem}; use crate::{ - ast_elements::type_parameter::ConstGenericExpr, decl_engine::DeclEngineGet as _, engine_threading::*, language::parsed::{self, AbiDeclaration}, @@ -29,70 +28,6 @@ pub struct TyAbiDecl { pub attributes: transform::Attributes, } -fn has_const_generics(type_id: TypeId, engines: &Engines) -> bool { - let types = type_id.extract_any_including_self(engines, &|_| true, vec![], 0); - - for (t, _) in types { - let t = engines.te().get(t); - match &*t { - TypeInfo::StringArray(length) => match length.expr() { - ConstGenericExpr::Literal { .. } => {} - ConstGenericExpr::AmbiguousVariableExpression { .. } => return true, - }, - TypeInfo::Enum(decl_id) => { - let decl = engines.de().get(decl_id); - let any_const_generics = decl - .generic_parameters - .iter() - .any(|x| x.as_const_parameter().is_some()); - if any_const_generics { - return true; - } - } - TypeInfo::Struct(decl_id) => { - let decl = engines.de().get(decl_id); - let any_const_generics = decl - .generic_parameters - .iter() - .any(|x| x.as_const_parameter().is_some()); - if any_const_generics { - return true; - } - - for field in decl.fields.iter() { - let any_const_generics = - has_const_generics(field.type_argument.type_id, engines); - if any_const_generics { - return true; - } - } - } - TypeInfo::Tuple(items) => { - for item in items { - let any_const_generics = has_const_generics(item.type_id, engines); - if any_const_generics { - return true; - } - } - } - TypeInfo::Array(item, length) => { - let any_const_generics = has_const_generics(item.type_id, engines); - if any_const_generics { - return true; - } - - match length.expr() { - ConstGenericExpr::Literal { .. } => {} - ConstGenericExpr::AmbiguousVariableExpression { .. } => return true, - } - } - _ => {} - } - } - - false -} - impl TyAbiDecl { pub(crate) fn forbid_const_generics( &self, @@ -104,7 +39,7 @@ impl TyAbiDecl { TyTraitInterfaceItem::TraitFn(decl_ref) => { let decl = engines.de().get(decl_ref.id()); - if has_const_generics(decl.return_type.type_id, engines) { + if decl.return_type.type_id.has_const_generics(engines) { let err = handler.emit_err(CompileError::ConstGenericNotSupportedHere { span: decl.return_type.span(), }); @@ -112,7 +47,7 @@ impl TyAbiDecl { } for arg in decl.parameters.iter() { - if has_const_generics(arg.type_argument.type_id, engines) { + if arg.type_argument.type_id.has_const_generics(engines) { let err = handler.emit_err(CompileError::ConstGenericNotSupportedHere { span: arg.type_argument.span.clone(), @@ -130,7 +65,7 @@ impl TyAbiDecl { match item { TyTraitItem::Fn(decl_ref) => { let decl = engines.de().get(decl_ref.id()); - if has_const_generics(decl.return_type.type_id, engines) { + if decl.return_type.type_id.has_const_generics(engines) { let err = handler.emit_err(CompileError::ConstGenericNotSupportedHere { span: decl.return_type.span(), }); @@ -138,7 +73,7 @@ impl TyAbiDecl { } for arg in decl.parameters.iter() { - if has_const_generics(arg.type_argument.type_id, engines) { + if arg.type_argument.type_id.has_const_generics(engines) { let err = handler.emit_err(CompileError::ConstGenericNotSupportedHere { span: arg.type_argument.span.clone(), diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs b/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs index 691e21842c6..26345d0fe8c 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs @@ -188,6 +188,22 @@ impl ty::TyConfigurableDecl { visibility, }) } + + pub(crate) fn forbid_const_generics( + &self, + handler: &Handler, + engines: &Engines, + ) -> Result<(), ErrorEmitted> { + if self.type_ascription.type_id.has_const_generics(engines) { + Err( + handler.emit_err(CompileError::ConstGenericNotSupportedHere { + span: self.type_ascription.span.clone(), + }), + ) + } else { + Ok(()) + } + } } impl TypeCheckAnalysis for TyConfigurableDecl { diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index ce5aacf5784..8bed1c9eef8 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -120,9 +120,10 @@ impl TyDecl { let name = decl.name.clone(); let typed_const_decl = match ty::TyConfigurableDecl::type_check(handler, ctx.by_ref(), decl) { - Ok(config_decl) => ty::TyDecl::from( - decl_engine.insert(config_decl.clone(), Some(&decl_id)), - ), + Ok(config_decl) => { + config_decl.forbid_const_generics(handler, engines)?; + ty::TyDecl::from(decl_engine.insert(config_decl, Some(&decl_id))) + } Err(err) => ty::TyDecl::ErrorRecovery(span, err), }; ctx.insert_symbol(handler, name, typed_const_decl.clone())?; diff --git a/sway-core/src/type_system/id.rs b/sway-core/src/type_system/id.rs index a87dffab6e1..f4535642fe7 100644 --- a/sway-core/src/type_system/id.rs +++ b/sway-core/src/type_system/id.rs @@ -1484,4 +1484,68 @@ impl TypeId { pub fn get_type_str(&self, engines: &Engines) -> String { engines.te().get(*self).get_type_str(engines) } + + pub fn has_const_generics(&self, engines: &Engines) -> bool { + let types = self.extract_any_including_self(engines, &|_| true, vec![], 0); + + for (t, _) in types { + let t = engines.te().get(t); + match &*t { + TypeInfo::StringArray(length) => match length.expr() { + ConstGenericExpr::Literal { .. } => {} + ConstGenericExpr::AmbiguousVariableExpression { .. } => return true, + }, + TypeInfo::Enum(decl_id) => { + let decl = engines.de().get(decl_id); + let any_const_generics = decl + .generic_parameters + .iter() + .any(|x| x.as_const_parameter().is_some()); + if any_const_generics { + return true; + } + } + TypeInfo::Struct(decl_id) => { + let decl = engines.de().get(decl_id); + let any_const_generics = decl + .generic_parameters + .iter() + .any(|x| x.as_const_parameter().is_some()); + if any_const_generics { + return true; + } + + for field in decl.fields.iter() { + let any_const_generics = + field.type_argument.type_id.has_const_generics(engines); + if any_const_generics { + return true; + } + } + } + TypeInfo::Tuple(items) => { + for item in items { + let any_const_generics = item.type_id.has_const_generics(engines); + if any_const_generics { + return true; + } + } + } + TypeInfo::Array(item, length) => { + let any_const_generics = item.type_id.has_const_generics(engines); + if any_const_generics { + return true; + } + + match length.expr() { + ConstGenericExpr::Literal { .. } => {} + ConstGenericExpr::AmbiguousVariableExpression { .. } => return true, + } + } + _ => {} + } + } + + false + } } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw index 919294c1c05..b566c574e4c 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw @@ -42,6 +42,8 @@ impl A for CrazyEnum { } } +// abi cannot have const generics + abi NoConstGenericsOnArgs { fn f(a: CrazyStruct<1>); } @@ -66,6 +68,12 @@ abi NoConstGenericsIndirectEnum { fn f() -> EnumWithConstGenericInside; } +// configurable cannot have const generics + +configurable { + A: CrazyStruct<1> = CrazyStruct { }, +} + fn main() { let _: CrazyStruct = CrazyStruct { }; let _: CrazyEnum = CrazyEnum::A; diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/stdout.snap index c0acb23ea6b..325ef14c21c 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/stdout.snap @@ -8,14 +8,14 @@ output: Compiling library std (sway-lib-std) Compiling script unsupported_const_generics (test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics) warning - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:62:5 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:64:5 | -60 | -61 | enum EnumWithConstGenericInside { -62 | A: CrazyStruct<1>, +62 | +63 | enum EnumWithConstGenericInside { +64 | A: CrazyStruct<1>, | - Enum variant A is never constructed. -63 | } -64 | +65 | } +66 | | ____ @@ -48,38 +48,38 @@ warning ____ warning - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:53:8 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:55:8 | -51 | } -52 | -53 | struct StructWithConstGenericInside { +53 | } +54 | +55 | struct StructWithConstGenericInside { | ---------------------------- This struct is never used. -54 | a: CrazyStruct<1>, -55 | } +56 | a: CrazyStruct<1>, +57 | } | ____ warning - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:54:5 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:56:5 | -52 | -53 | struct StructWithConstGenericInside { -54 | a: CrazyStruct<1>, +54 | +55 | struct StructWithConstGenericInside { +56 | a: CrazyStruct<1>, | - This struct field is never accessed. -55 | } -56 | +57 | } +58 | | ____ warning - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:61:6 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:63:6 | -59 | } -60 | -61 | enum EnumWithConstGenericInside { +61 | } +62 | +63 | enum EnumWithConstGenericInside { | -------------------------- This enum is never used. -62 | A: CrazyStruct<1>, -63 | } +64 | A: CrazyStruct<1>, +65 | } | ____ @@ -154,6 +154,18 @@ error: Multiple definitions of constant | ____ +error + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:74:8 + | +72 | +73 | configurable { +74 | A: CrazyStruct<1> = CrazyStruct { }, + | ^^^^^^^^^^^^^^ "const generics" are not supported here. +75 | } +76 | + | +____ + error: Multiple definitions of constant --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:24:73 | @@ -228,99 +240,99 @@ error: Multiple definitions of constant ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:46:13 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:48:13 | -44 | -45 | abi NoConstGenericsOnArgs { -46 | fn f(a: CrazyStruct<1>); +46 | +47 | abi NoConstGenericsOnArgs { +48 | fn f(a: CrazyStruct<1>); | ^^^^^^^^^^^^^^ "const generics" are not supported here. -47 | } -48 | +49 | } +50 | | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:50:15 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:52:15 | -48 | -49 | abi NoConstGenericsOnReturn { -50 | fn f() -> CrazyEnum<1>; +50 | +51 | abi NoConstGenericsOnReturn { +52 | fn f() -> CrazyEnum<1>; | ^^^^^^^^^^^^ "const generics" are not supported here. -51 | } -52 | +53 | } +54 | | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:58:15 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:60:15 | -56 | -57 | abi NoConstGenericsIndirectStruct { -58 | fn f() -> StructWithConstGenericInside; +58 | +59 | abi NoConstGenericsIndirectStruct { +60 | fn f() -> StructWithConstGenericInside; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "const generics" are not supported here. -59 | } -60 | +61 | } +62 | | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:66:15 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:68:15 | -64 | -65 | abi NoConstGenericsIndirectEnum { -66 | fn f() -> EnumWithConstGenericInside; +66 | +67 | abi NoConstGenericsIndirectEnum { +68 | fn f() -> EnumWithConstGenericInside; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ "const generics" are not supported here. -67 | } -68 | +69 | } +70 | | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:70:24 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:78:24 | -68 | -69 | fn main() { -70 | let _: CrazyStruct = CrazyStruct { }; +76 | +77 | fn main() { +78 | let _: CrazyStruct = CrazyStruct { }; | ^^^^^^^ Could not find symbol "UNKNOWN" in this scope. -71 | let _: CrazyEnum = CrazyEnum::A; -72 | let _: [u8; UNKNOWN] = [1u8]; +79 | let _: CrazyEnum = CrazyEnum::A; +80 | let _: [u8; UNKNOWN] = [1u8]; | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:71:22 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:79:22 | -69 | fn main() { -70 | let _: CrazyStruct = CrazyStruct { }; -71 | let _: CrazyEnum = CrazyEnum::A; +77 | fn main() { +78 | let _: CrazyStruct = CrazyStruct { }; +79 | let _: CrazyEnum = CrazyEnum::A; | ^^^^^^^ Could not find symbol "UNKNOWN" in this scope. -72 | let _: [u8; UNKNOWN] = [1u8]; -73 | let _: str[UNKNOWN] = __to_str_array("abc"); +80 | let _: [u8; UNKNOWN] = [1u8]; +81 | let _: str[UNKNOWN] = __to_str_array("abc"); | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:72:17 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:80:17 | -70 | let _: CrazyStruct = CrazyStruct { }; -71 | let _: CrazyEnum = CrazyEnum::A; -72 | let _: [u8; UNKNOWN] = [1u8]; +78 | let _: CrazyStruct = CrazyStruct { }; +79 | let _: CrazyEnum = CrazyEnum::A; +80 | let _: [u8; UNKNOWN] = [1u8]; | ^^^^^^^ Could not find symbol "UNKNOWN" in this scope. -73 | let _: str[UNKNOWN] = __to_str_array("abc"); -74 | } +81 | let _: str[UNKNOWN] = __to_str_array("abc"); +82 | } | ____ error - --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:73:16 + --> test/src/e2e_vm_tests/test_programs/should_fail/unsupported_const_generics/src/main.sw:81:16 | -71 | let _: CrazyEnum = CrazyEnum::A; -72 | let _: [u8; UNKNOWN] = [1u8]; -73 | let _: str[UNKNOWN] = __to_str_array("abc"); +79 | let _: CrazyEnum = CrazyEnum::A; +80 | let _: [u8; UNKNOWN] = [1u8]; +81 | let _: str[UNKNOWN] = __to_str_array("abc"); | ^^^^^^^ Could not find symbol "UNKNOWN" in this scope. -74 | } +82 | } | ____ - Aborting due to 22 errors. + Aborting due to 23 errors. error: Failed to compile unsupported_const_generics