Skip to content

Commit

Permalink
feat(experimental): show macro errors where they happen (#7333)
Browse files Browse the repository at this point in the history
Co-authored-by: jfecher <jake@aztecprotocol.com>
  • Loading branch information
asterite and jfecher authored Feb 20, 2025
1 parent 44c35dc commit 04dd6d9
Show file tree
Hide file tree
Showing 116 changed files with 4,610 additions and 2,682 deletions.
220 changes: 96 additions & 124 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion compiler/noirc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
pub mod debug_info;
mod position;
pub mod reporter;
pub use position::{Location, Position, Span, Spanned};
pub use position::{Located, Location, Position, Span, Spanned};
pub use reporter::{CustomDiagnostic, DiagnosticKind};

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
85 changes: 79 additions & 6 deletions compiler/noirc_errors/src/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,68 @@ use codespan::Span as ByteSpan;
use fm::FileId;
use serde::{Deserialize, Serialize};
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
ops::Range,
};

pub type Position = u32;

#[derive(Eq, Debug, Clone)]
pub struct Located<T> {
pub contents: T,
location: Location,
}

/// This is important for tests. Two Located objects are equal if their content is equal
/// They may not have the same location. Use `.location()` to test for Location being equal specifically
impl<T: PartialEq> PartialEq<Located<T>> for Located<T> {
fn eq(&self, other: &Located<T>) -> bool {
self.contents == other.contents
}
}

impl<T: PartialOrd> PartialOrd<Located<T>> for Located<T> {
fn partial_cmp(&self, other: &Located<T>) -> Option<Ordering> {
self.contents.partial_cmp(&other.contents)
}
}

impl<T: Ord> Ord for Located<T> {
fn cmp(&self, other: &Located<T>) -> Ordering {
self.contents.cmp(&other.contents)
}
}

impl<T: Default> Default for Located<T> {
fn default() -> Self {
Self { contents: Default::default(), location: Location::dummy() }
}
}

/// Hash-based data structures (HashMap, HashSet) rely on the inverse of Hash
/// being injective, i.e. x.eq(y) => hash(x, H) == hash(y, H), we hence align
/// this with the above
impl<T: Hash> Hash for Located<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.contents.hash(state);
}
}

impl<T> Located<T> {
pub fn from(location: Location, contents: T) -> Located<T> {
Located { location, contents }
}

pub fn span(&self) -> Span {
self.location.span
}

pub fn location(&self) -> Location {
self.location
}
}

#[derive(PartialOrd, Eq, Ord, Debug, Clone, Default)]
pub struct Spanned<T> {
pub contents: T,
Expand Down Expand Up @@ -36,17 +92,13 @@ impl<T> Spanned<T> {
Spanned { span: Span::inclusive(start, end), contents }
}

pub const fn from(t_span: Span, contents: T) -> Spanned<T> {
pub fn from(t_span: Span, contents: T) -> Spanned<T> {
Spanned { span: t_span, contents }
}

pub fn span(&self) -> Span {
self.span
}

pub fn set_span(&mut self, span: Span) {
self.span = span;
}
}

impl<T> std::borrow::Borrow<T> for Spanned<T> {
Expand Down Expand Up @@ -135,12 +187,33 @@ impl Location {
}

pub fn dummy() -> Self {
Self { span: Span::single_char(0), file: FileId::dummy() }
Self { span: Span::default(), file: FileId::dummy() }
}

pub fn contains(&self, other: &Location) -> bool {
self.file == other.file && self.span.contains(&other.span)
}

#[must_use]
pub fn merge(self, other: Location) -> Location {
if self.file == other.file {
Location::new(self.span.merge(other.span), self.file)
} else {
self
}
}
}

impl Ord for Location {
fn cmp(&self, other: &Self) -> Ordering {
(self.file, self.span).cmp(&(other.file, other.span))
}
}

impl PartialOrd for Location {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

#[cfg(test)]
Expand Down
25 changes: 11 additions & 14 deletions compiler/noirc_evaluator/src/ssa/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ impl<'a> Parser<'a> {
}

fn eat_identifier(&mut self) -> ParseResult<Option<Identifier>> {
let span = self.token.to_span();
let span = self.token.span();
if let Some(name) = self.eat_ident()? {
Ok(Some(Identifier::new(name, span)))
} else {
Expand Down Expand Up @@ -960,72 +960,69 @@ impl<'a> Parser<'a> {
fn expected_instruction_or_terminator<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedInstructionOrTerminator {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_string_or_data<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedStringOrData {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_byte_string<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedByteString {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_identifier<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedIdentifier {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_int<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedInt {
found: self.token.token().clone(),
span: self.token.to_span(),
})
Err(ParserError::ExpectedInt { found: self.token.token().clone(), span: self.token.span() })
}

fn expected_type<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedType {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_value<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedValue {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_global_value<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedGlobalValue {
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_token<T>(&mut self, token: Token) -> ParseResult<T> {
Err(ParserError::ExpectedToken {
token,
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}

fn expected_one_of_tokens<T>(&mut self, tokens: &[Token]) -> ParseResult<T> {
Err(ParserError::ExpectedOneOfTokens {
tokens: tokens.to_vec(),
found: self.token.token().clone(),
span: self.token.to_span(),
span: self.token.span(),
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl SpannedToken {
SpannedToken(Spanned::from(span, token))
}

pub(crate) fn to_span(&self) -> Span {
pub(crate) fn span(&self) -> Span {
self.0.span()
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ impl<'a> FunctionContext<'a> {
let value = value.replace('{', "{{").replace('}', "}}");
string.push_str(&value);
}
FmtStrFragment::Interpolation(value, _span) => {
FmtStrFragment::Interpolation(value, _) => {
string.push('{');
string.push_str(value);
string.push('}');
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/ast/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::ast::{Ident, UnresolvedGenerics, UnresolvedType};
use crate::token::SecondaryAttribute;

use iter_extended::vecmap;
use noirc_errors::Span;
use noirc_errors::Location;

use super::{Documented, ItemVisibility};

Expand All @@ -16,7 +16,7 @@ pub struct NoirEnumeration {
pub visibility: ItemVisibility,
pub generics: UnresolvedGenerics,
pub variants: Vec<Documented<EnumVariant>>,
pub span: Span,
pub location: Location,
}

impl NoirEnumeration {
Expand Down
Loading

0 comments on commit 04dd6d9

Please sign in to comment.