Skip to content

Commit 4625137

Browse files
committed
feat: add std::warn::warn
1 parent df20280 commit 4625137

File tree

6 files changed

+64
-4
lines changed

6 files changed

+64
-4
lines changed

compiler/noirc_frontend/src/elaborator/patterns.rs

+25
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{
2020
node_interner::{
2121
DefinitionId, DefinitionInfo, DefinitionKind, ExprId, FuncId, GlobalId, TraitImplKind,
2222
},
23+
token::FunctionAttribute,
2324
};
2425

2526
use super::{Elaborator, ResolverMeta, path_resolution::PathResolutionItem};
@@ -572,6 +573,8 @@ impl Elaborator<'_> {
572573
}
573574
}
574575

576+
self.check_call_to_warn_builtin_at_runtime(&definition_kind, location);
577+
575578
let id = self.interner.push_expr(HirExpression::Ident(expr.clone(), generics.clone()));
576579

577580
self.interner.push_expr_location(id, location);
@@ -597,6 +600,28 @@ impl Elaborator<'_> {
597600
}
598601
}
599602

603+
// It's an error to call to the built-in function "warn" if we are not in a comptime context
604+
fn check_call_to_warn_builtin_at_runtime(
605+
&mut self,
606+
definition_kind: &Option<DefinitionKind>,
607+
location: Location,
608+
) {
609+
let Some(DefinitionKind::Function(func_id)) = definition_kind else {
610+
return;
611+
};
612+
613+
if self.in_comptime_context() {
614+
return;
615+
}
616+
617+
let attribute = self.interner.function_attributes(func_id).function();
618+
if let Some(FunctionAttribute::Builtin(builtin)) = attribute {
619+
if builtin == "warn" {
620+
self.push_err(ResolverError::WarnUsedAtRuntime { location });
621+
}
622+
}
623+
}
624+
600625
/// Solve any generics that are part of the path before the function, for example:
601626
///
602627
/// foo::Bar::<i32>::baz

compiler/noirc_frontend/src/hir/comptime/errors.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ pub enum InterpreterError {
256256
LoopHaltedForUiResponsiveness {
257257
location: Location,
258258
},
259+
Warning {
260+
message: String,
261+
location: Location,
262+
},
259263

260264
// These cases are not errors, they are just used to prevent us from running more code
261265
// until the loop can be resumed properly. These cases will never be displayed to users.
@@ -331,7 +335,8 @@ impl InterpreterError {
331335
| InterpreterError::UnknownArrayLength { location, .. }
332336
| InterpreterError::CannotInterpretFormatStringWithErrors { location }
333337
| InterpreterError::GlobalsDependencyCycle { location }
334-
| InterpreterError::LoopHaltedForUiResponsiveness { location } => *location,
338+
| InterpreterError::LoopHaltedForUiResponsiveness { location }
339+
| InterpreterError::Warning { location, .. } => *location,
335340

336341
InterpreterError::FailedToParseMacro { error, .. } => error.location(),
337342
InterpreterError::NoMatchingImplFound { error } => error.location,
@@ -695,6 +700,9 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic {
695700
"This error doesn't happen in normal executions of `nargo`".to_string();
696701
CustomDiagnostic::simple_warning(msg, secondary, *location)
697702
}
703+
InterpreterError::Warning { message, location } => {
704+
CustomDiagnostic::simple_warning(message.into(), String::new(), *location)
705+
}
698706
}
699707
}
700708
}

compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

+13
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ impl Interpreter<'_, '_> {
248248
"unresolved_type_is_bool" => unresolved_type_is_bool(interner, arguments, location),
249249
"unresolved_type_is_field" => unresolved_type_is_field(interner, arguments, location),
250250
"unresolved_type_is_unit" => unresolved_type_is_unit(interner, arguments, location),
251+
"warn" => warn(self.elaborator, arguments, location),
251252
"zeroed" => Ok(zeroed(return_type, location)),
252253
_ => {
253254
let item = format!("Comptime evaluation for builtin function '{name}'");
@@ -1403,6 +1404,18 @@ where
14031404
Ok(option(return_type, option_value, location))
14041405
}
14051406

1407+
// fn warn<T, let N: u32>(message: fmtstr<N, T>) {}
1408+
fn warn(
1409+
elaborator: &mut Elaborator,
1410+
arguments: Vec<(Value, Location)>,
1411+
location: Location,
1412+
) -> IResult<Value> {
1413+
let message = check_one_argument(arguments, location)?;
1414+
let (message, _) = get_format_string(elaborator.interner, message)?;
1415+
elaborator.push_err(InterpreterError::Warning { message: message.to_string(), location });
1416+
Ok(Value::Unit)
1417+
}
1418+
14061419
// fn zeroed<T>() -> T
14071420
fn zeroed(return_type: Type, location: Location) -> Value {
14081421
match return_type {

compiler/noirc_frontend/src/hir/resolution/errors.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ pub enum ResolverError {
192192
UnexpectedItemInPattern { location: Location, item: &'static str },
193193
#[error("Trait `{trait_name}` doesn't have a method named `{method_name}`")]
194194
NoSuchMethodInTrait { trait_name: String, method_name: String, location: Location },
195+
#[error("The `std::warn::warn` function cannot be called at runtime")]
196+
WarnUsedAtRuntime { location: Location },
195197
}
196198

197199
impl ResolverError {
@@ -255,9 +257,8 @@ impl ResolverError {
255257
| ResolverError::TypeUnsupportedInMatch { location, .. }
256258
| ResolverError::UnexpectedItemInPattern { location, .. }
257259
| ResolverError::NoSuchMethodInTrait { location, .. }
258-
| ResolverError::VariableAlreadyDefinedInPattern { new_location: location, .. } => {
259-
*location
260-
}
260+
| ResolverError::VariableAlreadyDefinedInPattern { new_location: location, .. }
261+
| ResolverError::WarnUsedAtRuntime { location } => *location,
261262
ResolverError::UnusedVariable { ident }
262263
| ResolverError::UnusedItem { ident, .. }
263264
| ResolverError::DuplicateField { field: ident }
@@ -801,6 +802,13 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
801802
*location,
802803
)
803804
},
805+
ResolverError::WarnUsedAtRuntime {location } => {
806+
Diagnostic::simple_error(
807+
"The `std::warn::warn` function cannot be called at runtime".to_string(),
808+
"This function can only be called in comptime code".to_string(),
809+
*location,
810+
)
811+
},
804812
}
805813
}
806814
}

noir_stdlib/src/lib.nr

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub mod append;
2222
pub mod mem;
2323
pub mod panic;
2424
pub mod hint;
25+
pub mod warn;
2526

2627
use convert::AsPrimitive;
2728

noir_stdlib/src/warn.nr

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// Produces a warning during compilation.
2+
///
3+
/// Note: this function cannot be used at runtime.
4+
#[builtin(warn)]
5+
pub comptime fn warn<T, let N: u32>(message: fmtstr<N, T>) {}

0 commit comments

Comments
 (0)