Repository: noir-lang/noir (Rust)

Issue:
Improve testing error locations
Right now in the compiler's frontend tests we just check that expected errors happen. However, we don't check **where** they happen.

One way to do this would be in a way similar to how it's done in parser tests:

https://github.com/noir-lang/noir/blob/8783e480a39efb47c7783c68b0e09c1c65b1f33a/compiler/noirc_frontend/src/parser/parser/statement.rs#L711-L724

That is, allow squiggles bellow a line, pre-process that input and extract the span where the error would happen.



Fix (patch):
diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs
index ae7f0bef150..c44bfa6389c 100644
--- a/compiler/noirc_frontend/src/ast/statement.rs
+++ b/compiler/noirc_frontend/src/ast/statement.rs
@@ -505,7 +505,11 @@ impl PathSegment {
     ///
     /// Returns an empty span at the end of `foo` if there's no turbofish.
     pub fn turbofish_span(&self) -> Span {
-        Span::from(self.ident.span().end()..self.location.span.end())
+        if self.ident.location().file == self.location.file {
+            Span::from(self.ident.span().end()..self.location.span.end())
+        } else {
+            self.location.span
+        }
     }
 
     pub fn turbofish_location(&self) -> Location {
diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs
index 9847ced3b41..91d72debc0c 100644
--- a/compiler/noirc_frontend/src/hir/resolution/errors.rs
+++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs
@@ -309,7 +309,7 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
 
                 let mut diagnostic = Diagnostic::simple_warning(
                     format!("unused variable {name}"),
-                    "unused variable ".to_string(),
+                    "unused variable".to_string(),
                     ident.location(),
                 );
                 diagnostic.unnecessary = true;
diff --git a/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs
index ceb1dee9cb3..16e25b80465 100644
--- a/compiler/noirc_frontend/src/hir/resolution/import.rs
+++ b/compiler/noirc_frontend/src/hir/resolution/import.rs
@@ -115,7 +115,8 @@ impl<'a> From<&'a PathResolutionError> for CustomDiagnostic {
                 CustomDiagnostic::simple_warning(error.to_string(), String::new(), ident.location())
             }
             PathResolutionError::UnresolvedWithPossibleTraitsToImport { ident, traits } => {
-                let traits = vecmap(traits, |trait_name| format!("`{}`", trait_name));
+                let mut traits = vecmap(traits, |trait_name| format!("`{}`", trait_name));
+                traits.sort();
                 CustomDiagnostic::simple_error(
                     error.to_string(),
                     format!(
@@ -126,7 +127,8 @@ impl<'a> From<&'a PathResolutionError> for CustomDiagnostic {
                 )
             }
             PathResolutionError::MultipleTraitsInScope { ident, traits } => {
-                let traits = vecmap(traits, |trait_name| format!("`{}`", trait_name));
+                let mut traits = vecmap(traits, |trait_name| format!("`{}`", trait_name));
+                traits.sort();
                 CustomDiagnostic::simple_error(
                     error.to_string(),
                     format!(
diff --git a/compiler/noirc_frontend/src/parser/parser/path.rs b/compiler/noirc_frontend/src/parser/parser/path.rs
index b2d0c713cf3..e48e37b748a 100644
--- a/compiler/noirc_frontend/src/parser/parser/path.rs
+++ b/compiler/noirc_frontend/src/parser/parser/path.rs
@@ -125,7 +125,11 @@ impl Parser<'_> {
                     None
                 };
 
-                segments.push(PathSegment { ident, generics, location });
+                segments.push(PathSegment {
+                    ident,
+                    generics,
+                    location: self.location_since(location),
+                });
 
                 if self.at(Token::DoubleColon)
                     && matches!(self.next_token.token(), Token::Ident(..))