Skip to content

Commit

Permalink
Remove the global DeclarationEngine (FuelLabs#3411)
Browse files Browse the repository at this point in the history
This PR removes the global `DeclarationEngine` in favor of keeping a
local copy in the `TypeCheckContext`.

This PR is pretty big... there aren't any additional things added other
than what I """ had to add """ in order to complete this task. At a high
level:

- This PR introduces the `Engines` struct, which has two fields
`type_engine: &TypeEngine` and `declaration_engine: &DeclarationEngine`.
- For most/many of the traits introduced in FuelLabs#3353, this PR changes these
traits to take a `Engines` instead of a `&TypeEngine`

Closes FuelLabs#2063

Co-authored-by: emilyaherbert <[email protected]>
  • Loading branch information
emilyaherbert and emilyaherbert authored Dec 22, 2022
1 parent cdfc56c commit 978de4d
Show file tree
Hide file tree
Showing 111 changed files with 4,018 additions and 3,343 deletions.
63 changes: 26 additions & 37 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ use std::{
str::FromStr,
};
use sway_core::{
declaration_engine::DeclarationEngine,
fuel_prelude::{
fuel_crypto,
fuel_tx::{self, Contract, ContractId, StorageSlot},
},
TypeEngine,
Engines, TypeEngine,
};
use sway_core::{
language::{
Expand Down Expand Up @@ -94,6 +95,7 @@ pub struct BuiltPackage {
pub tree_type: TreeType,
source_map: SourceMap,
pub pkg_name: String,
pub declaration_engine: DeclarationEngine,
}

/// The result of successfully compiling a workspace.
Expand Down Expand Up @@ -2169,9 +2171,9 @@ pub fn dependency_namespace(
graph: &Graph,
node: NodeIx,
constants: BTreeMap<String, ConfigTimeConstant>,
type_engine: &TypeEngine,
engines: Engines<'_>,
) -> Result<namespace::Module, vec1::Vec1<CompileError>> {
let mut namespace = namespace::Module::default_with_constants(type_engine, constants)?;
let mut namespace = namespace::Module::default_with_constants(engines, constants)?;

// Add direct dependencies.
let mut core_added = false;
Expand Down Expand Up @@ -2202,7 +2204,7 @@ pub fn dependency_namespace(
public: true,
};
constants.insert(contract_dep_constant_name.to_string(), contract_id_constant);
namespace::Module::default_with_constants(type_engine, constants)?
namespace::Module::default_with_constants(engines, constants)?
}
};
namespace.insert_submodule(dep_name, dep_namespace);
Expand All @@ -2220,18 +2222,10 @@ pub fn dependency_namespace(
}
}

namespace.star_import_with_reexports(
&[CORE, PRELUDE].map(Ident::new_no_span),
&[],
type_engine,
);
namespace.star_import_with_reexports(&[CORE, PRELUDE].map(Ident::new_no_span), &[], engines);

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

Ok(namespace)
Expand Down Expand Up @@ -2291,16 +2285,15 @@ fn find_core_dep(graph: &Graph, node: NodeIx) -> Option<NodeIx> {

/// Compiles the package to an AST.
pub fn compile_ast(
type_engine: &TypeEngine,
engines: Engines<'_>,
manifest: &PackageManifestFile,
build_profile: &BuildProfile,
namespace: namespace::Module,
) -> Result<CompileResult<ty::TyProgram>> {
let source = manifest.entry_string()?;
let sway_build_config =
sway_build_config(manifest.dir(), &manifest.entry_path(), build_profile)?;
let ast_res =
sway_core::compile_to_ast(type_engine, source, namespace, Some(&sway_build_config));
let ast_res = sway_core::compile_to_ast(engines, source, namespace, Some(&sway_build_config));
Ok(ast_res)
}

Expand All @@ -2327,7 +2320,7 @@ pub fn compile(
manifest: &PackageManifestFile,
build_profile: &BuildProfile,
namespace: namespace::Module,
type_engine: &TypeEngine,
engines: Engines<'_>,
source_map: &mut SourceMap,
) -> Result<(BuiltPackage, namespace::Root)> {
// Time the given expression and print the result if `build_config.time_phases` is true.
Expand Down Expand Up @@ -2362,7 +2355,7 @@ pub fn compile(
// First, compile to an AST. We'll update the namespace and check for JSON ABI output.
let ast_res = time_expr!(
"compile to ast",
compile_ast(type_engine, manifest, build_profile, namespace)?
compile_ast(engines, manifest, build_profile, namespace)?
);
let typed_program = match ast_res.value.as_ref() {
None => return fail(&ast_res.warnings, &ast_res.errors),
Expand All @@ -2376,7 +2369,7 @@ pub fn compile(
let mut types = vec![];
let json_abi_program = time_expr!(
"generate JSON ABI program",
typed_program.generate_json_abi_program(type_engine, &mut types)
typed_program.generate_json_abi_program(engines.te(), &mut types)
);

let storage_slots = typed_program.storage_slots.clone();
Expand All @@ -2390,7 +2383,7 @@ pub fn compile(

let asm_res = time_expr!(
"compile ast to asm",
sway_core::ast_to_asm(type_engine, &ast_res, &sway_build_config)
sway_core::ast_to_asm(engines, &ast_res, &sway_build_config)
);
let entries = asm_res
.value
Expand All @@ -2414,6 +2407,7 @@ pub fn compile(
entries,
source_map: source_map.to_owned(),
pkg_name: pkg.name.clone(),
declaration_engine: engines.de().clone(),
};
Ok((built_package, namespace))
}
Expand Down Expand Up @@ -2614,8 +2608,6 @@ pub fn build(
profile: &BuildProfile,
outputs: &HashSet<NodeIx>,
) -> anyhow::Result<Vec<(NodeIx, BuiltPackage)>> {
//TODO remove once type engine isn't global anymore.
sway_core::clear_lazy_statics();
let mut built_packages = Vec::new();

let required: HashSet<NodeIx> = outputs
Expand All @@ -2624,6 +2616,9 @@ pub fn build(
.collect();

let type_engine = TypeEngine::default();
let declaration_engine = DeclarationEngine::default();
let engines = Engines::new(&type_engine, &declaration_engine);

let mut lib_namespace_map = Default::default();
let mut compiled_contract_deps = HashMap::new();
for &node in plan
Expand All @@ -2641,7 +2636,7 @@ pub fn build(
&plan.graph,
node,
constants,
&type_engine,
engines,
) {
Ok(o) => o,
Err(errs) => {
Expand All @@ -2654,7 +2649,7 @@ pub fn build(
manifest,
profile,
dep_namespace,
&type_engine,
engines,
&mut source_map,
)?;
let (mut built_package, namespace) = res;
Expand Down Expand Up @@ -2813,10 +2808,8 @@ type ParseAndTypedPrograms = CompileResult<(ParseProgram, Option<ty::TyProgram>)
pub fn check(
plan: &BuildPlan,
terse_mode: bool,
type_engine: &TypeEngine,
engines: Engines<'_>,
) -> anyhow::Result<Vec<ParseAndTypedPrograms>> {
//TODO remove once type engine isn't global anymore.
sway_core::clear_lazy_statics();
let mut lib_namespace_map = Default::default();
let mut source_map = SourceMap::new();
// During `check`, we don't compile so this stays empty.
Expand All @@ -2833,14 +2826,14 @@ pub fn check(
&plan.graph,
node,
constants,
type_engine,
engines,
)
.expect("failed to create dependency namespace");
let CompileResult {
value,
mut warnings,
mut errors,
} = parse(manifest, terse_mode, type_engine)?;
} = parse(manifest, terse_mode, engines)?;

let parse_program = match value {
None => {
Expand All @@ -2850,7 +2843,7 @@ pub fn check(
Some(program) => program,
};

let ast_result = sway_core::parsed_to_ast(type_engine, &parse_program, dep_namespace, None);
let ast_result = sway_core::parsed_to_ast(engines, &parse_program, dep_namespace, None);
warnings.extend(ast_result.warnings);
errors.extend(ast_result.errors);

Expand Down Expand Up @@ -2884,19 +2877,15 @@ pub fn check(
pub fn parse(
manifest: &PackageManifestFile,
terse_mode: bool,
type_engine: &TypeEngine,
engines: Engines<'_>,
) -> anyhow::Result<CompileResult<ParseProgram>> {
let profile = BuildProfile {
terse: terse_mode,
..BuildProfile::debug()
};
let source = manifest.entry_string()?;
let sway_build_config = sway_build_config(manifest.dir(), &manifest.entry_path(), &profile)?;
Ok(sway_core::parse(
source,
type_engine,
Some(&sway_build_config),
))
Ok(sway_core::parse(source, engines, Some(&sway_build_config)))
}

/// Attempt to find a `Forc.toml` with the given project name within the given directory.
Expand Down
25 changes: 13 additions & 12 deletions forc-plugins/forc-doc/src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) enum Descriptor {
impl Descriptor {
/// Decides whether a [TyDeclaration] is [Descriptor::Documentable].
pub(crate) fn from_typed_decl(
declaration_engine: &DeclarationEngine,
ty_decl: &TyDeclaration,
module_prefix: Vec<String>,
document_private_items: bool,
Expand All @@ -33,7 +34,8 @@ impl Descriptor {
use TyDeclaration::*;
match ty_decl {
StructDeclaration(ref decl_id) => {
let struct_decl = de_get_struct(decl_id.clone(), &decl_id.span())?;
let struct_decl =
declaration_engine.get_struct(decl_id.clone(), &decl_id.span())?;
if !document_private_items && struct_decl.visibility.is_private() {
Ok(Descriptor::NonDocumentable)
} else {
Expand Down Expand Up @@ -65,7 +67,7 @@ impl Descriptor {
}
}
EnumDeclaration(ref decl_id) => {
let enum_decl = de_get_enum(decl_id.clone(), &decl_id.span())?;
let enum_decl = declaration_engine.get_enum(decl_id.clone(), &decl_id.span())?;
if !document_private_items && enum_decl.visibility.is_private() {
Ok(Descriptor::NonDocumentable)
} else {
Expand Down Expand Up @@ -97,7 +99,7 @@ impl Descriptor {
}
}
TraitDeclaration(ref decl_id) => {
let trait_decl = de_get_trait(decl_id.clone(), &decl_id.span())?;
let trait_decl = declaration_engine.get_trait(decl_id.clone(), &decl_id.span())?;
if !document_private_items && trait_decl.visibility.is_private() {
Ok(Descriptor::NonDocumentable)
} else {
Expand Down Expand Up @@ -129,7 +131,7 @@ impl Descriptor {
}
}
AbiDeclaration(ref decl_id) => {
let abi_decl = de_get_abi(decl_id.clone(), &decl_id.span())?;
let abi_decl = declaration_engine.get_abi(decl_id.clone(), &decl_id.span())?;
let item_name = abi_decl.name.as_str().to_string();
let attrs_opt = (!abi_decl.attributes.is_empty())
.then(|| attrsmap_to_html_string(&abi_decl.attributes));
Expand All @@ -155,7 +157,8 @@ impl Descriptor {
}))
}
StorageDeclaration(ref decl_id) => {
let storage_decl = de_get_storage(decl_id.clone(), &decl_id.span())?;
let storage_decl =
declaration_engine.get_storage(decl_id.clone(), &decl_id.span())?;
let item_name = CONTRACT_STORAGE.to_string();
let attrs_opt = (!storage_decl.attributes.is_empty())
.then(|| attrsmap_to_html_string(&storage_decl.attributes));
Expand Down Expand Up @@ -183,11 +186,8 @@ impl Descriptor {
}))
}
ImplTrait(ref decl_id) => {
// TODO: figure out how to use this, likely we don't want to document this directly.
//
// This declaration type may make more sense to document as part of another declaration
// much like how we document method functions for traits or fields on structs.
let impl_trait = de_get_impl_trait(decl_id.clone(), &decl_id.span())?;
let impl_trait =
declaration_engine.get_impl_trait(decl_id.clone(), &decl_id.span())?;
let item_name = impl_trait.trait_name.suffix.as_str().to_string();

Ok(Descriptor::Documentable(Document {
Expand All @@ -211,7 +211,7 @@ impl Descriptor {
}))
}
FunctionDeclaration(ref decl_id) => {
let fn_decl = de_get_function(decl_id.clone(), &decl_id.span())?;
let fn_decl = declaration_engine.get_function(decl_id.clone(), &decl_id.span())?;
if !document_private_items && fn_decl.visibility.is_private() {
Ok(Descriptor::NonDocumentable)
} else {
Expand Down Expand Up @@ -241,7 +241,8 @@ impl Descriptor {
}
}
ConstantDeclaration(ref decl_id) => {
let const_decl = de_get_constant(decl_id.clone(), &decl_id.span())?;
let const_decl =
declaration_engine.get_constant(decl_id.clone(), &decl_id.span())?;
if !document_private_items && const_decl.visibility.is_private() {
Ok(Descriptor::NonDocumentable)
} else {
Expand Down
19 changes: 15 additions & 4 deletions forc-plugins/forc-doc/src/doc.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use std::sync::Arc;

use crate::{
descriptor::Descriptor,
render::{ItemBody, ItemHeader},
};
use anyhow::Result;
use horrorshow::{box_html, RenderBox};
use sway_core::language::ty::{TyAstNodeContent, TyProgram, TySubmodule};
use sway_core::{
declaration_engine::DeclarationEngine,
language::ty::{TyAstNodeContent, TyProgram, TySubmodule},
};

pub(crate) type Documentation = Vec<Document>;
/// A finalized Document ready to be rendered. We want to retain all
Expand Down Expand Up @@ -38,6 +43,7 @@ impl Document {
}
/// Gather [Documentation] from the [TyProgram].
pub(crate) fn from_ty_program(
declaration_engine: &DeclarationEngine,
project_name: &str,
typed_program: &TyProgram,
no_deps: bool,
Expand All @@ -48,6 +54,7 @@ impl Document {
for ast_node in &typed_program.root.all_nodes {
if let TyAstNodeContent::Declaration(ref decl) = ast_node.content {
let desc = Descriptor::from_typed_decl(
declaration_engine,
decl,
vec![project_name.to_owned()],
document_private_items,
Expand All @@ -64,6 +71,7 @@ impl Document {
for (_, ref typed_submodule) in &typed_program.root.submodules {
let module_prefix = vec![project_name.to_owned()];
Document::from_ty_submodule(
declaration_engine,
typed_submodule,
&mut docs,
&module_prefix,
Expand All @@ -75,6 +83,7 @@ impl Document {
Ok(docs)
}
fn from_ty_submodule(
declaration_engine: &DeclarationEngine,
typed_submodule: &TySubmodule,
docs: &mut Documentation,
module_prefix: &[String],
Expand All @@ -85,6 +94,7 @@ impl Document {
for ast_node in &typed_submodule.module.all_nodes {
if let TyAstNodeContent::Declaration(ref decl) = ast_node.content {
let desc = Descriptor::from_typed_decl(
declaration_engine,
decl,
new_submodule_prefix.clone(),
document_private_items,
Expand All @@ -98,6 +108,7 @@ impl Document {
// if there is another submodule we need to go a level deeper
if let Some((_, submodule)) = typed_submodule.module.submodules.first() {
Document::from_ty_submodule(
declaration_engine,
submodule,
docs,
&new_submodule_prefix,
Expand All @@ -109,10 +120,10 @@ impl Document {
}
}
impl crate::render::Renderable for Document {
fn render(self) -> Box<dyn RenderBox> {
fn render(self, declaration_engine: Arc<DeclarationEngine>) -> Box<dyn RenderBox> {
box_html! {
: self.item_header.render();
: self.item_body.render();
: self.item_header.render(declaration_engine.clone());
: self.item_body.render(declaration_engine);
}
}
}
Loading

0 comments on commit 978de4d

Please sign in to comment.