Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Sync from noir #8423

Merged
merged 2 commits into from
Sep 6, 2024
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
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b84009ca428a5790acf53a6c027146b706170574
3dab4dd771b7d8b9242ce3a9aeff5770f4d85cf6
1 change: 0 additions & 1 deletion noir/noir-repo/.gitattributes

This file was deleted.

83 changes: 68 additions & 15 deletions noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
},
dc_mod,
},
def_map::ModuleId,
def_map::{LocalModuleId, ModuleId},
resolution::errors::ResolverError,
},
hir_def::expr::HirIdent,
Expand All @@ -30,6 +30,24 @@ use crate::{

use super::{Elaborator, FunctionContext, ResolverMeta};

#[derive(Debug, Copy, Clone)]
struct AttributeContext {
// The file where generated items should be added
file: FileId,
// The module where generated items should be added
module: LocalModuleId,
// The file where the attribute is located
attribute_file: FileId,
// The module where the attribute is located
attribute_module: LocalModuleId,
}

impl AttributeContext {
fn new(file: FileId, module: LocalModuleId) -> Self {
Self { file, module, attribute_file: file, attribute_module: module }
}
}

impl<'context> Elaborator<'context> {
/// Elaborate an expression from the middle of a comptime scope.
/// When this happens we require additional information to know
Expand Down Expand Up @@ -89,15 +107,22 @@ impl<'context> Elaborator<'context> {
}
}

pub(super) fn run_comptime_attributes_on_item(
fn run_comptime_attributes_on_item(
&mut self,
attributes: &[SecondaryAttribute],
item: Value,
span: Span,
attribute_context: AttributeContext,
generated_items: &mut CollectedItems,
) {
for attribute in attributes {
self.run_comptime_attribute_on_item(attribute, &item, span, generated_items);
self.run_comptime_attribute_on_item(
attribute,
&item,
span,
attribute_context,
generated_items,
);
}
}

Expand All @@ -106,6 +131,7 @@ impl<'context> Elaborator<'context> {
attribute: &SecondaryAttribute,
item: &Value,
span: Span,
attribute_context: AttributeContext,
generated_items: &mut CollectedItems,
) {
if let SecondaryAttribute::Custom(attribute) = attribute {
Expand All @@ -114,6 +140,7 @@ impl<'context> Elaborator<'context> {
item.clone(),
span,
attribute.contents_span,
attribute_context,
generated_items,
) {
self.errors.push(error);
Expand All @@ -127,8 +154,12 @@ impl<'context> Elaborator<'context> {
item: Value,
span: Span,
attribute_span: Span,
attribute_context: AttributeContext,
generated_items: &mut CollectedItems,
) -> Result<(), (CompilationError, FileId)> {
self.file = attribute_context.attribute_file;
self.local_module = attribute_context.attribute_module;

let location = Location::new(attribute_span, self.file);
let Some((function, arguments)) = Self::parse_attribute(attribute, location)? else {
// Do not issue an error if the attribute is unknown
Expand Down Expand Up @@ -156,6 +187,9 @@ impl<'context> Elaborator<'context> {
return Err((ResolverError::NonFunctionInAnnotation { span }.into(), self.file));
};

self.file = attribute_context.file;
self.local_module = attribute_context.module;

let mut interpreter = self.setup_interpreter();
let mut arguments = Self::handle_attribute_arguments(
&mut interpreter,
Expand Down Expand Up @@ -463,18 +497,28 @@ impl<'context> Elaborator<'context> {
let attributes = &trait_.trait_def.attributes;
let item = Value::TraitDefinition(*trait_id);
let span = trait_.trait_def.span;
self.local_module = trait_.module_id;
self.file = trait_.file_id;
self.run_comptime_attributes_on_item(attributes, item, span, &mut generated_items);
let context = AttributeContext::new(trait_.file_id, trait_.module_id);
self.run_comptime_attributes_on_item(
attributes,
item,
span,
context,
&mut generated_items,
);
}

for (struct_id, struct_def) in types {
let attributes = &struct_def.struct_def.attributes;
let item = Value::StructDefinition(*struct_id);
let span = struct_def.struct_def.span;
self.local_module = struct_def.module_id;
self.file = struct_def.file_id;
self.run_comptime_attributes_on_item(attributes, item, span, &mut generated_items);
let context = AttributeContext::new(struct_def.file_id, struct_def.module_id);
self.run_comptime_attributes_on_item(
attributes,
item,
span,
context,
&mut generated_items,
);
}

self.run_attributes_on_functions(functions, &mut generated_items);
Expand All @@ -496,10 +540,14 @@ impl<'context> Elaborator<'context> {
let attribute = &module_attribute.attribute;
let span = Span::default();

self.local_module = module_attribute.attribute_module_id;
self.file = module_attribute.attribute_file_id;
let context = AttributeContext {
file: module_attribute.file_id,
module: module_attribute.module_id,
attribute_file: module_attribute.attribute_file_id,
attribute_module: module_attribute.attribute_module_id,
};

self.run_comptime_attribute_on_item(attribute, &item, span, generated_items);
self.run_comptime_attribute_on_item(attribute, &item, span, context, generated_items);
}
}

Expand All @@ -509,15 +557,20 @@ impl<'context> Elaborator<'context> {
generated_items: &mut CollectedItems,
) {
for function_set in function_sets {
self.file = function_set.file_id;
self.self_type = function_set.self_type.clone();

for (local_module, function_id, function) in &function_set.functions {
self.local_module = *local_module;
let context = AttributeContext::new(function_set.file_id, *local_module);
let attributes = function.secondary_attributes();
let item = Value::FunctionDefinition(*function_id);
let span = function.span();
self.run_comptime_attributes_on_item(attributes, item, span, generated_items);
self.run_comptime_attributes_on_item(
attributes,
item,
span,
context,
generated_items,
);
}
}
}
Expand Down
87 changes: 49 additions & 38 deletions noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
use crate::{
ast::FunctionKind,
ast::{FunctionKind, Ident},
graph::CrateId,
hir::{
resolution::errors::{PubPosition, ResolverError},
type_check::TypeCheckError,
},
hir_def::expr::HirIdent,
hir_def::{expr::HirIdent, function::FuncMeta},
macros_api::{
HirExpression, HirLiteral, NodeInterner, NoirFunction, Signedness, UnaryOp,
UnresolvedTypeData, Visibility,
HirExpression, HirLiteral, NodeInterner, NoirFunction, Signedness, UnaryOp, Visibility,
},
node_interner::{DefinitionKind, ExprId, FuncId},
node_interner::{DefinitionKind, ExprId, FuncId, FunctionModifiers},
Type,
};

use noirc_errors::Span;
use noirc_errors::{Span, Spanned};

pub(super) fn deprecated_function(interner: &NodeInterner, expr: ExprId) -> Option<TypeCheckError> {
let HirExpression::Ident(HirIdent { location, id, impl_kind: _ }, _) =
Expand All @@ -39,16 +38,17 @@ pub(super) fn deprecated_function(interner: &NodeInterner, expr: ExprId) -> Opti
/// Inline attributes are only relevant for constrained functions
/// as all unconstrained functions are not inlined and so
/// associated attributes are disallowed.
pub(super) fn inlining_attributes(func: &NoirFunction) -> Option<ResolverError> {
if func.def.is_unconstrained {
let attributes = func.attributes().clone();

if attributes.is_no_predicates() {
Some(ResolverError::NoPredicatesAttributeOnUnconstrained {
ident: func.name_ident().clone(),
})
} else if attributes.is_foldable() {
Some(ResolverError::FoldAttributeOnUnconstrained { ident: func.name_ident().clone() })
pub(super) fn inlining_attributes(
func: &FuncMeta,
modifiers: &FunctionModifiers,
) -> Option<ResolverError> {
if modifiers.is_unconstrained {
if modifiers.attributes.is_no_predicates() {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::NoPredicatesAttributeOnUnconstrained { ident })
} else if modifiers.attributes.is_foldable() {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::FoldAttributeOnUnconstrained { ident })
} else {
None
}
Expand All @@ -59,24 +59,30 @@ pub(super) fn inlining_attributes(func: &NoirFunction) -> Option<ResolverError>

/// Attempting to define new low level (`#[builtin]` or `#[foreign]`) functions outside of the stdlib is disallowed.
pub(super) fn low_level_function_outside_stdlib(
func: &NoirFunction,
func: &FuncMeta,
modifiers: &FunctionModifiers,
crate_id: CrateId,
) -> Option<ResolverError> {
let is_low_level_function =
func.attributes().function.as_ref().map_or(false, |func| func.is_low_level());
modifiers.attributes.function.as_ref().map_or(false, |func| func.is_low_level());
if !crate_id.is_stdlib() && is_low_level_function {
Some(ResolverError::LowLevelFunctionOutsideOfStdlib { ident: func.name_ident().clone() })
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::LowLevelFunctionOutsideOfStdlib { ident })
} else {
None
}
}

/// Oracle definitions (functions with the `#[oracle]` attribute) must be marked as unconstrained.
pub(super) fn oracle_not_marked_unconstrained(func: &NoirFunction) -> Option<ResolverError> {
pub(super) fn oracle_not_marked_unconstrained(
func: &FuncMeta,
modifiers: &FunctionModifiers,
) -> Option<ResolverError> {
let is_oracle_function =
func.attributes().function.as_ref().map_or(false, |func| func.is_oracle());
if is_oracle_function && !func.def.is_unconstrained {
Some(ResolverError::OracleMarkedAsConstrained { ident: func.name_ident().clone() })
modifiers.attributes.function.as_ref().map_or(false, |func| func.is_oracle());
if is_oracle_function && !modifiers.is_unconstrained {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::OracleMarkedAsConstrained { ident })
} else {
None
}
Expand Down Expand Up @@ -106,24 +112,26 @@ pub(super) fn oracle_called_from_constrained_function(
}

/// `pub` is required on return types for entry point functions
pub(super) fn missing_pub(func: &NoirFunction, is_entry_point: bool) -> Option<ResolverError> {
if is_entry_point
&& func.return_type().typ != UnresolvedTypeData::Unit
&& func.def.return_visibility == Visibility::Private
pub(super) fn missing_pub(func: &FuncMeta, modifiers: &FunctionModifiers) -> Option<ResolverError> {
if func.is_entry_point
&& func.return_type() != &Type::Unit
&& func.return_visibility == Visibility::Private
{
Some(ResolverError::NecessaryPub { ident: func.name_ident().clone() })
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::NecessaryPub { ident })
} else {
None
}
}

/// `#[recursive]` attribute is only allowed for entry point functions
pub(super) fn recursive_non_entrypoint_function(
func: &NoirFunction,
is_entry_point: bool,
func: &FuncMeta,
modifiers: &FunctionModifiers,
) -> Option<ResolverError> {
if !is_entry_point && func.kind == FunctionKind::Recursive {
Some(ResolverError::MisplacedRecursiveAttribute { ident: func.name_ident().clone() })
if !func.is_entry_point && func.kind == FunctionKind::Recursive {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::MisplacedRecursiveAttribute { ident })
} else {
None
}
Expand Down Expand Up @@ -163,14 +171,13 @@ pub(super) fn unconstrained_function_return(
///
/// Application of `pub` to other functions is not meaningful and is a mistake.
pub(super) fn unnecessary_pub_return(
func: &NoirFunction,
func: &FuncMeta,
modifiers: &FunctionModifiers,
is_entry_point: bool,
) -> Option<ResolverError> {
if !is_entry_point && func.def.return_visibility == Visibility::Public {
Some(ResolverError::UnnecessaryPub {
ident: func.name_ident().clone(),
position: PubPosition::ReturnType,
})
if !is_entry_point && func.return_visibility == Visibility::Public {
let ident = func_meta_name_ident(func, modifiers);
Some(ResolverError::UnnecessaryPub { ident, position: PubPosition::ReturnType })
} else {
None
}
Expand Down Expand Up @@ -252,3 +259,7 @@ pub(crate) fn overflowing_int(

errors
}

fn func_meta_name_ident(func: &FuncMeta, modifiers: &FunctionModifiers) -> Ident {
Ident(Spanned::from(func.name.location.span, modifiers.name.clone()))
}
Loading
Loading