Skip to content

Commit

Permalink
feat: Sync from noir (#7308)
Browse files Browse the repository at this point in the history
Automated pull of development from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
feat: build releases for `aarch64-unknown-linux-gnu` target
(noir-lang/noir#5289)
fix: go to definition from `use` statement
(noir-lang/noir#5390)
feat: lsp rename struct (noir-lang/noir#5380)
END_COMMIT_OVERRIDE

---------

Co-authored-by: TomAFrench <[email protected]>
  • Loading branch information
AztecBot and TomAFrench authored Jul 3, 2024
1 parent d4359a3 commit 2ae17f2
Show file tree
Hide file tree
Showing 29 changed files with 432 additions and 335 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
32029f91f6aae4d2f6b08b4ea40481f5837e50bc
f35614a43cf8c5cfb244d9f6ffc9d63282a63e6d
2 changes: 1 addition & 1 deletion noir/noir-repo/.github/workflows/publish-nargo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
strategy:
fail-fast: false
matrix:
target: [x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl]
target: [x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, aarch64-unknown-linux-gnu]
timeout-minutes: 30

steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
HirLiteral, HirStatement, Ident, IndexExpression, Literal, MemberAccessExpression,
MethodCallExpression, PrefixExpression,
},
node_interner::{DefinitionKind, ExprId, FuncId},
node_interner::{DefinitionKind, DependencyId, ExprId, FuncId},
token::Tokens,
Kind, QuotedType, Shared, StructType, Type,
};
Expand Down Expand Up @@ -431,6 +431,11 @@ impl<'context> Elaborator<'context> {
r#type,
struct_generics,
});

let referenced = DependencyId::Struct(struct_type.borrow().id);
let reference = DependencyId::Variable(Location::new(span, self.file));
self.interner.add_reference(referenced, reference);

(expr, Type::Struct(struct_type, generics))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ impl<'context> Elaborator<'context> {
mutable: Option<Span>,
new_definitions: &mut Vec<HirIdent>,
) -> HirPattern {
let name_span = name.last_segment().span();

let error_identifier = |this: &mut Self| {
// Must create a name here to return a HirPattern::Identifier. Allowing
// shadowing here lets us avoid further errors if we define ERROR_IDENT
Expand Down Expand Up @@ -196,6 +198,10 @@ impl<'context> Elaborator<'context> {
new_definitions,
);

let referenced = DependencyId::Struct(struct_type.borrow().id);
let reference = DependencyId::Variable(Location::new(name_span, self.file));
self.interner.add_reference(referenced, reference);

HirPattern::Struct(expected_type, fields, location)
}

Expand Down Expand Up @@ -584,10 +590,7 @@ impl<'context> Elaborator<'context> {
}

pub fn get_ident_from_path(&mut self, path: Path) -> (HirIdent, usize) {
let location = Location::new(
path.segments.last().expect("ice: path without segments").span(),
self.file,
);
let location = Location::new(path.last_segment().span(), self.file);

let error = match path.as_ident().map(|ident| self.use_variable(ident)) {
Some(Ok(found)) => return found,
Expand Down
11 changes: 10 additions & 1 deletion noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ use crate::{
HirExpression, HirLiteral, HirStatement, Path, PathKind, SecondaryAttribute, Signedness,
UnaryOp, UnresolvedType, UnresolvedTypeData,
},
node_interner::{DefinitionKind, ExprId, GlobalId, TraitId, TraitImplKind, TraitMethodId},
node_interner::{
DefinitionKind, DependencyId, ExprId, GlobalId, TraitId, TraitImplKind, TraitMethodId,
},
Generics, Kind, ResolvedGeneric, Type, TypeBinding, TypeVariable, TypeVariableKind,
};

Expand Down Expand Up @@ -242,6 +244,8 @@ impl<'context> Elaborator<'context> {
return Type::Alias(alias, args);
}

let last_segment = path.last_segment();

match self.lookup_struct_or_error(path) {
Some(struct_type) => {
if self.resolving_ids.contains(&struct_type.borrow().id) {
Expand Down Expand Up @@ -279,6 +283,11 @@ impl<'context> Elaborator<'context> {
self.interner.add_type_dependency(current_item, dependency_id);
}

let referenced = DependencyId::Struct(struct_type.borrow().id);
let reference =
DependencyId::Variable(Location::new(last_segment.span(), self.file));
self.interner.add_reference(referenced, reference);

Type::Struct(struct_type, args)
}
None => Type::Error,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,17 @@ fn add_import_reference(
// We ignore empty spans at 0 location, this must be Stdlib
return;
}
if let crate::macros_api::ModuleDefId::FunctionId(func_id) = def_id {
let variable = DependencyId::Variable(Location::new(name.span(), file_id));
interner.add_reference_for(DependencyId::Function(func_id), variable);

match def_id {
crate::macros_api::ModuleDefId::FunctionId(func_id) => {
let variable = DependencyId::Variable(Location::new(name.span(), file_id));
interner.add_reference(DependencyId::Function(func_id), variable);
}
crate::macros_api::ModuleDefId::TypeId(struct_id) => {
let variable = DependencyId::Variable(Location::new(name.span(), file_id));
interner.add_reference(DependencyId::Struct(struct_id), variable);
}
_ => (),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::ast::{
TypeImpl,
};
use crate::macros_api::NodeInterner;
use crate::node_interner::DependencyId;
use crate::{
graph::CrateId,
hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait},
Expand Down Expand Up @@ -267,6 +268,7 @@ impl<'a> ModCollector<'a> {
let mut definition_errors = vec![];
for struct_definition in types {
let name = struct_definition.name.clone();
let name_location = Location::new(name.span(), self.file_id);

let unresolved = UnresolvedStruct {
file_id: self.file_id,
Expand Down Expand Up @@ -310,6 +312,9 @@ impl<'a> ModCollector<'a> {

// And store the TypeId -> StructType mapping somewhere it is reachable
self.def_collector.items.types.insert(id, unresolved);

context.def_interner.add_struct_location(id, name_location);
context.def_interner.add_definition_location(DependencyId::Struct(id));
}
definition_errors
}
Expand Down
5 changes: 5 additions & 0 deletions noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,9 @@ impl Context<'_, '_> {
ResolvedGeneric { name, type_var, kind, span }
})
}

// Enables reference tracking (useful for tools like LSP).
pub fn track_references(&mut self) {
self.def_interner.track_references = true;
}
}
76 changes: 43 additions & 33 deletions noir/noir-repo/compiler/noirc_frontend/src/locations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,31 @@ impl NodeInterner {
pub fn dependency_location(&self, dependency: DependencyId) -> Location {
match dependency {
DependencyId::Function(id) => self.function_modifiers(&id).name_location,
DependencyId::Struct(id) => self.get_struct(id).borrow().location,
DependencyId::Struct(id) => self.struct_location(&id),
DependencyId::Global(id) => self.get_global(id).location,
DependencyId::Alias(id) => self.get_type_alias(id).borrow().location,
DependencyId::Variable(location) => location,
}
}

pub(crate) fn add_reference(&mut self, referenced: DependencyId, reference: DependencyId) {
let referenced_index = self.get_or_insert_reference(referenced);
let reference_index = self.reference_graph.add_node(reference);

let referenced_location = self.dependency_location(referenced);
let reference_location = self.dependency_location(reference);

self.reference_graph.add_edge(referenced_index, reference_index, ());
self.location_indices.add_location(referenced_location, referenced_index);
self.location_indices.add_location(reference_location, reference_index);
}

pub(crate) fn add_reference_for(
&mut self,
referenced_id: DependencyId,
reference: DependencyId,
) {
let Some(referenced_index) = self.reference_graph_indices.get(&referenced_id) else {
panic!("Compiler Error: Referenced index not found")
};
if !self.track_references {
return;
}

let referenced_index = self.get_or_insert_reference(referenced);
let reference_location = self.dependency_location(reference);
let reference_index = self.reference_graph.add_node(reference);
self.reference_graph.add_edge(*referenced_index, reference_index, ());

self.reference_graph.add_edge(reference_index, referenced_index, ());
self.location_indices.add_location(reference_location, reference_index);
}

pub(crate) fn add_definition_location(&mut self, referenced: DependencyId) {
if !self.track_references {
return;
}

let referenced_index = self.get_or_insert_reference(referenced);
let referenced_location = self.dependency_location(referenced);
self.location_indices.add_location(referenced_location, referenced_index);
Expand All @@ -83,40 +73,60 @@ impl NodeInterner {
index
}

pub fn check_rename_possible(&self, location: Location) -> bool {
// Given a reference location, find the location of the referenced node.
pub fn find_referenced_location(&self, reference_location: Location) -> Option<Location> {
self.location_indices
.get_node_from_location(reference_location)
.and_then(|node_index| self.referenced_index(node_index))
.map(|node_index| self.dependency_location(self.reference_graph[node_index]))
}

// Is the given location known to this interner?
pub fn is_location_known(&self, location: Location) -> bool {
self.location_indices.get_node_from_location(location).is_some()
}

pub fn find_rename_symbols_at(&self, location: Location) -> Option<Vec<Location>> {
// Starting at the given location, find the node referenced by it. Then, gather
// all locations that reference that node, and return all of them
// (the referenced node and the references).
// Returns `None` if the location is not known to this interner.
pub fn find_all_references(&self, location: Location) -> Option<Vec<Location>> {
let node_index = self.location_indices.get_node_from_location(location)?;

let reference_node = self.reference_graph[node_index];
let found_locations: Vec<Location> = match reference_node {
DependencyId::Alias(_) | DependencyId::Struct(_) | DependencyId::Global(_) => todo!(),
DependencyId::Function(_) => self.get_edit_locations(node_index),
DependencyId::Alias(_) | DependencyId::Global(_) => todo!(),
DependencyId::Function(_) | DependencyId::Struct(_) => {
self.find_all_references_for_index(node_index)
}

DependencyId::Variable(_) => {
let referenced_node_index = self
.reference_graph
.neighbors_directed(node_index, petgraph::Direction::Incoming)
.next()?;

self.get_edit_locations(referenced_node_index)
let referenced_node_index = self.referenced_index(node_index)?;
self.find_all_references_for_index(referenced_node_index)
}
};
Some(found_locations)
}

fn get_edit_locations(&self, referenced_node_index: PetGraphIndex) -> Vec<Location> {
// Given a referenced node index, find all references to it and return their locations, together
// with the reference node's location.
fn find_all_references_for_index(&self, referenced_node_index: PetGraphIndex) -> Vec<Location> {
let id = self.reference_graph[referenced_node_index];
let mut edit_locations = vec![self.dependency_location(id)];

self.reference_graph
.neighbors_directed(referenced_node_index, petgraph::Direction::Outgoing)
.neighbors_directed(referenced_node_index, petgraph::Direction::Incoming)
.for_each(|reference_node_index| {
let id = self.reference_graph[reference_node_index];
edit_locations.push(self.dependency_location(id));
});
edit_locations
}

// Given a reference index, returns the referenced index, if any.
fn referenced_index(&self, reference_index: PetGraphIndex) -> Option<PetGraphIndex> {
self.reference_graph
.neighbors_directed(reference_index, petgraph::Direction::Outgoing)
.next()
}
}
34 changes: 33 additions & 1 deletion noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::ops::Deref;

use fm::FileId;
Expand Down Expand Up @@ -64,6 +65,9 @@ pub struct NodeInterner {
// Contains the source module each function was defined in
function_modules: HashMap<FuncId, ModuleId>,

// The location of each struct name
struct_name_locations: HashMap<StructId, Location>,

/// This graph tracks dependencies between different global definitions.
/// This is used to ensure the absence of dependency cycles for globals and types.
dependency_graph: DiGraph<DependencyId, ()>,
Expand Down Expand Up @@ -184,7 +188,25 @@ pub struct NodeInterner {
/// the actual type since types do not implement Send or Sync.
quoted_types: noirc_arena::Arena<Type>,

/// Store the location of the references in the graph
/// Whether to track references. In regular compilations this is false, but tools set it to true.
pub(crate) track_references: bool,

/// Store the location of the references in the graph.
/// Edges are directed from reference nodes to referenced nodes.
/// For example:
///
/// ```
/// let foo = 3;
/// // referenced
/// // ^
/// // |
/// // +------------+
/// let bar = foo; |
/// // reference |
/// // v |
/// // | |
/// // +------+
/// ```
pub(crate) reference_graph: DiGraph<DependencyId, ()>,

/// Tracks the index of the references in the graph
Expand Down Expand Up @@ -504,6 +526,7 @@ impl Default for NodeInterner {
function_definition_ids: HashMap::new(),
function_modifiers: HashMap::new(),
function_modules: HashMap::new(),
struct_name_locations: HashMap::new(),
func_id_to_trait: HashMap::new(),
dependency_graph: petgraph::graph::DiGraph::new(),
dependency_graph_indices: HashMap::new(),
Expand Down Expand Up @@ -531,6 +554,7 @@ impl Default for NodeInterner {
type_alias_ref: Vec::new(),
type_ref_locations: Vec::new(),
quoted_types: Default::default(),
track_references: false,
location_indices: LocationIndices::default(),
reference_graph: petgraph::graph::DiGraph::new(),
reference_graph_indices: HashMap::new(),
Expand Down Expand Up @@ -928,6 +952,14 @@ impl NodeInterner {
&self.struct_attributes[struct_id]
}

pub fn add_struct_location(&mut self, struct_id: StructId, location: Location) {
self.struct_name_locations.insert(struct_id, location);
}

pub fn struct_location(&self, struct_id: &StructId) -> Location {
self.struct_name_locations[struct_id]
}

pub fn global_attributes(&self, global_id: &GlobalId) -> &[SecondaryAttribute] {
&self.global_attributes[global_id]
}
Expand Down
16 changes: 10 additions & 6 deletions noir/noir-repo/compiler/noirc_frontend/src/resolve_locations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ impl NodeInterner {
location: Location,
return_type_location_instead: bool,
) -> Option<Location> {
self.find_location_index(location)
.and_then(|index| self.resolve_location(index, return_type_location_instead))
.or_else(|| self.try_resolve_trait_impl_location(location))
.or_else(|| self.try_resolve_trait_method_declaration(location))
.or_else(|| self.try_resolve_type_ref(location))
.or_else(|| self.try_resolve_type_alias(location))
// First try to find the location in the reference graph
self.find_referenced_location(location).or_else(|| {
// Otherwise fallback to the location indices
self.find_location_index(location)
.and_then(|index| self.resolve_location(index, return_type_location_instead))
.or_else(|| self.try_resolve_trait_impl_location(location))
.or_else(|| self.try_resolve_trait_method_declaration(location))
.or_else(|| self.try_resolve_type_ref(location))
.or_else(|| self.try_resolve_type_alias(location))
})
}

pub fn get_declaration_location_from(&self, location: Location) -> Option<Location> {
Expand Down
Loading

0 comments on commit 2ae17f2

Please sign in to comment.