Skip to content

Commit

Permalink
Fixes trait map issue on the use of absolute path (FuelLabs#4697)
Browse files Browse the repository at this point in the history
## Description

The test case use_absolute_path included in this PR was generating an
error due to the `CallPath` `to_fullpath` generating
`use_absolute_path::foo::trait::Trait` instead of
`use_absolute_path::trait::Trait`.

The issue was fixed by including a boolean in `namespace.use_synonyms`
that indicates when the path is absolute. With that information
`to_fullpath` can behave accordingly.

Fixes FuelLabs#4696

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: Joshua Batty <[email protected]>
  • Loading branch information
esdrubal and JoshuaBatty authored Jun 23, 2023
1 parent 7245883 commit e8d6472
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 32 deletions.
2 changes: 2 additions & 0 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1683,13 +1683,15 @@ pub fn dependency_namespace(
&[CORE, PRELUDE].map(|s| Ident::new_no_span(s.into())),
&[],
engines,
true,
);

if has_std_dep(graph, node) {
namespace.star_import_with_reexports(
&[STD, PRELUDE].map(|s| Ident::new_no_span(s.into())),
&[],
engines,
true,
);
}

Expand Down
8 changes: 6 additions & 2 deletions sway-core/src/language/call_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,11 @@ impl CallPath {
// current submodule.
let mut synonym_prefixes = vec![];
let mut is_external = false;
let mut is_absolute = false;

if let Some(use_synonym) = namespace.use_synonyms.get(&self.suffix) {
synonym_prefixes = use_synonym.0.clone();
is_absolute = use_synonym.3;
let submodule = namespace.submodule(&[use_synonym.0[0].clone()]);
if let Some(submodule) = submodule {
is_external = submodule.is_external;
Expand All @@ -127,8 +129,10 @@ impl CallPath {
prefixes.push(pkg_name.clone());
}

for mod_path in namespace.mod_path() {
prefixes.push(mod_path.clone());
if !is_absolute {
for mod_path in namespace.mod_path() {
prefixes.push(mod_path.clone());
}
}
}

Expand Down
30 changes: 21 additions & 9 deletions sway-core/src/semantic_analysis/ast_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@ impl ty::TyAstNode {
let mut res = match a.import_type {
ImportType::Star => {
// try a standard starimport first
let import = ctx.namespace.star_import(&path, engines);
let import = ctx.namespace.star_import(&path, engines, a.is_absolute);
if import.is_ok() {
import
} else {
// if it doesn't work it could be an enum star import
if let Some((enum_name, path)) = path.split_last() {
let variant_import =
ctx.namespace.variant_star_import(path, engines, enum_name);
let variant_import = ctx.namespace.variant_star_import(
path,
engines,
enum_name,
a.is_absolute,
);
if variant_import.is_ok() {
variant_import
} else {
Expand All @@ -56,14 +60,21 @@ impl ty::TyAstNode {
}
}
}
ImportType::SelfImport(_) => {
ctx.namespace.self_import(engines, &path, a.alias.clone())
}
ImportType::SelfImport(_) => ctx.namespace.self_import(
engines,
&path,
a.alias.clone(),
a.is_absolute,
),
ImportType::Item(ref s) => {
// try a standard item import first
let import =
ctx.namespace
.item_import(engines, &path, s, a.alias.clone());
let import = ctx.namespace.item_import(
engines,
&path,
s,
a.alias.clone(),
a.is_absolute,
);

if import.is_ok() {
import
Expand All @@ -76,6 +87,7 @@ impl ty::TyAstNode {
enum_name,
s,
a.alias.clone(),
a.is_absolute,
);
if variant_import.is_ok() {
variant_import
Expand Down
4 changes: 2 additions & 2 deletions sway-core/src/semantic_analysis/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub(crate) enum GlobImport {
}

pub(super) type SymbolMap = im::OrdMap<Ident, ty::TyDecl>;
pub(super) type UseSynonyms = im::HashMap<Ident, (Vec<Ident>, GlobImport, ty::TyDecl)>;
pub(super) type UseSynonyms = im::HashMap<Ident, (Vec<Ident>, GlobImport, ty::TyDecl, bool)>;
pub(super) type UseAliases = im::HashMap<String, Ident>;

/// The set of items that exist within some lexical scope via declaration or importing.
Expand Down Expand Up @@ -137,7 +137,7 @@ impl Items {
append_shadowing_error(decl, &item, &mut errors);
}

if let Some((_, GlobImport::No, decl)) = self.use_synonyms.get(&name) {
if let Some((_, GlobImport::No, decl, _)) = self.use_synonyms.get(&name) {
append_shadowing_error(decl, &item, &mut errors);
}

Expand Down
34 changes: 24 additions & 10 deletions sway-core/src/semantic_analysis/namespace/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ impl Module {
src: &Path,
dst: &Path,
engines: &Engines,
is_src_absolute: bool,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
Expand Down Expand Up @@ -271,7 +272,12 @@ impl Module {
for symbol_and_decl in symbols_and_decls {
dst_ns.use_synonyms.insert(
symbol_and_decl.0,
(src.to_vec(), GlobImport::Yes, symbol_and_decl.1),
(
src.to_vec(),
GlobImport::Yes,
symbol_and_decl.1,
is_src_absolute,
),
);
}

Expand All @@ -289,6 +295,7 @@ impl Module {
src: &Path,
dst: &Path,
engines: &Engines,
is_src_absolute: bool,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
Expand All @@ -314,7 +321,7 @@ impl Module {
let mut symbols_and_decls = src_ns
.use_synonyms
.iter()
.map(|(symbol, (_, _, decl))| (symbol.clone(), decl.clone()))
.map(|(symbol, (_, _, decl, _))| (symbol.clone(), decl.clone()))
.collect::<Vec<_>>();
for (symbol, decl) in src_ns.symbols.iter() {
if is_ancestor(src, dst) || decl.visibility(decl_engine).is_public() {
Expand All @@ -323,7 +330,7 @@ impl Module {
}

let mut symbols_paths_and_decls = vec![];
for (symbol, (mod_path, _, decl)) in use_synonyms {
for (symbol, (mod_path, _, decl, _)) in use_synonyms {
let mut is_external = false;
let submodule = src_ns.submodule(&[mod_path[0].clone()]);
if let Some(submodule) = submodule {
Expand All @@ -348,7 +355,7 @@ impl Module {
let mut try_add = |symbol, path, decl: ty::TyDecl| {
dst_ns
.use_synonyms
.insert(symbol, (path, GlobImport::Yes, decl));
.insert(symbol, (path, GlobImport::Yes, decl, is_src_absolute));
};

for (symbol, decl) in symbols_and_decls {
Expand All @@ -372,9 +379,10 @@ impl Module {
src: &Path,
dst: &Path,
alias: Option<Ident>,
is_src_absolute: bool,
) -> CompileResult<()> {
let (last_item, src) = src.split_last().expect("guaranteed by grammar");
self.item_import(engines, src, last_item, dst, alias)
self.item_import(engines, src, last_item, dst, alias, is_src_absolute)
}

/// Pull a single `item` from the given `src` module and import it into the `dst` module.
Expand All @@ -387,6 +395,7 @@ impl Module {
item: &Ident,
dst: &Path,
alias: Option<Ident>,
is_src_absolute: bool,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
Expand Down Expand Up @@ -429,12 +438,13 @@ impl Module {
// no matter what, import it this way though.
let dst_ns = &mut self[dst];
let add_synonym = |name| {
if let Some((_, GlobImport::No, _)) = dst_ns.use_synonyms.get(name) {
if let Some((_, GlobImport::No, _, _)) = dst_ns.use_synonyms.get(name) {
errors.push(CompileError::ShadowsOtherSymbol { name: name.clone() });
}
dst_ns
.use_synonyms
.insert(name.clone(), (src.to_vec(), GlobImport::No, decl));
dst_ns.use_synonyms.insert(
name.clone(),
(src.to_vec(), GlobImport::No, decl, is_src_absolute),
);
};
match alias {
Some(alias) => {
Expand Down Expand Up @@ -473,6 +483,7 @@ impl Module {
variant_name: &Ident,
dst: &Path,
alias: Option<Ident>,
is_src_absolute: bool,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
Expand Down Expand Up @@ -520,7 +531,7 @@ impl Module {
// import it this way.
let dst_ns = &mut self[dst];
let mut add_synonym = |name| {
if let Some((_, GlobImport::No, _)) = dst_ns.use_synonyms.get(name) {
if let Some((_, GlobImport::No, _, _)) = dst_ns.use_synonyms.get(name) {
errors
.push(CompileError::ShadowsOtherSymbol { name: name.clone() });
}
Expand All @@ -534,6 +545,7 @@ impl Module {
variant_name: variant_name.clone(),
variant_decl_span: variant_decl.span.clone(),
}),
is_src_absolute,
),
);
};
Expand Down Expand Up @@ -582,6 +594,7 @@ impl Module {
dst: &Path,
engines: &Engines,
enum_name: &Ident,
is_src_absolute: bool,
) -> CompileResult<()> {
let mut warnings = vec![];
let mut errors = vec![];
Expand Down Expand Up @@ -638,6 +651,7 @@ impl Module {
variant_name,
variant_decl_span: variant_decl.span.clone(),
}),
is_src_absolute,
),
);
}
Expand Down
32 changes: 25 additions & 7 deletions sway-core/src/semantic_analysis/namespace/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,14 @@ impl Namespace {
}

/// Short-hand for performing a [Module::star_import] with `mod_path` as the destination.
pub(crate) fn star_import(&mut self, src: &Path, engines: &Engines) -> CompileResult<()> {
self.root.star_import(src, &self.mod_path, engines)
pub(crate) fn star_import(
&mut self,
src: &Path,
engines: &Engines,
is_absolute: bool,
) -> CompileResult<()> {
self.root
.star_import(src, &self.mod_path, engines, is_absolute)
}

/// Short-hand for performing a [Module::variant_star_import] with `mod_path` as the destination.
Expand All @@ -519,9 +525,10 @@ impl Namespace {
src: &Path,
engines: &Engines,
enum_name: &Ident,
is_absolute: bool,
) -> CompileResult<()> {
self.root
.variant_star_import(src, &self.mod_path, engines, enum_name)
.variant_star_import(src, &self.mod_path, engines, enum_name, is_absolute)
}

/// Short-hand for performing a [Module::self_import] with `mod_path` as the destination.
Expand All @@ -530,8 +537,10 @@ impl Namespace {
engines: &Engines,
src: &Path,
alias: Option<Ident>,
is_absolute: bool,
) -> CompileResult<()> {
self.root.self_import(engines, src, &self.mod_path, alias)
self.root
.self_import(engines, src, &self.mod_path, alias, is_absolute)
}

/// Short-hand for performing a [Module::item_import] with `mod_path` as the destination.
Expand All @@ -541,9 +550,10 @@ impl Namespace {
src: &Path,
item: &Ident,
alias: Option<Ident>,
is_absolute: bool,
) -> CompileResult<()> {
self.root
.item_import(engines, src, item, &self.mod_path, alias)
.item_import(engines, src, item, &self.mod_path, alias, is_absolute)
}

/// Short-hand for performing a [Module::variant_import] with `mod_path` as the destination.
Expand All @@ -554,9 +564,17 @@ impl Namespace {
enum_name: &Ident,
variant_name: &Ident,
alias: Option<Ident>,
is_absolute: bool,
) -> CompileResult<()> {
self.root
.variant_import(engines, src, enum_name, variant_name, &self.mod_path, alias)
self.root.variant_import(
engines,
src,
enum_name,
variant_name,
&self.mod_path,
alias,
is_absolute,
)
}

/// "Enter" the submodule at the given path by returning a new [SubmoduleNamespace].
Expand Down
6 changes: 4 additions & 2 deletions sway-core/src/semantic_analysis/namespace/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ impl Root {
.get(symbol.as_str())
.unwrap_or(symbol);
match module.use_synonyms.get(symbol) {
Some((_, _, decl @ ty::TyDecl::EnumVariantDecl { .. })) => ok(decl, vec![], vec![]),
Some((src_path, _, _)) if mod_path != src_path => {
Some((_, _, decl @ ty::TyDecl::EnumVariantDecl { .. }, _)) => {
ok(decl, vec![], vec![])
}
Some((src_path, _, _, _)) if mod_path != src_path => {
// TODO: check that the symbol import is public?
self.resolve_symbol(src_path, true_symbol)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'core'
source = 'path+from-root-9F4EED204534DB2D'

[[package]]
name = 'std'
source = 'path+from-root-9F4EED204534DB2D'
dependencies = ['core']

[[package]]
name = 'use_absolute_path'
source = 'member'
dependencies = ['std']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "use_absolute_path"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"configurables": [],
"functions": [
{
"attributes": null,
"inputs": [],
"name": "main",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
}
],
"loggedTypes": [],
"messagesTypes": [],
"types": [
{
"components": null,
"type": "u64",
"typeId": 0,
"typeParameters": null
}
]
}
Loading

0 comments on commit e8d6472

Please sign in to comment.