Skip to content

Commit e476469

Browse files
authored
Merge branch 'master' into ironcev/partial-equivalence
2 parents 9b0ee9e + 1fdf630 commit e476469

File tree

6 files changed

+141
-7
lines changed

6 files changed

+141
-7
lines changed

forc-pkg/src/manifest/mod.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ impl DependencyDetails {
326326
if git.is_none() && (branch.is_some() || tag.is_some() || rev.is_some()) {
327327
bail!("Details reserved for git sources used without a git field");
328328
}
329+
329330
Ok(())
330331
}
331332
}
@@ -638,13 +639,26 @@ impl PackageManifest {
638639
/// 1. The project and organization names against a set of reserved/restricted keywords and patterns.
639640
/// 2. The validity of the details provided. Makes sure that there are no mismatching detail
640641
/// declarations (to prevent mixing details specific to certain types).
642+
/// 3. The dependencies listed does not have an alias ("package" field) that is the same as package name.
641643
pub fn validate(&self) -> Result<()> {
642644
validate_project_name(&self.project.name)?;
643645
if let Some(ref org) = self.project.organization {
644646
validate_name(org, "organization name")?;
645647
}
646-
for (_, dependency_details) in self.deps_detailed() {
648+
for (dep_name, dependency_details) in self.deps_detailed() {
647649
dependency_details.validate()?;
650+
if dependency_details
651+
.package
652+
.as_ref()
653+
.is_some_and(|package_alias| package_alias == &self.project.name)
654+
{
655+
bail!(format!("Dependency \"{dep_name}\" declares an alias (\"package\" field) that is the same as project name"))
656+
}
657+
if dep_name == &self.project.name {
658+
bail!(format!(
659+
"Dependency \"{dep_name}\" collides with project name."
660+
))
661+
}
648662
}
649663
Ok(())
650664
}
@@ -1666,4 +1680,43 @@ mod tests {
16661680
assert_eq!(original.workspace.members, deserialized.workspace.members);
16671681
assert_eq!(original.workspace.metadata, deserialized.workspace.metadata);
16681682
}
1683+
1684+
#[test]
1685+
fn test_dependency_alias_project_name_collision() {
1686+
let original_toml = r#"
1687+
[project]
1688+
authors = ["Fuel Labs <contact@fuel.sh>"]
1689+
entry = "main.sw"
1690+
license = "Apache-2.0"
1691+
name = "lib_contract_abi"
1692+
1693+
[dependencies]
1694+
lib_contract = { path = "../lib_contract_abi/", package = "lib_contract_abi" }
1695+
"#;
1696+
1697+
let project = PackageManifest::from_string(original_toml.to_string());
1698+
let err = project.unwrap_err();
1699+
assert_eq!(err.to_string(), format!("Dependency \"lib_contract\" declares an alias (\"package\" field) that is the same as project name"))
1700+
}
1701+
1702+
#[test]
1703+
fn test_dependency_name_project_name_collision() {
1704+
let original_toml = r#"
1705+
[project]
1706+
authors = ["Fuel Labs <contact@fuel.sh>"]
1707+
entry = "main.sw"
1708+
license = "Apache-2.0"
1709+
name = "lib_contract"
1710+
1711+
[dependencies]
1712+
lib_contract = { path = "../lib_contract_abi/", package = "lib_contract_abi" }
1713+
"#;
1714+
1715+
let project = PackageManifest::from_string(original_toml.to_string());
1716+
let err = project.unwrap_err();
1717+
assert_eq!(
1718+
err.to_string(),
1719+
format!("Dependency \"lib_contract\" collides with project name.")
1720+
)
1721+
}
16691722
}

sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,35 @@ pub(crate) fn type_check_method_application(
7777
true
7878
}
7979
});
80-
handler.append(arg_handler);
80+
handler.append(arg_handler.clone());
8181
}
8282

83-
args_opt_buf.push_back((arg_opt, needs_second_pass));
83+
args_opt_buf.push_back((arg_opt, arg_handler, needs_second_pass));
8484
}
8585

8686
// resolve the method name to a typed function declaration and type_check
87-
let (original_decl_ref, call_path_typeid) = resolve_method_name(
87+
let method_result = resolve_method_name(
8888
handler,
8989
ctx.by_ref(),
9090
&method_name_binding,
9191
args_opt_buf
9292
.iter()
93-
.map(|(arg, _has_errors)| match arg {
93+
.map(|(arg, _, _has_errors)| match arg {
9494
Some(arg) => arg.return_type,
9595
None => type_engine.new_unknown(),
9696
})
9797
.collect(),
98-
)?;
98+
);
99+
100+
// In case resolve_method_name fails throw argument errors.
101+
let (original_decl_ref, call_path_typeid) = if let Err(e) = method_result {
102+
for (_, arg_handler, _) in args_opt_buf.iter() {
103+
handler.append(arg_handler.clone());
104+
}
105+
return Err(e);
106+
} else {
107+
method_result.unwrap()
108+
};
99109

100110
let mut fn_ref = monomorphize_method(
101111
handler,
@@ -120,7 +130,7 @@ pub(crate) fn type_check_method_application(
120130
// type check the function arguments (2nd pass)
121131
let mut args_buf = VecDeque::new();
122132
for (arg, index, arg_opt) in izip!(arguments.iter(), 0.., args_opt_buf.iter().cloned()) {
123-
if let (Some(arg), false) = arg_opt {
133+
if let (Some(arg), _, false) = arg_opt {
124134
args_buf.push_back(arg);
125135
} else {
126136
// We type check the argument expression again this time throwing out the error.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[[package]]
2+
name = "core"
3+
source = "path+from-root-1C5801B8398D8ED4"
4+
5+
[[package]]
6+
name = "variable_does_not_exist"
7+
source = "member"
8+
dependencies = ["core"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[project]
2+
name = "variable_does_not_exist"
3+
authors = ["Fuel Labs <contact@fuel.sh>"]
4+
entry = "main.sw"
5+
license = "Apache-2.0"
6+
implicit-std = false
7+
8+
[dependencies]
9+
core = { path = "../../../../../../sway-lib-core" }
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
script;
2+
3+
struct S {}
4+
5+
impl S {
6+
fn associated(a: u64, b: u64, c: u64) -> u64 {
7+
a + b + c
8+
}
9+
}
10+
11+
fn function(a: u64, b: u64, c: u64) -> u64 {
12+
a + b + c
13+
}
14+
15+
fn main() {
16+
let _ = S::associated(x, y, z);
17+
18+
19+
let _ = function(x, y, z);
20+
21+
22+
let _ = x + y + z;
23+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
category = "fail"
2+
3+
# check: $()let _ = S::associated(x, y, z);
4+
# nextln:$()Variable "x" does not exist in this scope.
5+
6+
# check: $()let _ = S::associated(x, y, z);
7+
# nextln:$()Variable "y" does not exist in this scope.
8+
9+
# check: $()let _ = S::associated(x, y, z);
10+
# nextln:$()Variable "z" does not exist in this scope.
11+
12+
# check: $()let _ = function(x, y, z);
13+
# nextln:$()Variable "x" does not exist in this scope.
14+
15+
# check: $()let _ = function(x, y, z);
16+
# nextln:$()Variable "y" does not exist in this scope.
17+
18+
# check: $()let _ = function(x, y, z);
19+
# nextln:$()Variable "z" does not exist in this scope.
20+
21+
# check: $()let _ = x + y + z;
22+
# nextln: $()Variable "x" does not exist in this scope.
23+
24+
# check: $()let _ = x + y + z;
25+
# nextln: $()Variable "y" does not exist in this scope.
26+
27+
# check: $()let _ = x + y + z;
28+
# nextln: $()No method "add({unknown}, unknown)" found for type "{unknown}".
29+
30+
# check: $()let _ = x + y + z;
31+
# nextln: $()Variable "z" does not exist in this scope.

0 commit comments

Comments
 (0)