Skip to content

Commit

Permalink
Test and fix overlapping trait impls.
Browse files Browse the repository at this point in the history
find_method_for_type now if we have: impl<T> FromBytes for T
and: impl FromBytes for DataPoint, we pick the second implementation.

Fixes #6572
  • Loading branch information
esdrubal committed Oct 8, 2024
1 parent f8ca396 commit 001ac1f
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 15 deletions.
46 changes: 31 additions & 15 deletions sway-core/src/semantic_analysis/type_check_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,22 +1408,38 @@ impl<'a> TypeCheckContext<'a> {
}
}

let trait_methods_key = (
trait_decl.trait_name.clone(),
trait_decl
.trait_type_arguments
.iter()
.cloned()
.map(|a| self.engines.help_out(a))
.collect::<Vec<_>>(),
method.implementing_for_typeid.map(|t| {
self.engines.help_out((*self.engines.te().get(t)).clone())
}),
);

// If we have: impl<T> FromBytes for T
// and: impl FromBytes for DataPoint
// We pick the second implementation.
if let Some(existing_value) = trait_methods.get(&trait_methods_key) {
let existing_method = decl_engine.get_function(existing_value);
if let Some(ty::TyDecl::ImplSelfOrTrait(existing_impl_trait)) =
existing_method.implementing_type.clone()
{
let existing_trait_decl = decl_engine
.get_impl_self_or_trait(&existing_impl_trait.decl_id);
if existing_trait_decl.impl_type_parameters.is_empty() {
// We already have an impl without type parameters so we skip the others.
skip_insert = true;
}
}
}

if !skip_insert {
trait_methods.insert(
(
trait_decl.trait_name.clone(),
trait_decl
.trait_type_arguments
.iter()
.cloned()
.map(|a| self.engines.help_out(a))
.collect::<Vec<_>>(),
method.implementing_for_typeid.map(|t| {
self.engines.help_out((*self.engines.te().get(t)).clone())
}),
),
method_ref.clone(),
);
trait_methods.insert(trait_methods_key, method_ref.clone());
}
if trait_decl.trait_decl_ref.is_none() {
impl_self_method = Some(method_ref);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = "core"
source = "path+from-root-BB2447E2F19FD755"

[[package]]
name = "overlapped_trait_impls"
source = "member"
dependencies = ["std"]

[[package]]
name = "std"
source = "path+from-root-BB2447E2F19FD755"
dependencies = ["core"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
license = "Apache-2.0"
name = "overlapped_trait_impls"
entry = "main.sw"
implicit-std = false

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
script;

use std::{
bytes::Bytes,
vec::Vec,
};

pub trait FromBytesConvertible {
fn _from_be_bytes(bytes: Bytes) -> Self;
}

pub trait FromBytes {
fn from_bytes(bytes: Bytes) -> Self;
}

impl<T> FromBytes for T
where
T: FromBytesConvertible,
{
fn from_bytes(bytes: Bytes) -> Self {
Self::_from_be_bytes(bytes)
}
}

pub struct DataPoint {}
pub struct Payload {}

impl FromBytes for DataPoint {
fn from_bytes(bytes: Bytes) -> Self {
Self {}
}
}

impl Payload {
pub fn from_bytes(bytes: Bytes) {
let mut data_points = Vec::new();

data_points.push(DataPoint::from_bytes(bytes));

let a:DataPoint = DataPoint::from_bytes(bytes);
data_points.push(a);
}
}

pub fn main() -> bool {
Payload::from_bytes(Bytes::new());

true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
category = "run"
expected_result = { action = "return", value = 1 }
expected_result_new_encoding = { action = "return_data", value = "01" }
validate_abi = false
expected_warnings = 3

0 comments on commit 001ac1f

Please # to comment.