From bdfea6d660d7885e866f2506b69b3182e2c51f76 Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Fri, 31 Jan 2025 17:01:23 +0100 Subject: [PATCH 1/8] Added testcase --- .../type_alias_unification/Forc.lock | 13 ++++++++ .../type_alias_unification/Forc.toml | 8 +++++ .../type_alias_unification/src/main.sw | 33 +++++++++++++++++++ .../type_alias_unification/test.toml | 3 ++ 4 files changed, 57 insertions(+) create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.lock new file mode 100644 index 00000000000..1f8113a3e20 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.lock @@ -0,0 +1,13 @@ +[[package]] +name = "core" +source = "path+from-root-6E306998EEBF0DBD" + +[[package]] +name = "std" +source = "path+from-root-6E306998EEBF0DBD" +dependencies = ["core"] + +[[package]] +name = "type_alias_unification" +source = "member" +dependencies = ["std"] diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.toml new file mode 100644 index 00000000000..c3ac933766e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "type_alias_unification" + +[dependencies] +std = { path = "../../../reduced_std_libs/sway-lib-std-assert" } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw new file mode 100644 index 00000000000..fc41624b308 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw @@ -0,0 +1,33 @@ +script; + +trait MyTrait { + fn extract_a(self) -> u64; +} + +struct A { + a: u64, +} + +impl MyTrait for A { + fn extract_a(self) -> u64 { + self.a + } +} + +type B = A; + +// B is an alias for A, and A already has an implementation of MyTrait, +// so this should cause a compilation error. +impl MyTrait for B { + fn extract_a(self) -> u64 { + self.a + 1 + } +} + +fn main() { + let struct_a = A { a: 1 }; + let struct_b = B { a: 42 }; + // TODO: This results in disambiguation error, which is unhelpful since it doesn't get to the root of the problem - needs to recongnize that A == B + assert(struct_a.extract_a() == 1); + assert(struct_b.extract_a() == 42); +} diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml new file mode 100644 index 00000000000..696197d0e7a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml @@ -0,0 +1,3 @@ +category = "fail" + +#not: $()error \ No newline at end of file From 7e268f745833d4bac529cd1d29267ac8939af477 Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Mon, 24 Feb 2025 22:09:39 +0100 Subject: [PATCH 2/8] Improved error message when implementing duplicate impls for aliased types --- .../semantic_analysis/namespace/trait_map.rs | 15 ++++++------ sway-error/src/error.rs | 23 ++++++++++++++----- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index 74d8b2ace33..0d280f2c743 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -237,7 +237,7 @@ impl TraitMap { is_extending_existing_impl: IsExtendingExistingImpl, engines: &Engines, ) -> Result<(), ErrorEmitted> { - let type_id = engines.te().get_unaliased_type_id(type_id); + let unaliased_type_id = engines.te().get_unaliased_type_id(type_id); handler.scope(|handler| { let mut trait_items: TraitItems = HashMap::new(); @@ -267,7 +267,7 @@ impl TraitMap { } } - let trait_impls = self.get_impls_mut(engines, type_id); + let trait_impls = self.get_impls_mut(engines, unaliased_type_id); // check to see if adding this trait will produce a conflicting definition for TraitEntry { @@ -295,11 +295,11 @@ impl TraitMap { let unify_checker = UnifyCheck::non_generic_constraint_subset(engines); - // Types are subset if the `type_id` that we want to insert can unify with the + // Types are subset if the `unaliased_type_id` that we want to insert can unify with the // existing `map_type_id`. In addition we need to additionally check for the case of // `&mut ` and `&`. - let types_are_subset = unify_checker.check(type_id, *map_type_id) - && is_unified_type_subset(engines.te(), type_id, *map_type_id); + let types_are_subset = unify_checker.check(unaliased_type_id, *map_type_id) + && is_unified_type_subset(engines.te(), unaliased_type_id, *map_type_id); /// `left` can unify into `right`. Additionally we need to check subset condition in case of /// [TypeInfo::Ref] types. Although `&mut ` can unify with `&` @@ -367,7 +367,8 @@ impl TraitMap { { handler.emit_err(CompileError::ConflictingImplsForTraitAndType { trait_name: trait_name.to_string_with_args(engines, &trait_type_args), - type_implementing_for: engines.help_out(type_id).to_string(), + type_implementing_for: engines.help_out(unaliased_type_id).to_string(), + type_implementing_for_alias: engines.help_out(type_id).to_string(), existing_impl_span: existing_impl_span.clone(), second_impl_span: impl_span.clone(), }); @@ -442,7 +443,7 @@ impl TraitMap { trait_name, impl_span.clone(), trait_decl_span, - type_id, + unaliased_type_id, trait_items, engines, ); diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index 349ac2fc7a3..f0f613b7d4f 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -621,10 +621,11 @@ pub enum CompileError { }, #[error("An ABI can only be implemented for the `Contract` type, so this implementation of an ABI for type \"{ty}\" is invalid.")] ImplAbiForNonContract { span: Span, ty: String }, - #[error("Conflicting implementations of trait \"{trait_name}\" for type \"{type_implementing_for}\".")] + #[error("Conflicting implementations of trait \"{trait_name}\" for type \"{type_implementing_for_alias}\".")] ConflictingImplsForTraitAndType { trait_name: String, type_implementing_for: String, + type_implementing_for_alias: String, existing_impl_span: Span, second_impl_span: Span, }, @@ -2317,20 +2318,30 @@ impl ToDiagnostic for CompileError { format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single) ], }, - ConflictingImplsForTraitAndType { trait_name, type_implementing_for, existing_impl_span, second_impl_span } => Diagnostic { + ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_alias, existing_impl_span, second_impl_span } => Diagnostic { reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())), issue: Issue::error( source_engine, second_impl_span.clone(), - format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".") + if type_implementing_for == type_implementing_for_alias { + format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".") + } else { + format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for_alias}\", possibly using an alias (the unaliased type name is \"{type_implementing_for}\").") + } ), hints: vec![ Hint::info( source_engine, existing_impl_span.clone(), - format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".", - call_path_suffix_with_args(trait_name) - ) + if type_implementing_for == type_implementing_for_alias { + format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".", + call_path_suffix_with_args(trait_name) + ) + } else { + format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for_alias}\", possibly using an alias (the unaliased type name is \"{type_implementing_for}\").", + call_path_suffix_with_args(trait_name) + ) + } ), ], help: vec![ From c85d708d1b89ad3e6fdb3208bc03b5e38badfe4b Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Mon, 24 Feb 2025 22:13:37 +0100 Subject: [PATCH 3/8] Removed TODO --- .../test_programs/should_fail/type_alias_unification/src/main.sw | 1 - 1 file changed, 1 deletion(-) diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw index fc41624b308..10a35a26f0b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw @@ -27,7 +27,6 @@ impl MyTrait for B { fn main() { let struct_a = A { a: 1 }; let struct_b = B { a: 42 }; - // TODO: This results in disambiguation error, which is unhelpful since it doesn't get to the root of the problem - needs to recongnize that A == B assert(struct_a.extract_a() == 1); assert(struct_b.extract_a() == 42); } From 5f5a23db53276dc8f5cc8c840cfc4ab0e7e7eee8 Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Thu, 27 Feb 2025 15:47:37 +0100 Subject: [PATCH 4/8] Improve remaining error messages in TraitMap::insert --- .../semantic_analysis/namespace/trait_map.rs | 21 ++++++---- sway-error/src/error.rs | 42 +++++++++++++++---- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index 0d280f2c743..3dd0e5da02d 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -367,8 +367,8 @@ impl TraitMap { { handler.emit_err(CompileError::ConflictingImplsForTraitAndType { trait_name: trait_name.to_string_with_args(engines, &trait_type_args), - type_implementing_for: engines.help_out(unaliased_type_id).to_string(), - type_implementing_for_alias: engines.help_out(type_id).to_string(), + type_implementing_for: engines.help_out(type_id).to_string(), + type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_impl_span.clone(), second_impl_span: impl_span.clone(), }); @@ -383,21 +383,22 @@ impl TraitMap { ResolvedTraitImplItem::Parsed(_item) => todo!(), ResolvedTraitImplItem::Typed(item) => match item { ty::TyTraitItem::Fn(decl_ref) => { - if map_trait_items.get(name).is_some() { + if let Some(existing_item) = map_trait_items.get(name) { handler.emit_err( CompileError::DuplicateDeclDefinedForType { decl_kind: "method".into(), decl_name: decl_ref.name().to_string(), type_implementing_for: engines .help_out(type_id) - .to_string(), - span: decl_ref.name().span(), + .to_string(), + type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_item.span(engines).clone(), + second_impl_span: decl_ref.name().span(), }, ); } } ty::TyTraitItem::Constant(decl_ref) => { - if map_trait_items.get(name).is_some() { + if let Some(existing_item) = map_trait_items.get(name) { handler.emit_err( CompileError::DuplicateDeclDefinedForType { decl_kind: "constant".into(), @@ -405,13 +406,14 @@ impl TraitMap { type_implementing_for: engines .help_out(type_id) .to_string(), - span: decl_ref.name().span(), + type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_item.span(engines).clone(), + second_impl_span: decl_ref.name().span(), }, ); } } ty::TyTraitItem::Type(decl_ref) => { - if map_trait_items.get(name).is_some() { + if let Some(existing_item) = map_trait_items.get(name) { handler.emit_err( CompileError::DuplicateDeclDefinedForType { decl_kind: "type".into(), @@ -419,7 +421,8 @@ impl TraitMap { type_implementing_for: engines .help_out(type_id) .to_string(), - span: decl_ref.name().span(), + type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_item.span(engines).clone(), + second_impl_span: decl_ref.name().span(), }, ); } diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index f0f613b7d4f..7bf166fb072 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -621,11 +621,11 @@ pub enum CompileError { }, #[error("An ABI can only be implemented for the `Contract` type, so this implementation of an ABI for type \"{ty}\" is invalid.")] ImplAbiForNonContract { span: Span, ty: String }, - #[error("Conflicting implementations of trait \"{trait_name}\" for type \"{type_implementing_for_alias}\".")] + #[error("Conflicting implementations of trait \"{trait_name}\" for type \"{type_implementing_for}\".")] ConflictingImplsForTraitAndType { trait_name: String, type_implementing_for: String, - type_implementing_for_alias: String, + type_implementing_for_unaliased: String, existing_impl_span: Span, second_impl_span: Span, }, @@ -641,7 +641,9 @@ pub enum CompileError { decl_kind: String, decl_name: String, type_implementing_for: String, - span: Span, + type_implementing_for_unaliased: String, + existing_impl_span: Span, + second_impl_span: Span, }, #[error("The function \"{fn_name}\" in {interface_name} is defined with {num_parameters} parameters, but the provided implementation has {provided_parameters} parameters.")] IncorrectNumberOfInterfaceSurfaceFunctionParameters { @@ -1181,7 +1183,7 @@ impl Spanned for CompileError { second_impl_span, .. } => second_impl_span.clone(), MarkerTraitExplicitlyImplemented { span, .. } => span.clone(), - DuplicateDeclDefinedForType { span, .. } => span.clone(), + DuplicateDeclDefinedForType { second_impl_span, .. } => second_impl_span.clone(), IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(), ArgumentParameterTypeMismatch { span, .. } => span.clone(), RecursiveCall { span, .. } => span.clone(), @@ -2318,27 +2320,27 @@ impl ToDiagnostic for CompileError { format!("{}- referencing a mutable copy of \"{decl_name}\", by returning it from a block: `&mut {{ {decl_name} }}`.", Indent::Single) ], }, - ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_alias, existing_impl_span, second_impl_span } => Diagnostic { + ConflictingImplsForTraitAndType { trait_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic { reason: Some(Reason::new(code(1), "Trait is already implemented for type".to_string())), issue: Issue::error( source_engine, second_impl_span.clone(), - if type_implementing_for == type_implementing_for_alias { + if type_implementing_for == type_implementing_for_unaliased { format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\".") } else { - format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for_alias}\", possibly using an alias (the unaliased type name is \"{type_implementing_for}\").") + format!("Trait \"{trait_name}\" is already implemented for type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").") } ), hints: vec![ Hint::info( source_engine, existing_impl_span.clone(), - if type_implementing_for == type_implementing_for_alias { + if type_implementing_for == type_implementing_for_unaliased { format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\".", call_path_suffix_with_args(trait_name) ) } else { - format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for_alias}\", possibly using an alias (the unaliased type name is \"{type_implementing_for}\").", + format!("This is the already existing implementation of \"{}\" for \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").", call_path_suffix_with_args(trait_name) ) } @@ -2349,6 +2351,28 @@ impl ToDiagnostic for CompileError { "This property is called \"trait coherence\".".to_string(), ], }, + DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic { + reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())), + issue: Issue::error( + source_engine, + second_impl_span.clone(), + if type_implementing_for == type_implementing_for_unaliased { + format!("{decl_kind} \"{decl_name}\" already declared in type \"{type_implementing_for}\".") + } else { + format!("{decl_kind} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").") + } + ), + hints: vec![ + Hint::info( + source_engine, + existing_impl_span.clone(), + format!("\"{decl_name}\" previously defined here.") + ) + ], + help: vec![ + "A type may not contain two or more declarations of the same name".to_string(), + ], + }, MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic { reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())), issue: Issue::error( From a2f67bffcfeeec55fbae45c6cdbcf3fece774cd6 Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Thu, 27 Feb 2025 15:52:57 +0100 Subject: [PATCH 5/8] Expected test output --- .../should_fail/type_alias_unification/test.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml index 696197d0e7a..ef322b7f74e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/test.toml @@ -1,3 +1,7 @@ category = "fail" -#not: $()error \ No newline at end of file +#check: $()Trait is already implemented for type +#check: $()This is the already existing implementation of "MyTrait" for "B" (which is an alias for "A"). +#check: $()Trait "type_alias_unification::MyTrait" is already implemented for type "B" (which is an alias for "A"). + +#check: $()Aborting due to 1 error. From 4cd928e0f8a97a190b9c1d3e7162a01f7c87aad0 Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Thu, 27 Feb 2025 15:55:25 +0100 Subject: [PATCH 6/8] clippy, fmt --- .../semantic_analysis/namespace/trait_map.rs | 27 +++++++++++++++---- sway-error/src/error.rs | 6 +++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index 3dd0e5da02d..feaeba38e99 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -368,7 +368,9 @@ impl TraitMap { handler.emit_err(CompileError::ConflictingImplsForTraitAndType { trait_name: trait_name.to_string_with_args(engines, &trait_type_args), type_implementing_for: engines.help_out(type_id).to_string(), - type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), + type_implementing_for_unaliased: engines + .help_out(unaliased_type_id) + .to_string(), existing_impl_span: existing_impl_span.clone(), second_impl_span: impl_span.clone(), }); @@ -390,8 +392,13 @@ impl TraitMap { decl_name: decl_ref.name().to_string(), type_implementing_for: engines .help_out(type_id) - .to_string(), - type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_item.span(engines).clone(), + .to_string(), + type_implementing_for_unaliased: engines + .help_out(unaliased_type_id) + .to_string(), + existing_impl_span: existing_item + .span(engines) + .clone(), second_impl_span: decl_ref.name().span(), }, ); @@ -406,7 +413,12 @@ impl TraitMap { type_implementing_for: engines .help_out(type_id) .to_string(), - type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_item.span(engines).clone(), + type_implementing_for_unaliased: engines + .help_out(unaliased_type_id) + .to_string(), + existing_impl_span: existing_item + .span(engines) + .clone(), second_impl_span: decl_ref.name().span(), }, ); @@ -421,7 +433,12 @@ impl TraitMap { type_implementing_for: engines .help_out(type_id) .to_string(), - type_implementing_for_unaliased: engines.help_out(unaliased_type_id).to_string(), existing_impl_span: existing_item.span(engines).clone(), + type_implementing_for_unaliased: engines + .help_out(unaliased_type_id) + .to_string(), + existing_impl_span: existing_item + .span(engines) + .clone(), second_impl_span: decl_ref.name().span(), }, ); diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index 7bf166fb072..3f381f96441 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -1183,7 +1183,9 @@ impl Spanned for CompileError { second_impl_span, .. } => second_impl_span.clone(), MarkerTraitExplicitlyImplemented { span, .. } => span.clone(), - DuplicateDeclDefinedForType { second_impl_span, .. } => second_impl_span.clone(), + DuplicateDeclDefinedForType { + second_impl_span, .. + } => second_impl_span.clone(), IncorrectNumberOfInterfaceSurfaceFunctionParameters { span, .. } => span.clone(), ArgumentParameterTypeMismatch { span, .. } => span.clone(), RecursiveCall { span, .. } => span.clone(), @@ -2358,7 +2360,7 @@ impl ToDiagnostic for CompileError { second_impl_span.clone(), if type_implementing_for == type_implementing_for_unaliased { format!("{decl_kind} \"{decl_name}\" already declared in type \"{type_implementing_for}\".") - } else { + } else { format!("{decl_kind} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").") } ), From 971540091104742c5983ab7a77de490dd12d0853 Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Fri, 28 Feb 2025 15:25:15 +0100 Subject: [PATCH 7/8] Fixed failing tests --- sway-error/src/error.rs | 47 ++++++++++--------- .../impl_self_duplicated/test.toml | 8 +++- .../test.toml | 22 +++++++-- .../type_alias_shadowing_methods/test.toml | 8 ++-- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index 3f381f96441..9edd1f35801 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -2353,28 +2353,31 @@ impl ToDiagnostic for CompileError { "This property is called \"trait coherence\".".to_string(), ], }, - DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => Diagnostic { - reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())), - issue: Issue::error( - source_engine, - second_impl_span.clone(), - if type_implementing_for == type_implementing_for_unaliased { - format!("{decl_kind} \"{decl_name}\" already declared in type \"{type_implementing_for}\".") - } else { - format!("{decl_kind} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").") - } - ), - hints: vec![ - Hint::info( - source_engine, - existing_impl_span.clone(), - format!("\"{decl_name}\" previously defined here.") - ) - ], - help: vec![ - "A type may not contain two or more declarations of the same name".to_string(), - ], - }, + DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => { + let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind); + Diagnostic { + reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())), + issue: Issue::error( + source_engine, + second_impl_span.clone(), + if type_implementing_for == type_implementing_for_unaliased { + format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".") + } else { + format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").") + } + ), + hints: vec![ + Hint::info( + source_engine, + existing_impl_span.clone(), + format!("\"{decl_name}\" previously defined here.") + ) + ], + help: vec![ + "A type may not contain two or more declarations of the same name".to_string(), + ], + } + }, MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic { reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())), issue: Issue::error( diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/impl_self_duplicated/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/impl_self_duplicated/test.toml index 716219cfde9..5b27cecd833 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/impl_self_duplicated/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/impl_self_duplicated/test.toml @@ -2,5 +2,9 @@ category = "fail" validate_abi = false expected_warnings = 3 -# check: fn foo(self) -> u64 { -# nextln: $()Duplicate definitions for the method "foo" for type "S". +# check: $()Type contains duplicate declarations +# check: $()fn foo(self) -> u64 { +# check: $()"foo" previously defined here. +# check: $()Method "foo" already declared in type "S". + +# check: $()Aborting due to 1 error. \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/multiple_methods_with_the_same_name/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/multiple_methods_with_the_same_name/test.toml index 7c383bbf1db..2e4be8b0f3d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/multiple_methods_with_the_same_name/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/multiple_methods_with_the_same_name/test.toml @@ -1,13 +1,27 @@ category = "fail" +# check: $()Type contains duplicate declarations # check: $()fn my_add(self, other: Self) -> Self { -# check: $()Duplicate definitions for the method "my_add" for type "Data". +# check: $()"my_add" previously defined here. +# check: $()fn my_add(self, other: Self) -> Self { +# check: $()Method "my_add" already declared in type "Data". +# check: $()Type contains duplicate declarations +# check: $()fn get_value(self) -> u64 { +# check: $()"get_value" previously defined here. # check: $()fn get_value(self) -> u64 { -# check: $()Duplicate definitions for the method "get_value" for type "Data". +# check: $(Method "get_value" already declared in type "Data". +# check: $()Type contains duplicate declarations +# check: $()fn my_add(self, other: Self) -> Self { +# check: $()"my_add" previously defined here. # check: $()fn my_add(self, other: Self) -> Self { -# check: $()Duplicate definitions for the method "my_add" for type "Data". +# check: $()Method "my_add" already declared in type "Data". +# check: $()Type contains duplicate declarations # check: $()fn my_add(self, other: Self) -> Self { -# check: $()Duplicate definitions for the method "my_add" for type "Data". +# check: $()"my_add" previously defined here. +# check: $()fn my_add(self, other: Self) -> Self { +# check: $()Method "my_add" already declared in type "Data". + +# check: $()Aborting due to 6 errors \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_shadowing_methods/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_shadowing_methods/test.toml index dde5c71514e..c24b2329807 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_shadowing_methods/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_shadowing_methods/test.toml @@ -1,5 +1,7 @@ category = "fail" -#check: $()impl Alias2 { -#nextln: $()fn foo() {} -#nextln: $()Duplicate definitions for the method "foo" for type "MyStruct1". +#check: $()Type contains duplicate declarations +#check: $()fn foo() {} +#nextln: $()"foo" previously defined here. +#check: $()fn foo() {} +#nextln: $()Method "foo" already declared in type "Alias2" (which is an alias for "MyStruct1"). From dff92512ece2ac68598376cdacafad30c6c2763b Mon Sep 17 00:00:00 2001 From: Jacob Johannsen Date: Mon, 3 Mar 2025 22:09:55 +0100 Subject: [PATCH 8/8] Untabify --- sway-error/src/error.rs | 24 +++++++++---------- .../type_alias_unification/src/main.sw | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index 9edd1f35801..7a085ae7745 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -2354,30 +2354,30 @@ impl ToDiagnostic for CompileError { ], }, DuplicateDeclDefinedForType { decl_kind, decl_name, type_implementing_for, type_implementing_for_unaliased, existing_impl_span, second_impl_span } => { - let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind); - Diagnostic { + let decl_kind_snake_case = sway_types::style::to_upper_camel_case(decl_kind); + Diagnostic { reason: Some(Reason::new(code(1), "Type contains duplicate declarations".to_string())), issue: Issue::error( - source_engine, - second_impl_span.clone(), - if type_implementing_for == type_implementing_for_unaliased { + source_engine, + second_impl_span.clone(), + if type_implementing_for == type_implementing_for_unaliased { format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\".") - } else { + } else { format!("{decl_kind_snake_case} \"{decl_name}\" already declared in type \"{type_implementing_for}\" (which is an alias for \"{type_implementing_for_unaliased}\").") - } + } ), hints: vec![ - Hint::info( + Hint::info( source_engine, existing_impl_span.clone(), format!("\"{decl_name}\" previously defined here.") - ) + ) ], help: vec![ - "A type may not contain two or more declarations of the same name".to_string(), + "A type may not contain two or more declarations of the same name".to_string(), ], - } - }, + } + }, MarkerTraitExplicitlyImplemented { marker_trait_full_name, span} => Diagnostic { reason: Some(Reason::new(code(1), "Marker traits cannot be explicitly implemented".to_string())), issue: Issue::error( diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw index 10a35a26f0b..36870f342e1 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_fail/type_alias_unification/src/main.sw @@ -20,7 +20,7 @@ type B = A; // so this should cause a compilation error. impl MyTrait for B { fn extract_a(self) -> u64 { - self.a + 1 + self.a + 1 } }