Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing the same item multiple times should be a compile error #739

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sway-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@ pub enum CompileError {
},
#[error("The name \"{name}\" shadows another symbol with the same name.")]
ShadowsOtherSymbol { name: String, span: Span },
#[error("The name \"{name}\" imported through `*` shadows another symbol with the same name.")]
StarImportShadowsOtherSymbol { name: String, span: Span },
#[error(
"Match expression arm has mismatched types.\n\
expected: {expected}\n\
Expand Down Expand Up @@ -1004,6 +1006,7 @@ impl CompileError {
ArrayOutOfBounds { span, .. } => span,
TupleOutOfBounds { span, .. } => span,
ShadowsOtherSymbol { span, .. } => span,
StarImportShadowsOtherSymbol { span, .. } => span,
MatchWrongType { span, .. } => span,
NotAnEnum { span, .. } => span,
PatternMatchingAlgorithmFailure(_, span) => span,
Expand Down
20 changes: 19 additions & 1 deletion sway-core/src/semantic_analysis/namespace/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,16 @@ impl NamespaceWrapper for NamespaceRef {
namespace,
);
write_module(
move |m| {
|m| {
m.implemented_traits
.extend(&mut implemented_traits.into_iter());
for symbol in symbols {
if m.use_synonyms.contains_key(&symbol) {
errors.push(CompileError::StarImportShadowsOtherSymbol {
name: symbol.as_str().to_string(),
span: symbol.span().clone(),
});
}
m.use_synonyms.insert(symbol, path.clone());
}
},
Expand Down Expand Up @@ -487,11 +493,23 @@ impl NamespaceWrapper for NamespaceRef {
// no matter what, import it this way though.
match alias.clone() {
Some(alias) => {
if m.use_synonyms.contains_key(&alias) {
errors.push(CompileError::ShadowsOtherSymbol {
name: alias.as_str().to_string(),
span: alias.span().clone(),
});
}
m.use_synonyms.insert(alias.clone(), path.clone());
m.use_aliases
.insert(alias.as_str().to_string(), item.clone());
}
None => {
if m.use_synonyms.contains_key(item) {
errors.push(CompileError::ShadowsOtherSymbol {
name: item.as_str().to_string(),
span: item.span().clone(),
});
}
m.use_synonyms.insert(item.clone(), path.clone());
}
};
Expand Down
1 change: 1 addition & 0 deletions test/src/e2e_vm_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub fn run(filter_regex: Option<regex::Regex>) {
"contract_pure_calls_impure",
"literal_too_large_for_type",
"item_used_without_import",
"shadow_import",
];
number_of_tests_run += negative_project_names.iter().fold(0, |acc, name| {
if filter(name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ script;

dep bar;

use ::bar::{Bar1 as MyBar1, Bar2, double_bar::{DoubleBar1 as MyDoubleBar1, DoubleBar2, *}};
use ::bar::{Bar1 as MyBar1, Bar2, double_bar::{DoubleBar1 as MyDoubleBar1, DoubleBar2, DoubleBar3}};

fn main() -> bool {
let bar1 = MyBar1 {
Expand Down
5 changes: 5 additions & 0 deletions test/src/e2e_vm_tests/test_programs/shadow_import/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
author = "Fuel Labs <contact@fuel.sh>"
license = "Apache-2.0"
name = "shadow_import"
entry = "main.sw"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
13 changes: 13 additions & 0 deletions test/src/e2e_vm_tests/test_programs/shadow_import/src/bar.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
library bar;

pub struct Bar1 {
a: u32,
}

pub struct Bar2 {
b: u32,
}

pub struct Bar3 {
c: u32,
}
19 changes: 19 additions & 0 deletions test/src/e2e_vm_tests/test_programs/shadow_import/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
script;

dep bar;

// This is okay
use ::bar::{Bar1, Bar1 as Foo};

// This is not okay because symbol `Foo` is already reserved
use ::bar::Bar2 as Foo;

// This is not okay
use ::bar::{Bar2, Bar2};

// This not okay now because Bar1 and Bar2 have already been imported
use ::bar::*;

fn main() -> bool {
false
}