From a53f5ed86ad9a372ecad8a0367f7af3a843aae56 Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 8 Aug 2023 13:24:20 -0500 Subject: [PATCH] fix: Add foreign impl error (#2216) Add foreign impl error --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 2 +- .../src/hir/def_collector/dc_crate.rs | 21 +++++++++++++++---- .../src/hir/def_collector/errors.rs | 7 +++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs index aca809a85fa..7409a199641 100644 --- a/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -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::{ diff --git a/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs b/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs index 2beebf6871c..631f0cf86e4 100644 --- a/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/crates/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -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; @@ -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. @@ -258,9 +271,9 @@ fn collect_impls( } } -fn get_local_id_from_type(typ: &Type) -> Option { +fn get_struct_type(typ: &Type) -> Option<&Shared> { match typ { - Type::Struct(definition, _) => Some(definition.borrow().id.0.local_id), + Type::Struct(definition, _) => Some(definition), _ => None, } } diff --git a/crates/noirc_frontend/src/hir/def_collector/errors.rs b/crates/noirc_frontend/src/hir/def_collector/errors.rs index d18df58d64d..03f528020f8 100644 --- a/crates/noirc_frontend/src/hir/def_collector/errors.rs +++ b/crates/noirc_frontend/src/hir/def_collector/errors.rs @@ -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 { @@ -101,6 +103,11 @@ impl From 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, + ), } } }