Skip to content

Commit

Permalink
Improved error reporting on linking errors
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Jan 18, 2024
1 parent f932b4a commit 4cd04c8
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 41 deletions.
6 changes: 6 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ pub struct LinkInfo {
pub span : Span
}

impl LinkInfo {
pub fn get_full_name(&self) -> String {
format!("::{}", self.name)
}
}

#[derive(Debug)]
pub struct Module {
pub link_info : LinkInfo,
Expand Down
26 changes: 18 additions & 8 deletions src/flattening.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,29 @@ impl<'inst, 'l, 'm, 'resolved> FlatteningContext<'inst, 'l, 'm, 'resolved> {
}
}
}
fn flatten_declaration<const ONLY_ALLOW_TYPES : bool>(&mut self, decl_id : DeclID, read_only : bool) -> FlatID {
fn flatten_declaration<const ALLOW_MODULES : bool>(&mut self, decl_id : DeclID, read_only : bool) -> FlatID {
let decl = &self.module.declarations[decl_id];

if ONLY_ALLOW_TYPES {
if let TypeExpression::Named = &decl.typ.0 {
if let Some(NameElem::Module(module_id)) = self.linker.try_resolve_global(decl.typ.1) {
let md = &self.linker.get_module(module_id);
return self.alloc_module_interface(decl.name.clone(), md, module_id, decl.typ.1)
let typ : Type = if let TypeExpression::Named = &decl.typ.0 {
match self.linker.resolve_global(decl.typ.1, &self.errors) {
Some(NameElem::Module(id)) if ALLOW_MODULES => {
let md = &self.linker.get_module(id);
return self.alloc_module_interface(decl.name.clone(), md, id, decl.typ.1)
}
Some(NameElem::Type(id)) => {
Type::Named{id, span : Some(decl.typ.1)}
}
Some(global_module_or_type) => {
let accepted = if ALLOW_MODULES {"Type or Module"} else {"Type"};
self.linker.make_bad_error_location_error(global_module_or_type, accepted, decl.typ.1, &self.errors);
Type::Error
}
None => Type::Error
}
}
} else {
self.map_to_type(&decl.typ)
};

let typ = self.map_to_type(&decl.typ);
let typ_span = decl.typ.1;

let inst_id = self.instantiations.alloc(Instantiation::WireDeclaration(WireDeclaration{
Expand Down
68 changes: 35 additions & 33 deletions src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ pub const fn get_builtin_constant(name : &'static str) -> ConstantUUID {
}
}

pub struct LinkingErrorLocation<'a> {
pub struct LinkingErrorLocation {
pub named_type : &'static str,
pub name : &'a str,
pub full_name : String,
pub location : Option<(FileUUID, Span)>
}

Expand All @@ -60,7 +60,7 @@ pub trait Linkable {
fn get_full_name(&self) -> String {
format!("::{}", self.get_name())
}
fn get_linking_error_location<'a>(&'a self) -> LinkingErrorLocation<'a>;
fn get_linking_error_location(&self) -> LinkingErrorLocation;
fn get_link_info(&self) -> Option<&LinkInfo>;
fn get_link_info_mut(&mut self) -> Option<&mut LinkInfo>;
}
Expand All @@ -81,10 +81,8 @@ impl Linkable for NamedConstant {
NamedConstant::Builtin{name, typ:_, val:_} => name
}
}
fn get_linking_error_location<'a>(&'a self) -> LinkingErrorLocation<'a> {
match self {
NamedConstant::Builtin{name, typ:_, val:_} => LinkingErrorLocation { named_type: "Builtin Constant", name, location: None }
}
fn get_linking_error_location(&self) -> LinkingErrorLocation {
LinkingErrorLocation { named_type: "Builtin Constant", full_name : self.get_full_name(), location: None }
}
fn get_link_info(&self) -> Option<&LinkInfo> {
match self {
Expand All @@ -104,10 +102,8 @@ impl Linkable for NamedType {
NamedType::Builtin(name) => name,
}
}
fn get_linking_error_location<'a>(&'a self) -> LinkingErrorLocation<'a> {
match self {
NamedType::Builtin(name) => LinkingErrorLocation { named_type: "Builtin Type", name, location: None },
}
fn get_linking_error_location(&self) -> LinkingErrorLocation {
LinkingErrorLocation { named_type: "Builtin Type", full_name : self.get_full_name(), location: None }
}
fn get_link_info(&self) -> Option<&LinkInfo> {
match self {
Expand Down Expand Up @@ -223,11 +219,11 @@ impl Linker {
}
}
}
fn get_linking_error_location<'a>(&'a self, global : NameElem) -> LinkingErrorLocation<'a> {
fn get_linking_error_location(&self, global : NameElem) -> LinkingErrorLocation {
match global {
NameElem::Module(id) => {
let md = &self.modules[id];
LinkingErrorLocation{named_type: "Module", name : &md.link_info.name, location: Some((md.link_info.file, md.link_info.name_span))}
LinkingErrorLocation{named_type: "Module", full_name : md.link_info.get_full_name(), location: Some((md.link_info.file, md.link_info.name_span))}
}
NameElem::Type(id) => self.types[id].get_linking_error_location(),
NameElem::Constant(id) => self.constants[id].get_linking_error_location(),
Expand Down Expand Up @@ -410,32 +406,38 @@ impl<'linker, 'resolved_list> GlobalResolver<'linker, 'resolved_list> {
let name = self.file.get_token_text(name_span.assert_is_single_token());

let mut resolved_globals = self.resolved_globals.borrow_mut();
if let Some(NamespaceElement::Global(found)) = self.linker.global_namespace.get(name) {
resolved_globals.referenced_globals.push(*found);
Some(*found)
} else {
resolved_globals.all_resolved = false;
match self.linker.global_namespace.get(name) {
Some(NamespaceElement::Global(found)) => {
resolved_globals.referenced_globals.push(*found);
Some(*found)
}
Some(NamespaceElement::Colission(coll)) => {
resolved_globals.all_resolved = false;

errors.error_basic(name_span, format!("No Value or Type of the name '{name}' was found. Did you forget to import it?"));
let decl_infos = coll.iter().map(|collider_global| {
let err_loc = self.linker.get_linking_error_location(*collider_global);
if let Some((file, span)) = err_loc.location {
error_info(span, file, format!("{} {} declared here", err_loc.named_type, err_loc.full_name))
} else {
// Kinda hacky, point the 'builtin' back to the declaration location because builtins don't have a location
error_info(name_span, errors.file, format!("{} {}", err_loc.named_type, err_loc.full_name))
}
}).collect();

None
}
}
errors.error_with_info(name_span, format!("There were colliding imports for the name '{name}'. Pick one and import it by name."), decl_infos);

pub fn try_resolve_global(&self, name_span : Span) -> Option<NameElem> {
let name = self.file.get_token_text(name_span.assert_is_single_token());
None
}
None => {
resolved_globals.all_resolved = false;

let mut resolved_globals = self.resolved_globals.borrow_mut();
if let Some(NamespaceElement::Global(found)) = self.linker.global_namespace.get(name) {
resolved_globals.referenced_globals.push(*found);
Some(*found)
} else {
resolved_globals.all_resolved = false;
errors.error_basic(name_span, format!("No Global of the name '{name}' was found. Did you forget to import it?"));

None
None
}
}
}

pub fn get_module(&self, uuid : ModuleUUID) -> &'linker Module {
&self.linker.modules[uuid]
}
Expand All @@ -447,7 +449,7 @@ impl<'linker, 'resolved_list> GlobalResolver<'linker, 'resolved_list> {
} else {
vec![]
};
let name = info.name;
let name = info.full_name;
let ident_type = info.named_type;
errors.error_with_info(identifier_span, format!("{ident_type} {name} is not a {expected}!"), infos);
}
Expand Down

0 comments on commit 4cd04c8

Please sign in to comment.