Skip to content

Commit

Permalink
fix: Add foreign impl error (#2216)
Browse files Browse the repository at this point in the history
Add foreign impl error
  • Loading branch information
jfecher authored Aug 8, 2023
1 parent 968e12c commit a53f5ed
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
2 changes: 1 addition & 1 deletion crates/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ impl Context {

#[cfg(test)]
mod tests {
use std::{rc::Rc, collections::HashMap};
use std::{collections::HashMap, rc::Rc};

use acvm::{
acir::{
Expand Down
21 changes: 17 additions & 4 deletions crates/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use crate::hir::Context;
use crate::node_interner::{FuncId, NodeInterner, StmtId, StructId, TypeAliasId};
use crate::{
ExpressionKind, Generics, Ident, LetStatement, Literal, NoirFunction, NoirStruct,
NoirTypeAlias, ParsedModule, Shared, Type, TypeBinding, UnresolvedGenerics, UnresolvedType,
NoirTypeAlias, ParsedModule, Shared, StructType, Type, TypeBinding, UnresolvedGenerics,
UnresolvedType,
};
use fm::FileId;
use iter_extended::vecmap;
Expand Down Expand Up @@ -233,7 +234,19 @@ fn collect_impls(

extend_errors(errors, unresolved.file_id, resolver.take_errors());

if let Some(type_module) = get_local_id_from_type(&typ) {
if let Some(struct_type) = get_struct_type(&typ) {
let struct_type = struct_type.borrow();
let type_module = struct_type.id.0.local_id;

// `impl`s are only allowed on types defined within the current crate
if struct_type.id.0.krate != crate_id {
let span = *span;
let type_name = struct_type.name.to_string();
let error = DefCollectorErrorKind::ForeignImpl { span, type_name };
errors.push(error.into_file_diagnostic(unresolved.file_id));
continue;
}

// Grab the module defined by the struct type. Note that impls are a case
// where the module the methods are added to is not the same as the module
// they are resolved in.
Expand All @@ -258,9 +271,9 @@ fn collect_impls(
}
}

fn get_local_id_from_type(typ: &Type) -> Option<LocalModuleId> {
fn get_struct_type(typ: &Type) -> Option<&Shared<StructType>> {
match typ {
Type::Struct(definition, _) => Some(definition.borrow().id.0.local_id),
Type::Struct(definition, _) => Some(definition),
_ => None,
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/noirc_frontend/src/hir/def_collector/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub enum DefCollectorErrorKind {
PathResolutionError(PathResolutionError),
#[error("Non-struct type used in impl")]
NonStructTypeInImpl { span: Span },
#[error("Cannot `impl` a type defined outside the current crate")]
ForeignImpl { span: Span, type_name: String },
}

impl DefCollectorErrorKind {
Expand Down Expand Up @@ -101,6 +103,11 @@ impl From<DefCollectorErrorKind> for Diagnostic {
"Only struct types may have implementation methods".into(),
span,
),
DefCollectorErrorKind::ForeignImpl { span, type_name } => Diagnostic::simple_error(
"Cannot `impl` a type that was defined outside the current crate".into(),
format!("{type_name} was defined outside the current crate"),
span,
),
}
}
}

0 comments on commit a53f5ed

Please sign in to comment.