Skip to content

Commit

Permalink
Merge branch 'master' into tf/function-exports
Browse files Browse the repository at this point in the history
* master:
  feat(lsp): goto trait from trait impl (#3956)
  fix: preserve brillig entrypoint functions without arguments (#3951)
  feat: implement `Eq` trait on curve points (#3944)
  • Loading branch information
TomAFrench committed Jan 5, 2024
2 parents e98a839 + eb566e2 commit d08c4fb
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 52 deletions.
16 changes: 12 additions & 4 deletions compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ impl AcirContext {
inverse_code,
vec![AcirValue::Var(var, AcirType::field())],
vec![AcirType::field()],
true,
)?;
let inverted_var = Self::expect_one_var(results);

Expand Down Expand Up @@ -708,6 +709,7 @@ impl AcirContext {
AcirValue::Var(rhs, AcirType::unsigned(bit_size)),
],
vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)],
true,
)?
.try_into()
.expect("quotient only returns two values");
Expand Down Expand Up @@ -1310,6 +1312,7 @@ impl AcirContext {
generated_brillig: GeneratedBrillig,
inputs: Vec<AcirValue>,
outputs: Vec<AcirType>,
attempt_execution: bool,
) -> Result<Vec<AcirValue>, InternalError> {
let b_inputs = try_vecmap(inputs, |i| match i {
AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)),
Expand All @@ -1329,10 +1332,15 @@ impl AcirContext {

// Optimistically try executing the brillig now, if we can complete execution they just return the results.
// This is a temporary measure pending SSA optimizations being applied to Brillig which would remove constant-input opcodes (See #2066)
if let Some(brillig_outputs) =
self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs)
{
return Ok(brillig_outputs);
//
// We do _not_ want to do this in the situation where the `main` function is unconstrained, as if execution succeeds
// the entire program will be replaced with witness constraints to its outputs.
if attempt_execution {
if let Some(brillig_outputs) =
self.execute_brillig(&generated_brillig.byte_code, &b_inputs, &outputs)
{
return Ok(brillig_outputs);
}
}

// Otherwise we must generate ACIR for it and execute at runtime.
Expand Down
5 changes: 4 additions & 1 deletion compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,14 @@ impl Context {

let code = self.gen_brillig_for(main_func, &brillig)?;

// We specifically do not attempt execution of the brillig code being generated as this can result in it being
// replaced with constraints on witnesses to the program outputs.
let output_values = self.acir_context.brillig(
self.current_side_effects_enabled_var,
code,
inputs,
outputs,
false,
)?;
let output_vars: Vec<_> = output_values
.iter()
Expand Down Expand Up @@ -489,7 +492,7 @@ impl Context {

let outputs: Vec<AcirType> = vecmap(result_ids, |result_id| dfg.type_of_value(*result_id).into());

let output_values = self.acir_context.brillig(self.current_side_effects_enabled_var, code, inputs, outputs)?;
let output_values = self.acir_context.brillig(self.current_side_effects_enabled_var, code, inputs, outputs, true)?;

// Compiler sanity check
assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA");
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/hir_def/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
Generics, Ident, NoirFunction, Type, TypeVariable, TypeVariableId,
};
use fm::FileId;
use noirc_errors::Span;
use noirc_errors::{Location, Span};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TraitFunction {
Expand Down Expand Up @@ -56,7 +56,7 @@ pub struct Trait {

pub name: Ident,
pub generics: Generics,
pub span: Span,
pub location: Location,

/// When resolving the types of Trait elements, all references to `Self` resolve
/// to this TypeVariable. Then when we check if the types of trait impl elements
Expand Down
26 changes: 24 additions & 2 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ impl NodeInterner {
/// The [Location] may not necessarily point to the beginning of the item
/// so we check if the location's span is contained within the start or end
/// of each items [Span]
#[tracing::instrument(skip(self))]
pub fn find_location_index(&self, location: Location) -> Option<impl Into<Index>> {
let mut location_candidate: Option<(&Index, &Location)> = None;

Expand Down Expand Up @@ -504,7 +505,7 @@ impl NodeInterner {
id: type_id,
name: unresolved_trait.trait_def.name.clone(),
crate_id: unresolved_trait.crate_id,
span: unresolved_trait.trait_def.span,
location: Location::new(unresolved_trait.trait_def.span, unresolved_trait.file_id),
generics: vecmap(&unresolved_trait.trait_def.generics, |_| {
// Temporary type variable ids before the trait is resolved to its actual ids.
// This lets us record how many arguments the type expects so that other types
Expand Down Expand Up @@ -1142,6 +1143,7 @@ impl NodeInterner {
}

/// Adds a trait implementation to the list of known implementations.
#[tracing::instrument(skip(self))]
pub fn add_trait_implementation(
&mut self,
object_type: Type,
Expand Down Expand Up @@ -1274,7 +1276,9 @@ impl NodeInterner {
/// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId].
/// Returns [None] when definition is not found.
pub fn get_definition_location_from(&self, location: Location) -> Option<Location> {
self.find_location_index(location).and_then(|index| self.resolve_location(index))
self.find_location_index(location)
.and_then(|index| self.resolve_location(index))
.or_else(|| self.try_resolve_trait_impl_location(location))
}

/// For a given [Index] we return [Location] to which we resolved to
Expand Down Expand Up @@ -1429,6 +1433,24 @@ impl NodeInterner {
pub(crate) fn ordering_type(&self) -> Type {
self.ordering_type.clone().expect("Expected ordering_type to be set in the NodeInterner")
}

/// Attempts to resolve [Location] of [Trait] based on [Location] of [TraitImpl]
/// This is used by LSP to resolve the location of a trait based on the location of a trait impl.
///
/// Example:
/// impl Foo for Bar { ... } -> trait Foo { ... }
fn try_resolve_trait_impl_location(&self, location: Location) -> Option<Location> {
self.trait_implementations
.iter()
.find(|shared_trait_impl| {
let trait_impl = shared_trait_impl.borrow();
trait_impl.file == location.file && trait_impl.ident.span().contains(&location.span)
})
.and_then(|shared_trait_impl| {
let trait_impl = shared_trait_impl.borrow();
self.traits.get(&trait_impl.trait_id).map(|trait_| trait_.location)
})
}
}

impl Methods {
Expand Down
25 changes: 15 additions & 10 deletions noir_stdlib/src/ec/montcurve.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ mod affine {
use crate::ec::safe_inverse;
use crate::ec::sqrt;
use crate::ec::ZETA;
use crate::cmp::Eq;

// Curve specification
struct Curve { // Montgomery Curve configuration (ky^2 = x^3 + j*x^2 + x)
j: Field,
Expand All @@ -32,11 +34,6 @@ mod affine {
Self {x, y, infty: false}
}

// Check for equality
fn eq(self, p: Self) -> bool {
(self.infty & p.infty) | (!self.infty & !p.infty & (self.x == p.x) & (self.y == p.y))
}

// Check if zero
pub fn is_zero(self) -> bool {
self.infty
Expand Down Expand Up @@ -76,6 +73,12 @@ mod affine {
}
}

impl Eq for Point {
fn eq(self, p: Self) -> bool {
(self.infty & p.infty) | (!self.infty & !p.infty & (self.x == p.x) & (self.y == p.y))
}
}

impl Curve {
// Curve constructor
pub fn new(j: Field, k: Field, gen: Point) -> Self {
Expand Down Expand Up @@ -219,6 +222,7 @@ mod curvegroup {
use crate::ec::swcurve::curvegroup::Point as SWPoint;
use crate::ec::tecurve::curvegroup::Curve as TECurve;
use crate::ec::tecurve::curvegroup::Point as TEPoint;
use crate::cmp::Eq;

struct Curve { // Montgomery Curve configuration (ky^2 z = x*(x^2 + j*x*z + z*z))
j: Field,
Expand All @@ -239,11 +243,6 @@ mod curvegroup {
Self {x, y, z}
}

// Check for equality
fn eq(self, p: Self) -> bool {
(self.z == p.z) | (((self.x * self.z) == (p.x * p.z)) & ((self.y * self.z) == (p.y * p.z)))
}

// Check if zero
pub fn is_zero(self) -> bool {
self.z == 0
Expand Down Expand Up @@ -277,6 +276,12 @@ mod curvegroup {
}
}

impl Eq for Point {
fn eq(self, p: Self) -> bool {
(self.z == p.z) | (((self.x * self.z) == (p.x * p.z)) & ((self.y * self.z) == (p.y * p.z)))
}
}

impl Curve {
// Curve constructor
pub fn new(j: Field, k: Field, gen: Point) -> Self {
Expand Down
40 changes: 23 additions & 17 deletions noir_stdlib/src/ec/swcurve.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ mod affine {
use crate::ec::safe_inverse;
use crate::ec::is_square;
use crate::ec::sqrt;
use crate::cmp::Eq;

// Curve specification
struct Curve { // Short Weierstraß curve
// Coefficients in defining equation y^2 = x^3 + ax + b
Expand All @@ -28,15 +30,6 @@ mod affine {
Self {x, y, infty: false}
}

// Check for equality
fn eq(self, p: Point) -> bool {
let Self {x: x1, y: y1, infty: inf1} = self;
let Self {x: x2, y: y2, infty: inf2} = p;

(inf1 & inf2)
| (!inf1 & !inf2 & (x1 == x2) & (y1 == y2))
}

// Check if zero
pub fn is_zero(self) -> bool {
self.eq(Point::zero())
Expand Down Expand Up @@ -65,6 +58,16 @@ mod affine {
}
}

impl Eq for Point {
fn eq(self, p: Self) -> bool {
let Self {x: x1, y: y1, infty: inf1} = self;
let Self {x: x2, y: y2, infty: inf2} = p;

(inf1 & inf2)
| (!inf1 & !inf2 & (x1 == x2) & (y1 == y2))
}
}

impl Curve {
// Curve constructor
pub fn new(a: Field, b: Field, gen: Point) -> Curve {
Expand Down Expand Up @@ -182,6 +185,8 @@ mod curvegroup {
// Points are represented by three-dimensional Jacobian coordinates.
// See <https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates> for details.
use crate::ec::swcurve::affine;
use crate::cmp::Eq;

// Curve specification
struct Curve { // Short Weierstraß curve
// Coefficients in defining equation y^2 = x^3 + axz^4 + bz^6
Expand All @@ -203,14 +208,6 @@ mod curvegroup {
Self {x, y, z}
}

// Check for equality
fn eq(self, p: Point) -> bool {
let Self {x: x1, y: y1, z: z1} = self;
let Self {x: x2, y: y2, z: z2} = p;

((z1 == 0) & (z2 == 0)) | ((z1 != 0) & (z2 != 0) & (x1*z2*z2 == x2*z1*z1) & (y1*z2*z2*z2 == y2*z1*z1*z1))
}

// Check if zero
pub fn is_zero(self) -> bool {
self.eq(Point::zero())
Expand Down Expand Up @@ -240,6 +237,15 @@ mod curvegroup {
}
}

impl Eq for Point {
fn eq(self, p: Self) -> bool {
let Self {x: x1, y: y1, z: z1} = self;
let Self {x: x2, y: y2, z: z2} = p;

((z1 == 0) & (z2 == 0)) | ((z1 != 0) & (z2 != 0) & (x1*z2*z2 == x2*z1*z1) & (y1*z2*z2*z2 == y2*z1*z1*z1))
}
}

impl Curve {
// Curve constructor
pub fn new(a: Field, b: Field, gen: Point) -> Curve {
Expand Down
38 changes: 22 additions & 16 deletions noir_stdlib/src/ec/tecurve.nr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod affine {
use crate::ec::montcurve::affine::Point as MPoint;
use crate::ec::swcurve::affine::Curve as SWCurve;
use crate::ec::swcurve::affine::Point as SWPoint;
use crate::cmp::Eq;

// Curve specification
struct Curve { // Twisted Edwards curve
// Coefficients in defining equation ax^2 + y^2 = 1 + dx^2y^2
Expand All @@ -29,14 +31,6 @@ mod affine {
Self { x, y }
}

// Check for equality
fn eq(self, p: Point) -> bool {
let Self {x: x1, y: y1} = self;
let Self {x: x2, y: y2} = p;

(x1 == x2) & (y1 == y2)
}

// Check if zero
pub fn is_zero(self) -> bool {
self.eq(Point::zero())
Expand Down Expand Up @@ -74,6 +68,15 @@ mod affine {
}
}

impl Eq for Point {
fn eq(self, p: Self) -> bool {
let Self {x: x1, y: y1} = self;
let Self {x: x2, y: y2} = p;

(x1 == x2) & (y1 == y2)
}
}

impl Curve {
// Curve constructor
pub fn new(a: Field, d: Field, gen: Point) -> Curve {
Expand Down Expand Up @@ -198,6 +201,8 @@ mod curvegroup {
use crate::ec::montcurve::curvegroup::Point as MPoint;
use crate::ec::swcurve::curvegroup::Curve as SWCurve;
use crate::ec::swcurve::curvegroup::Point as SWPoint;
use crate::cmp::Eq;

// Curve specification
struct Curve { // Twisted Edwards curve
// Coefficients in defining equation a(x^2 + y^2)z^2 = z^4 + dx^2y^2
Expand All @@ -220,14 +225,6 @@ mod curvegroup {
Self {x, y, t, z}
}

// Check for equality
fn eq(self, p: Point) -> bool {
let Self {x: x1, y: y1, t: _t1, z: z1} = self;
let Self {x: x2, y: y2, t: _t2, z:z2} = p;

(x1*z2 == x2*z1) & (y1*z2 == y2*z1)
}

// Check if zero
pub fn is_zero(self) -> bool {
let Self {x, y, t, z} = self;
Expand Down Expand Up @@ -259,6 +256,15 @@ mod curvegroup {
}
}

impl Eq for Point {
fn eq(self, p: Self) -> bool {
let Self {x: x1, y: y1, t: _t1, z: z1} = self;
let Self {x: x2, y: y2, t: _t2, z:z2} = p;

(x1*z2 == x2*z1) & (y1*z2 == y2*z1)
}
}

impl Curve {
// Curve constructor
pub fn new(a: Field, d: Field, gen: Point) -> Curve {
Expand Down

0 comments on commit d08c4fb

Please sign in to comment.