Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 9 additions & 2 deletions compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,17 @@ pub struct CompileOptions {
#[arg(long, hide = true)]
pub debug_compile_stdin: bool,

/// Unstable features to enable for this current build
/// Unstable features to enable for this current build.
///
/// If non-empty, it disables unstable features required in crate manifests.
#[arg(value_parser = clap::value_parser!(UnstableFeature))]
#[clap(long, short = 'Z', value_delimiter = ',')]
#[clap(long, short = 'Z', value_delimiter = ',', conflicts_with = "no_unstable_features")]
pub unstable_features: Vec<UnstableFeature>,

/// Disable any unstable features required in crate manifests.
#[arg(long, conflicts_with = "unstable_features")]
pub no_unstable_features: bool,

/// Used internally to avoid comptime println from producing output
#[arg(long, hide = true)]
pub disable_comptime_printing: bool,
Expand Down Expand Up @@ -268,6 +274,7 @@ impl CompileOptions {
debug_comptime_in_file: self.debug_comptime_in_file.as_deref(),
pedantic_solving: self.pedantic_solving,
enabled_unstable_features: &self.unstable_features,
disable_required_unstable_features: self.no_unstable_features,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/elaborator/comptime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ impl<'context> Elaborator<'context> {
self.usage_tracker,
self.crate_graph,
self.interpreter_output,
self.required_unstable_features,
self.crate_id,
self.interpreter_call_stack.clone(),
self.options,
Expand Down
28 changes: 25 additions & 3 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ pub struct Elaborator<'context> {
pub(crate) crate_graph: &'context CrateGraph,
pub(crate) interpreter_output: &'context Option<Rc<RefCell<dyn std::io::Write>>>,

required_unstable_features: &'context BTreeMap<CrateId, Vec<UnstableFeature>>,

unsafe_block_status: UnsafeBlockStatus,
current_loop: Option<Loop>,

Expand Down Expand Up @@ -244,6 +246,7 @@ impl<'context> Elaborator<'context> {
usage_tracker: &'context mut UsageTracker,
crate_graph: &'context CrateGraph,
interpreter_output: &'context Option<Rc<RefCell<dyn std::io::Write>>>,
required_unstable_features: &'context BTreeMap<CrateId, Vec<UnstableFeature>>,
crate_id: CrateId,
interpreter_call_stack: im::Vector<Location>,
options: ElaboratorOptions<'context>,
Expand All @@ -257,6 +260,7 @@ impl<'context> Elaborator<'context> {
usage_tracker,
crate_graph,
interpreter_output,
required_unstable_features,
unsafe_block_status: UnsafeBlockStatus::NotInUnsafeBlock,
current_loop: None,
generics: Vec::new(),
Expand Down Expand Up @@ -290,6 +294,7 @@ impl<'context> Elaborator<'context> {
&mut context.usage_tracker,
&context.crate_graph,
&context.interpreter_output,
&context.required_unstable_features,
crate_id,
im::Vector::new(),
options,
Expand Down Expand Up @@ -2382,10 +2387,27 @@ impl<'context> Elaborator<'context> {
/// Register a use of the given unstable feature. Errors if the feature has not
/// been explicitly enabled in this package.
pub fn use_unstable_feature(&mut self, feature: UnstableFeature, location: Location) {
if !self.options.enabled_unstable_features.contains(&feature) {
let reason = ParserErrorReason::ExperimentalFeature(feature);
self.push_err(ParserError::with_reason(reason, location));
// Is the feature globally enabled via CLI options?
if self.options.enabled_unstable_features.contains(&feature) {
return;
}

// Can crates require unstable features in their manifest?
let enable_required_unstable_features = self.options.enabled_unstable_features.is_empty()
&& !self.options.disable_required_unstable_features;

// Is it required by the current crate?
if enable_required_unstable_features
&& self
.required_unstable_features
.get(&self.crate_id)
.is_some_and(|fs| fs.contains(&feature))
{
return;
}

let reason = ParserErrorReason::ExperimentalFeature(feature);
self.push_err(ParserError::with_reason(reason, location));
}

/// Run the given function using the resolver and return true if any errors (not warnings)
Expand Down
4 changes: 4 additions & 0 deletions compiler/noirc_frontend/src/elaborator/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ pub struct GenericOptions<'a, T> {
/// Unstable compiler features that were explicitly enabled. Any unstable features
/// that are not in this list result in an error when used.
pub enabled_unstable_features: &'a [UnstableFeature],

/// Deny crates from requiring unstable features.
pub disable_required_unstable_features: bool,
}

/// Options from nargo_cli that need to be passed down to the elaborator
Expand All @@ -57,6 +60,7 @@ impl<T> GenericOptions<'_, T> {
debug_comptime_in_file: None,
pedantic_solving: true,
enabled_unstable_features: &[UnstableFeature::Enums],
disable_required_unstable_features: true,
}
}
}
1 change: 1 addition & 0 deletions compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ impl DefCollector {
debug_comptime_in_file,
pedantic_solving: options.pedantic_solving,
enabled_unstable_features: options.enabled_unstable_features,
disable_required_unstable_features: options.disable_required_unstable_features,
};

let mut more_errors =
Expand Down
6 changes: 6 additions & 0 deletions compiler/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod type_check;

use crate::ast::UnresolvedGenerics;
use crate::debug::DebugInstrumenter;
use crate::elaborator::UnstableFeature;
use crate::graph::{CrateGraph, CrateId};
use crate::hir_def::function::FuncMeta;
use crate::node_interner::{FuncId, NodeInterner, TypeId};
Expand Down Expand Up @@ -56,6 +57,9 @@ pub struct Context<'file_manager, 'parsed_files> {

/// Writer for comptime prints.
pub interpreter_output: Option<Rc<RefCell<dyn std::io::Write>>>,

/// Any unstable features required by the current package or its dependencies.
pub required_unstable_features: BTreeMap<CrateId, Vec<UnstableFeature>>,
}

#[derive(Debug)]
Expand All @@ -78,6 +82,7 @@ impl Context<'_, '_> {
parsed_files: Cow::Owned(parsed_files),
package_build_path: PathBuf::default(),
interpreter_output: Some(Rc::new(RefCell::new(std::io::stdout()))),
required_unstable_features: BTreeMap::new(),
}
}

Expand All @@ -96,6 +101,7 @@ impl Context<'_, '_> {
parsed_files: Cow::Borrowed(parsed_files),
package_build_path: PathBuf::default(),
interpreter_output: Some(Rc::new(RefCell::new(std::io::stdout()))),
required_unstable_features: BTreeMap::new(),
}
}

Expand Down
1 change: 1 addition & 0 deletions docs/docs/getting_started/project_breakdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ The package section defines a number of fields including:
- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract
- `authors` (optional) - authors of the project
- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html)
- `compiler_unstable_features` (optional) - A list of unstable features required by this package to compile.
- `description` (optional)
- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`)
- `backend` (optional)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,13 @@ Run the fuzzing harnesses for this program
Possible values: `true`, `false`

* `-Z`, `--unstable-features <UNSTABLE_FEATURES>` — Unstable features to enable for this current build

* `--no-unstable-features` — Disable unstable features required by crates in their manifests

Default value: `false`

Possible values: `true`, `false`

* `--oracle-resolver <ORACLE_RESOLVER>` — JSON RPC url to solve oracle calls
* `--timeout <TIMEOUT>` — Maximum time in seconds to spend fuzzing (default: no timeout)

Expand All @@ -690,6 +697,7 @@ Run the fuzzing harnesses for this program




## `nargo info`

Provides detailed information on each of a program's function (represented by a single circuit)
Expand Down Expand Up @@ -855,4 +863,3 @@ Generates a shell completion script for your favorite shell
This document was generated automatically by
<a href="https://crates.io/crates/clap-markdown"><code>clap-markdown</code></a>.
</i></small>

4 changes: 4 additions & 0 deletions tooling/lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ fn byte_span_to_range<'a, F: files::Files<'a> + ?Sized>(
}
}

/// Create a workspace based on the source file location:
/// * if there is a `Nargo.toml` file, use it to read the workspace
/// * otherwise treat the parent directory as a dummy workspace
pub(crate) fn resolve_workspace_for_source_path(file_path: &Path) -> Result<Workspace, LspError> {
if let Some(toml_path) = find_file_manifest(file_path) {
match resolve_workspace_from_toml(
Expand Down Expand Up @@ -304,6 +307,7 @@ pub(crate) fn resolve_workspace_for_source_path(file_path: &Path) -> Result<Work
let assumed_package = Package {
version: None,
compiler_required_version: Some(NOIR_ARTIFACT_VERSION_STRING.to_string()),
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::from(parent_folder),
package_type: PackageType::Binary,
entry_path: PathBuf::from(file_path),
Expand Down
12 changes: 9 additions & 3 deletions tooling/nargo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub fn prepare_dependencies(
match dep {
Dependency::Remote { package } | Dependency::Local { package } => {
let crate_id = prepare_dependency(context, &package.entry_path);
add_unstable_features(context, crate_id, package);
add_dep(context, parent_crate, crate_id, dep_name.clone());
prepare_dependencies(context, crate_id, &package.dependencies);
}
Expand Down Expand Up @@ -287,10 +288,15 @@ pub fn prepare_package<'file_manager, 'parsed_files>(
package: &Package,
) -> (Context<'file_manager, 'parsed_files>, CrateId) {
let mut context = Context::from_ref_file_manager(file_manager, parsed_files);

let crate_id = prepare_crate(&mut context, &package.entry_path);

add_unstable_features(&mut context, crate_id, package);
prepare_dependencies(&mut context, crate_id, &package.dependencies);

(context, crate_id)
}

/// Add any unstable features required by the `Package` to the `Context`.
fn add_unstable_features(context: &mut Context, crate_id: CrateId, package: &Package) {
context
.required_unstable_features
.insert(crate_id, package.compiler_required_unstable_features.clone());
}
2 changes: 2 additions & 0 deletions tooling/nargo/src/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{collections::BTreeMap, fmt::Display, path::PathBuf};

use acvm::acir::circuit::ExpressionWidth;
pub use noirc_driver::CrateName;
use noirc_frontend::elaborator::UnstableFeature;

use crate::constants::PROVER_INPUT_FILE;

Expand Down Expand Up @@ -47,6 +48,7 @@ pub struct Package {
pub version: Option<String>,
// A semver string which specifies the compiler version required to compile this package
pub compiler_required_version: Option<String>,
pub compiler_required_unstable_features: Vec<UnstableFeature>,
pub root_dir: PathBuf,
pub package_type: PackageType,
pub entry_path: PathBuf,
Expand Down
1 change: 1 addition & 0 deletions tooling/nargo_cli/tests/stdlib-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn run_stdlib_tests(force_brillig: bool, inliner_aggressiveness: i64) {
let dummy_package = Package {
version: None,
compiler_required_version: None,
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::from("."),
package_type: PackageType::Binary,
entry_path: PathBuf::from("main.nr"),
Expand Down
14 changes: 13 additions & 1 deletion tooling/nargo_toml/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use std::{
collections::BTreeMap,
path::{Component, Path, PathBuf},
str::FromStr,
};

use errors::SemverError;
Expand All @@ -13,7 +14,7 @@ use nargo::{
workspace::Workspace,
};
use noirc_driver::parse_expression_width;
use noirc_frontend::graph::CrateName;
use noirc_frontend::{elaborator::UnstableFeature, graph::CrateName};
use serde::Deserialize;

mod errors;
Expand Down Expand Up @@ -241,9 +242,17 @@ impl PackageConfig {
})
.map_or(Ok(None), |res| res.map(Some))?;

// Collect any unstable features the package needs to compile.
// Ignore the ones that we don't recognize: maybe they are no longer unstable, but a dependency hasn't been updated.
let compiler_required_unstable_features =
self.package.compiler_unstable_features.as_ref().map_or(Vec::new(), |feats| {
feats.iter().flat_map(|feat| UnstableFeature::from_str(feat).ok()).collect()
});

Ok(Package {
version: self.package.version.clone(),
compiler_required_version: self.package.compiler_version.clone(),
compiler_required_unstable_features,
root_dir: root_dir.to_path_buf(),
entry_path,
package_type,
Expand Down Expand Up @@ -317,6 +326,9 @@ pub struct PackageMetadata {
// We also state that ACIR and the compiler will upgrade in lockstep.
// so you will not need to supply an ACIR and compiler version
pub compiler_version: Option<String>,
/// List of unstable features we want the compiler to enable to compile this package.
/// This is most useful with the LSP, so it can figure out what is allowed without CLI args.
pub compiler_unstable_features: Option<Vec<String>>,
pub license: Option<String>,
pub expression_width: Option<String>,
}
Expand Down
19 changes: 7 additions & 12 deletions tooling/nargo_toml/src/semver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ mod tests {

let mut package = Package {
compiler_required_version: Some("0.1.0".to_string()),
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
Expand Down Expand Up @@ -136,6 +137,7 @@ mod tests {

let mut package = Package {
compiler_required_version: Some("0.1.0".to_string()),
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
Expand All @@ -147,23 +149,13 @@ mod tests {

let valid_dependency = Package {
compiler_required_version: Some("0.1.0".to_string()),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
name: CrateName::from_str("good_dependency").unwrap(),
dependencies: BTreeMap::new(),
version: Some("1.0".to_string()),
expression_width: None,
..package.clone()
};
let invalid_dependency = Package {
compiler_required_version: Some("0.2.0".to_string()),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
name: CrateName::from_str("bad_dependency").unwrap(),
dependencies: BTreeMap::new(),
version: Some("1.0".to_string()),
expression_width: None,
..package.clone()
};

package.dependencies.insert(
Expand Down Expand Up @@ -202,6 +194,7 @@ mod tests {

let package = Package {
compiler_required_version: Some(">=0.1.0".to_string()),
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
Expand All @@ -224,6 +217,7 @@ mod tests {

let package = Package {
compiler_required_version: Some(">=0.1.0".to_string()),
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
Expand All @@ -244,6 +238,7 @@ mod tests {

let package = Package {
compiler_required_version: Some("0.1.0".to_string()),
compiler_required_unstable_features: Vec::new(),
root_dir: PathBuf::new(),
package_type: PackageType::Library,
entry_path: PathBuf::new(),
Expand Down
Loading