Keep track of where primitives are defined for better error messages

This commit is contained in:
Nick Fitzgerald
2021-10-11 11:32:49 -07:00
committed by Chris Fallin
parent fe836a2302
commit efe7df7f45
2 changed files with 21 additions and 7 deletions

View File

@@ -173,7 +173,7 @@ impl<'a> Codegen<'a> {
fn type_name(&self, typeid: TypeId, by_ref: bool) -> String { fn type_name(&self, typeid: TypeId, by_ref: bool) -> String {
match &self.typeenv.types[typeid.index()] { match &self.typeenv.types[typeid.index()] {
&Type::Primitive(_, sym) => self.typeenv.syms[sym.index()].clone(), &Type::Primitive(_, sym, _) => self.typeenv.syms[sym.index()].clone(),
&Type::Enum { name, .. } => { &Type::Enum { name, .. } => {
let r = if by_ref { "&" } else { "" }; let r = if by_ref { "&" } else { "" };
format!("{}{}", r, self.typeenv.syms[name.index()]) format!("{}{}", r, self.typeenv.syms[name.index()])
@@ -229,7 +229,7 @@ impl<'a> Codegen<'a> {
fn const_int(&self, val: i64, ty: TypeId) -> String { fn const_int(&self, val: i64, ty: TypeId) -> String {
let is_bool = match &self.typeenv.types[ty.index()] { let is_bool = match &self.typeenv.types[ty.index()] {
&Type::Primitive(_, name) => &self.typeenv.syms[name.index()] == "bool", &Type::Primitive(_, name, _) => &self.typeenv.syms[name.index()] == "bool",
_ => unreachable!(), _ => unreachable!(),
}; };
if is_bool { if is_bool {

View File

@@ -94,7 +94,7 @@ pub enum Type {
/// ///
/// These are always defined externally, and we allow literals of these /// These are always defined externally, and we allow literals of these
/// types to pass through from ISLE source code to the emitted Rust code. /// types to pass through from ISLE source code to the emitted Rust code.
Primitive(TypeId, Sym), Primitive(TypeId, Sym, Pos),
/// A sum type. /// A sum type.
/// ///
@@ -120,7 +120,14 @@ impl Type {
/// Get the name of this `Type`. /// Get the name of this `Type`.
pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str { pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str {
match self { match self {
Self::Primitive(_, name) | Self::Enum { name, .. } => &tyenv.syms[name.index()], Self::Primitive(_, name, _) | Self::Enum { name, .. } => &tyenv.syms[name.index()],
}
}
/// Get the position where this type was defined.
pub fn pos(&self) -> Pos {
match self {
Self::Primitive(_, _, pos) | Self::Enum { pos, .. } => *pos,
} }
} }
@@ -551,13 +558,20 @@ impl TypeEnv {
&ast::Def::Type(ref td) => { &ast::Def::Type(ref td) => {
let tid = TypeId(tyenv.type_map.len()); let tid = TypeId(tyenv.type_map.len());
let name = tyenv.intern_mut(&td.name); let name = tyenv.intern_mut(&td.name);
if tyenv.type_map.contains_key(&name) {
if let Some(existing) = tyenv.type_map.get(&name).copied() {
tyenv.report_error( tyenv.report_error(
td.pos, td.pos,
format!("Type name defined more than once: '{}'", td.name.0), format!("Type with name '{}' defined more than once", td.name.0),
);
let pos = unwrap_or_continue!(tyenv.types.get(existing.index())).pos();
tyenv.report_error(
pos,
format!("Type with name '{}' already defined here", td.name.0),
); );
continue; continue;
} }
tyenv.type_map.insert(name, tid); tyenv.type_map.insert(name, tid);
} }
_ => {} _ => {}
@@ -619,7 +633,7 @@ impl TypeEnv {
let name = self.intern(&ty.name).unwrap(); let name = self.intern(&ty.name).unwrap();
match &ty.ty { match &ty.ty {
&ast::TypeValue::Primitive(ref id, ..) => { &ast::TypeValue::Primitive(ref id, ..) => {
Some(Type::Primitive(tid, self.intern_mut(id))) Some(Type::Primitive(tid, self.intern_mut(id), ty.pos))
} }
&ast::TypeValue::Enum(ref ty_variants, ..) => { &ast::TypeValue::Enum(ref ty_variants, ..) => {
let mut variants = vec![]; let mut variants = vec![];