Skip to content

Commit

Permalink
Merge branch 'master' into michaeljklein/kind-size-checks
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljklein authored Oct 9, 2024
2 parents 17b3c7e + 8a31632 commit a4a1b6e
Show file tree
Hide file tree
Showing 87 changed files with 731 additions and 323 deletions.
7 changes: 7 additions & 0 deletions compiler/noirc_frontend/src/ast/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ pub struct NoirStruct {
pub span: Span,
}

impl NoirStruct {
pub fn is_abi(&self) -> bool {
self.attributes.iter().any(|attr| attr.is_abi())
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StructField {
pub visibility: ItemVisibility,
pub name: Ident,
pub typ: UnresolvedType,
}
Expand Down
35 changes: 23 additions & 12 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use rustc_hash::FxHashSet as HashSet;
use crate::{
ast::{
ArrayLiteral, BlockExpression, CallExpression, CastExpression, ConstructorExpression,
Expression, ExpressionKind, Ident, IfExpression, IndexExpression, InfixExpression, Lambda,
Literal, MemberAccessExpression, MethodCallExpression, PrefixExpression, StatementKind,
UnaryOp, UnresolvedTypeData, UnresolvedTypeExpression,
Expression, ExpressionKind, Ident, IfExpression, IndexExpression, InfixExpression,
ItemVisibility, Lambda, Literal, MemberAccessExpression, MethodCallExpression,
PrefixExpression, StatementKind, UnaryOp, UnresolvedTypeData, UnresolvedTypeExpression,
},
hir::{
comptime::{self, InterpreterError},
Expand Down Expand Up @@ -549,7 +549,7 @@ impl<'context> Elaborator<'context> {
let generics = struct_generics.clone();

let fields = constructor.fields;
let field_types = r#type.borrow().get_fields(&struct_generics);
let field_types = r#type.borrow().get_fields_with_visibility(&struct_generics);
let fields =
self.resolve_constructor_expr_fields(struct_type.clone(), field_types, fields, span);
let expr = HirExpression::Constructor(HirConstructorExpression {
Expand Down Expand Up @@ -577,7 +577,7 @@ impl<'context> Elaborator<'context> {
fn resolve_constructor_expr_fields(
&mut self,
struct_type: Shared<StructType>,
field_types: Vec<(String, Type)>,
field_types: Vec<(String, ItemVisibility, Type)>,
fields: Vec<(Ident, Expression)>,
span: Span,
) -> Vec<(Ident, ExprId)> {
Expand All @@ -589,10 +589,11 @@ impl<'context> Elaborator<'context> {
let expected_field_with_index = field_types
.iter()
.enumerate()
.find(|(_, (name, _))| name == &field_name.0.contents);
let expected_index = expected_field_with_index.map(|(index, _)| index);
.find(|(_, (name, _, _))| name == &field_name.0.contents);
let expected_index_and_visibility =
expected_field_with_index.map(|(index, (_, visibility, _))| (index, visibility));
let expected_type =
expected_field_with_index.map(|(_, (_, typ))| typ).unwrap_or(&Type::Error);
expected_field_with_index.map(|(_, (_, _, typ))| typ).unwrap_or(&Type::Error);

let field_span = field.span;
let (resolved, field_type) = self.elaborate_expression(field);
Expand All @@ -619,11 +620,21 @@ impl<'context> Elaborator<'context> {
});
}

if let Some(expected_index) = expected_index {
if let Some((index, visibility)) = expected_index_and_visibility {
let struct_type = struct_type.borrow();
let field_span = field_name.span();
let field_name = &field_name.0.contents;
self.check_struct_field_visibility(
&struct_type,
field_name,
*visibility,
field_span,
);

self.interner.add_struct_member_reference(
struct_type.borrow().id,
expected_index,
Location::new(field_name.span(), self.file),
struct_type.id,
index,
Location::new(field_span, self.file),
);
}

Expand Down
36 changes: 22 additions & 14 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
rc::Rc,
};

use crate::ast::ItemVisibility;
use crate::{ast::ItemVisibility, StructField};
use crate::{
ast::{
BlockExpression, FunctionKind, GenericTypeArgs, Ident, NoirFunction, NoirStruct, Param,
Expand Down Expand Up @@ -751,7 +751,7 @@ impl<'context> Elaborator<'context> {
);

if is_entry_point {
self.mark_parameter_type_as_used(&typ);
self.mark_type_as_used(&typ);
}

let pattern = self.elaborate_pattern_and_store_ids(
Expand Down Expand Up @@ -832,33 +832,33 @@ impl<'context> Elaborator<'context> {
self.current_item = None;
}

fn mark_parameter_type_as_used(&mut self, typ: &Type) {
fn mark_type_as_used(&mut self, typ: &Type) {
match typ {
Type::Array(_n, typ) => self.mark_parameter_type_as_used(typ),
Type::Slice(typ) => self.mark_parameter_type_as_used(typ),
Type::Array(_n, typ) => self.mark_type_as_used(typ),
Type::Slice(typ) => self.mark_type_as_used(typ),
Type::Tuple(types) => {
for typ in types {
self.mark_parameter_type_as_used(typ);
self.mark_type_as_used(typ);
}
}
Type::Struct(struct_type, generics) => {
self.mark_struct_as_constructed(struct_type.clone());
for generic in generics {
self.mark_parameter_type_as_used(generic);
self.mark_type_as_used(generic);
}
for (_, typ) in struct_type.borrow().get_fields(generics) {
self.mark_parameter_type_as_used(&typ);
self.mark_type_as_used(&typ);
}
}
Type::Alias(alias_type, generics) => {
self.mark_parameter_type_as_used(&alias_type.borrow().get_type(generics));
self.mark_type_as_used(&alias_type.borrow().get_type(generics));
}
Type::MutableReference(typ) => {
self.mark_parameter_type_as_used(typ);
self.mark_type_as_used(typ);
}
Type::InfixExpr(left, _op, right) => {
self.mark_parameter_type_as_used(left);
self.mark_parameter_type_as_used(right);
self.mark_type_as_used(left);
self.mark_type_as_used(right);
}
Type::FieldElement
| Type::Integer(..)
Expand Down Expand Up @@ -1277,6 +1277,13 @@ impl<'context> Elaborator<'context> {
self.local_module = typ.module_id;

let fields = self.resolve_struct_fields(&typ.struct_def, *type_id);

if typ.struct_def.is_abi() {
for field in &fields {
self.mark_type_as_used(&field.typ);
}
}

let fields_len = fields.len();
self.interner.update_struct(*type_id, |struct_def| {
struct_def.set_fields(fields);
Expand Down Expand Up @@ -1315,7 +1322,7 @@ impl<'context> Elaborator<'context> {
&mut self,
unresolved: &NoirStruct,
struct_id: StructId,
) -> Vec<(Ident, Type)> {
) -> Vec<StructField> {
self.recover_generics(|this| {
this.current_item = Some(DependencyId::Struct(struct_id));

Expand All @@ -1327,7 +1334,8 @@ impl<'context> Elaborator<'context> {
let fields = vecmap(&unresolved.fields, |field| {
let ident = &field.item.name;
let typ = &field.item.typ;
(ident.clone(), this.resolve_type(typ.clone()))
let visibility = field.item.visibility;
StructField { visibility, name: ident.clone(), typ: this.resolve_type(typ.clone()) }
});

this.resolving_ids.remove(&struct_id);
Expand Down
14 changes: 12 additions & 2 deletions compiler/noirc_frontend/src/elaborator/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use rustc_hash::FxHashSet as HashSet;

use crate::{
ast::{
Expression, ExpressionKind, Ident, Path, Pattern, TypePath, UnresolvedType, ERROR_IDENT,
Expression, ExpressionKind, Ident, ItemVisibility, Path, Pattern, TypePath, UnresolvedType,
ERROR_IDENT,
},
hir::{
def_collector::dc_crate::CompilationError,
Expand Down Expand Up @@ -272,7 +273,9 @@ impl<'context> Elaborator<'context> {
let mut unseen_fields = struct_type.borrow().field_names();

for (field, pattern) in fields {
let field_type = expected_type.get_field_type(&field.0.contents).unwrap_or(Type::Error);
let (field_type, visibility) = expected_type
.get_field_type_and_visibility(&field.0.contents)
.unwrap_or((Type::Error, ItemVisibility::Public));
let resolved = self.elaborate_pattern_mut(
pattern,
field_type,
Expand All @@ -286,6 +289,13 @@ impl<'context> Elaborator<'context> {
if unseen_fields.contains(&field) {
unseen_fields.remove(&field);
seen_fields.insert(field.clone());

self.check_struct_field_visibility(
&struct_type.borrow(),
&field.0.contents,
visibility,
field.span(),
);
} else if seen_fields.contains(&field) {
// duplicate field
self.push_err(ResolverError::DuplicateField { field: field.clone() });
Expand Down
28 changes: 23 additions & 5 deletions compiler/noirc_frontend/src/elaborator/statements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ use noirc_errors::{Location, Span, Spanned};
use crate::{
ast::{
AssignStatement, BinaryOpKind, ConstrainKind, ConstrainStatement, Expression,
ExpressionKind, ForLoopStatement, ForRange, InfixExpression, LValue, LetStatement, Path,
Statement, StatementKind,
ExpressionKind, ForLoopStatement, ForRange, Ident, InfixExpression, ItemVisibility, LValue,
LetStatement, Path, Statement, StatementKind,
},
hir::{
resolution::errors::ResolverError,
resolution::{
errors::ResolverError, import::PathResolutionError, visibility::struct_field_is_visible,
},
type_check::{Source, TypeCheckError},
},
hir_def::{
Expand All @@ -18,7 +20,7 @@ use crate::{
},
},
node_interner::{DefinitionId, DefinitionKind, GlobalId, StmtId},
Type,
StructType, Type,
};

use super::{lints, Elaborator};
Expand Down Expand Up @@ -439,10 +441,12 @@ impl<'context> Elaborator<'context> {
match &lhs_type {
Type::Struct(s, args) => {
let s = s.borrow();
if let Some((field, index)) = s.get_field(field_name, args) {
if let Some((field, visibility, index)) = s.get_field(field_name, args) {
let reference_location = Location::new(span, self.file);
self.interner.add_struct_member_reference(s.id, index, reference_location);

self.check_struct_field_visibility(&s, field_name, visibility, span);

return Some((field, index));
}
}
Expand Down Expand Up @@ -497,6 +501,20 @@ impl<'context> Elaborator<'context> {
None
}

pub(super) fn check_struct_field_visibility(
&mut self,
struct_type: &StructType,
field_name: &str,
visibility: ItemVisibility,
span: Span,
) {
if !struct_field_is_visible(struct_type, visibility, self.module_id(), self.def_maps) {
self.push_err(ResolverError::PathResolutionError(PathResolutionError::Private(
Ident::new(field_name.to_string(), span),
)));
}
}

fn elaborate_comptime_statement(&mut self, statement: Statement) -> (HirStatement, Type) {
let span = statement.span;
let (hir_statement, _typ) =
Expand Down
23 changes: 13 additions & 10 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use rustc_hash::FxHashMap as HashMap;
use crate::{
ast::{
ArrayLiteral, BlockExpression, ConstrainKind, Expression, ExpressionKind, ForRange,
FunctionKind, FunctionReturnType, Ident, IntegerBitSize, LValue, Literal, Pattern,
Signedness, Statement, StatementKind, UnaryOp, UnresolvedType, UnresolvedTypeData,
FunctionKind, FunctionReturnType, Ident, IntegerBitSize, ItemVisibility, LValue, Literal,
Pattern, Signedness, Statement, StatementKind, UnaryOp, UnresolvedType, UnresolvedTypeData,
Visibility,
},
hir::{
Expand All @@ -32,10 +32,9 @@ use crate::{
def_collector::dc_crate::CollectedItems,
def_map::ModuleDefId,
},
hir_def::{
expr::{HirExpression, HirLiteral},
function::FunctionBody,
},
hir_def::expr::{HirExpression, HirLiteral},
hir_def::function::FunctionBody,
hir_def::{self},
node_interner::{DefinitionKind, NodeInterner, TraitImplKind},
parser::{Parser, StatementOrExpressionOrLValue},
token::{Attribute, SecondaryAttribute, Token},
Expand Down Expand Up @@ -498,9 +497,9 @@ fn struct_def_fields(

let mut fields = im::Vector::new();

for (name, typ) in struct_def.get_fields_as_written() {
let name = Value::Quoted(Rc::new(vec![Token::Ident(name)]));
let typ = Value::Type(typ);
for field in struct_def.get_fields_as_written() {
let name = Value::Quoted(Rc::new(vec![Token::Ident(field.name.to_string())]));
let typ = Value::Type(field.typ);
fields.push_back(Value::Tuple(vec![name, typ]));
}

Expand Down Expand Up @@ -567,7 +566,11 @@ fn struct_def_set_fields(

match name_tokens.first() {
Some(Token::Ident(name)) if name_tokens.len() == 1 => {
Ok((Ident::new(name.clone(), field_location.span), typ))
Ok(hir_def::types::StructField {
visibility: ItemVisibility::Public,
name: Ident::new(name.clone(), field_location.span),
typ,
})
}
_ => {
let value = name_value.display(interner).to_string();
Expand Down
14 changes: 8 additions & 6 deletions compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,12 +1013,14 @@ pub fn collect_struct(

let parent_module_id = ModuleId { krate, local_id: module_id };

interner.usage_tracker.add_unused_item(
parent_module_id,
name.clone(),
UnusedItem::Struct(id),
visibility,
);
if !unresolved.struct_def.is_abi() {
interner.usage_tracker.add_unused_item(
parent_module_id,
name.clone(),
UnusedItem::Struct(id),
visibility,
);
}

if let Err((first_def, second_def)) = result {
let error = DefCollectorErrorKind::Duplicate {
Expand Down
Loading

0 comments on commit a4a1b6e

Please sign in to comment.