Skip to content

Commit

Permalink
feat: Allow secret functions to use public parameters (noir-lang#1051)
Browse files Browse the repository at this point in the history
* Allow secret functions to use public parameters

* Add carve-out for the Unit type for pub return values

* Fix contract test
  • Loading branch information
jfecher authored Mar 28, 2023
1 parent bc52612 commit 12c0668
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 7 deletions.
4 changes: 2 additions & 2 deletions crates/nargo/tests/test_data/contracts/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ fn main(x : Field, y : pub Field) {
}

contract Foo {
fn double(x: Field) -> Field { x * 2 }
fn triple(x: Field) -> Field { x * 3 }
fn double(x: Field) -> pub Field { x * 2 }
fn triple(x: Field) -> pub Field { x * 3 }
}
4 changes: 2 additions & 2 deletions crates/noirc_frontend/src/hir/resolution/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl From<ResolverError> for Diagnostic {
ident.0.span(),
);

diag.add_note("The `pub` keyword only has effects on arguments to the main function of a program. Thus, adding it to other function parameters can be deceiving and should be removed".to_owned());
diag.add_note("The `pub` keyword only has effects on arguments to the entry-point function of a program. Thus, adding it to other function parameters can be deceiving and should be removed".to_owned());
diag
}
ResolverError::NecessaryPub { ident } => {
Expand All @@ -178,7 +178,7 @@ impl From<ResolverError> for Diagnostic {
ident.0.span(),
);

diag.add_note("The `pub` keyword is mandatory for the main function return type because the verifier cannot retrieve private witness and thus the function will not be able to return a 'priv' value".to_owned());
diag.add_note("The `pub` keyword is mandatory for the entry-point function return type because the verifier cannot retrieve private witness and thus the function will not be able to return a 'priv' value".to_owned());
diag
}
ResolverError::ExpectedComptimeVariable { name, span } => Diagnostic::simple_error(
Expand Down
16 changes: 13 additions & 3 deletions crates/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ impl<'a> Resolver<'a> {
let mut parameter_types = vec![];

for (pattern, typ, visibility) in func.parameters().iter().cloned() {
if func.name() != "main" && visibility == noirc_abi::AbiVisibility::Public {
if visibility == noirc_abi::AbiVisibility::Public && !self.pub_allowed(func) {
self.push_err(ResolverError::UnnecessaryPub { ident: func.name_ident().clone() })
}

Expand All @@ -615,8 +615,9 @@ impl<'a> Resolver<'a> {

self.declare_numeric_generics(&parameter_types, &return_type);

if func.name() == "main"
&& *return_type != Type::Unit
// 'pub_allowed' also implies 'pub' is required on return types
if self.pub_allowed(func)
&& return_type.as_ref() != &Type::Unit
&& func.def.return_visibility != noirc_abi::AbiVisibility::Public
{
self.push_err(ResolverError::NecessaryPub { ident: func.name_ident().clone() })
Expand Down Expand Up @@ -650,6 +651,15 @@ impl<'a> Resolver<'a> {
}
}

/// True if the 'pub' keyword is allowed on parameters in this function
fn pub_allowed(&self, func: &NoirFunction) -> bool {
if self.in_contract() {
!func.def.is_unconstrained && !func.def.is_open
} else {
func.name() == "main"
}
}

fn handle_function_type(&mut self, func: &NoirFunction) -> Option<ContractFunctionType> {
if func.def.is_open {
if self.in_contract() {
Expand Down

0 comments on commit 12c0668

Please sign in to comment.