From c9feaae1c0f7f2ce8c1cf2e82852619709b2ab36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C5=9Bkowicz?= Date: Fri, 22 Dec 2023 12:00:24 +0100 Subject: [PATCH] Add support for compiler experimental features commit-id:480c1b28 --- scarb-metadata/Cargo.toml | 1 + scarb-metadata/src/lib.rs | 4 +++ scarb/src/compiler/db.rs | 12 ++++++- scarb/src/core/manifest/mod.rs | 2 ++ scarb/src/core/manifest/toml_manifest.rs | 14 ++++++++ .../core/publishing/manifest_normalization.rs | 1 + scarb/src/ops/metadata.rs | 13 ++++++++ scarb/tests/metadata.rs | 32 +++++++++++++++++++ website/docs/reference/manifest.md | 9 ++++++ website/docs/reference/workspaces.md | 1 + 10 files changed, 88 insertions(+), 1 deletion(-) diff --git a/scarb-metadata/Cargo.toml b/scarb-metadata/Cargo.toml index 58b62e01e..f5783eb82 100644 --- a/scarb-metadata/Cargo.toml +++ b/scarb-metadata/Cargo.toml @@ -13,6 +13,7 @@ readme = "README.md" repository.workspace = true [dependencies] +cairo-lang-filesystem.workspace = true camino.workspace = true derive_builder = { workspace = true, optional = true } semver.workspace = true diff --git a/scarb-metadata/src/lib.rs b/scarb-metadata/src/lib.rs index 5c8bd5f11..6622537c3 100644 --- a/scarb-metadata/src/lib.rs +++ b/scarb-metadata/src/lib.rs @@ -17,6 +17,7 @@ //! With the `command` feature (enabled by default), this crate also exposes an ergonomic interface //! to collect metadata from Scarb: [`MetadataCommand`]. +use cairo_lang_filesystem::db::ExperimentalFeaturesConfig; use std::collections::{BTreeMap, HashMap}; use std::fmt; use std::ops::Index; @@ -231,6 +232,9 @@ pub struct PackageMetadata { #[serde(flatten)] pub manifest_metadata: ManifestMetadata, + /// Compiler experimental features allowed for this package. + pub experimental_features: ExperimentalFeaturesConfig, + /// Additional data not captured by deserializer. #[cfg_attr(feature = "builder", builder(default))] #[serde(flatten)] diff --git a/scarb/src/compiler/db.rs b/scarb/src/compiler/db.rs index 84a2de99a..05097e956 100644 --- a/scarb/src/compiler/db.rs +++ b/scarb/src/compiler/db.rs @@ -97,7 +97,17 @@ fn build_project_config(unit: &CompilationUnit) -> Result { component.cairo_package_name(), CrateSettings { edition: component.package.manifest.edition, - experimental_features: Default::default(), + experimental_features: cairo_lang_filesystem::db::ExperimentalFeaturesConfig { + negative_impls: component + .package + .manifest + .metadata + .experimental + .clone() + .unwrap_or_default() + .negative_impls + .unwrap_or_default(), + }, }, ) }) diff --git a/scarb/src/core/manifest/mod.rs b/scarb/src/core/manifest/mod.rs index d33ebdc6f..880e2dcc9 100644 --- a/scarb/src/core/manifest/mod.rs +++ b/scarb/src/core/manifest/mod.rs @@ -67,6 +67,8 @@ pub struct ManifestMetadata { #[serde(rename = "tool")] pub tool_metadata: Option>, pub cairo_version: Option, + /// Allow experimental features. + pub experimental: Option, } impl ManifestBuilder { diff --git a/scarb/src/core/manifest/toml_manifest.rs b/scarb/src/core/manifest/toml_manifest.rs index 5fbf580cf..1f4a43a0c 100644 --- a/scarb/src/core/manifest/toml_manifest.rs +++ b/scarb/src/core/manifest/toml_manifest.rs @@ -119,6 +119,7 @@ pub struct PackageInheritableFields { pub readme: Option, pub repository: Option, pub cairo_version: Option, + pub experimental: Option, } macro_rules! get_field { @@ -147,6 +148,7 @@ impl PackageInheritableFields { get_field!(license_file, Utf8PathBuf); get_field!(repository, String); get_field!(edition, Edition); + get_field!(experimental, ScarbExperimentalFeaturesConfig); pub fn readme(&self, workspace_root: &Utf8Path, package_root: &Utf8Path) -> Result { let Ok(Some(readme)) = readme_for_package(workspace_root, self.readme.as_ref()) else { @@ -198,6 +200,13 @@ pub struct TomlPackage { /// **UNSTABLE** This package does not depend on Cairo's `core`. pub no_core: Option, pub cairo_version: Option>, + pub experimental: Option>, +} + +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct ScarbExperimentalFeaturesConfig { + pub negative_impls: Option, } #[derive(Clone, Debug, Serialize, Eq, PartialEq)] @@ -547,6 +556,11 @@ impl TomlManifest { .clone() .map(|mw| mw.resolve("cairo_version", || inheritable_package.cairo_version())) .transpose()?, + experimental: package + .experimental + .clone() + .map(|mw| mw.resolve("experimental", || inheritable_package.experimental())) + .transpose()?, }; let edition = package diff --git a/scarb/src/core/publishing/manifest_normalization.rs b/scarb/src/core/publishing/manifest_normalization.rs index 993534798..ea9984cc6 100644 --- a/scarb/src/core/publishing/manifest_normalization.rs +++ b/scarb/src/core/publishing/manifest_normalization.rs @@ -75,6 +75,7 @@ fn generate_package(pkg: &Package) -> Box { repository: metadata.repository.clone().map(MaybeWorkspace::Defined), no_core: summary.no_core.then_some(true), cairo_version: metadata.cairo_version.clone().map(MaybeWorkspace::Defined), + experimental: metadata.experimental.clone().map(MaybeWorkspace::Defined), }) } diff --git a/scarb/src/ops/metadata.rs b/scarb/src/ops/metadata.rs index 0ec9ab137..081ce4c40 100644 --- a/scarb/src/ops/metadata.rs +++ b/scarb/src/ops/metadata.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, HashMap}; use anyhow::{bail, Result}; +use cairo_lang_filesystem::db::ExperimentalFeaturesConfig; use itertools::Itertools; use semver::{Version, VersionReq}; use smol_str::SmolStr; @@ -135,6 +136,17 @@ fn collect_package_metadata(package: &Package) -> m::PackageMetadata { let edition = edition_variant(package.manifest.edition); + let experimental_features = ExperimentalFeaturesConfig { + negative_impls: package + .manifest + .metadata + .experimental + .clone() + .unwrap_or_default() + .negative_impls + .unwrap_or_default(), + }; + m::PackageMetadataBuilder::default() .id(wrap_package_id(package.id)) .name(package.id.name.clone()) @@ -146,6 +158,7 @@ fn collect_package_metadata(package: &Package) -> m::PackageMetadata { .dependencies(dependencies) .targets(targets) .manifest_metadata(manifest_metadata) + .experimental_features(experimental_features) .build() .unwrap() } diff --git a/scarb/tests/metadata.rs b/scarb/tests/metadata.rs index 91b6005f4..93dce3e19 100644 --- a/scarb/tests/metadata.rs +++ b/scarb/tests/metadata.rs @@ -1199,3 +1199,35 @@ fn includes_edition() { } panic!("Package not found in metadata!"); } + +#[test] +fn includes_experimental_features() { + let t = assert_fs::TempDir::new().unwrap(); + ProjectBuilder::start() + .name("hello") + .version("0.1.0") + .manifest_extra(indoc! { + r#" + [package.experimental] + negative-impls = true + "# + }) + .build(&t); + + let metadata = Scarb::quick_snapbox() + .arg("--json") + .arg("metadata") + .arg("--format-version") + .arg("1") + .current_dir(&t) + .stdout_json::(); + + assert!( + packages_by_name(metadata) + .get("hello") + .unwrap() + .clone() + .experimental_features + .negative_impls + ) +} diff --git a/website/docs/reference/manifest.md b/website/docs/reference/manifest.md index c414e6234..41a659b6e 100644 --- a/website/docs/reference/manifest.md +++ b/website/docs/reference/manifest.md @@ -209,6 +209,15 @@ Keys are human-readable link names, and values are URLs. "We're hiring" = "https://swmansion.com/careers/" ``` +### `experimental` + +This field is responsible for setting experimental flags to be used on the package for the compiler. + +```toml +[package.experimental] +negative-impls = true +``` + ## `[dependencies]` See [Specifying Dependencies](./specifying-dependencies) page. diff --git a/website/docs/reference/workspaces.md b/website/docs/reference/workspaces.md index 70a07175e..980e58fa6 100644 --- a/website/docs/reference/workspaces.md +++ b/website/docs/reference/workspaces.md @@ -100,6 +100,7 @@ Keys that are supported: - `readme` - `repository` - `cairo-version` +- `experimental` (See [manifest](./manifest) for more information on the meaning of inheritable keys.)