From efe7df7f45f585278feb41a13ce73d3916d24b4c Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Mon, 11 Oct 2021 11:32:49 -0700 Subject: [PATCH] Keep track of where primitives are defined for better error messages --- cranelift/isle/isle/src/codegen.rs | 4 ++-- cranelift/isle/isle/src/sema.rs | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cranelift/isle/isle/src/codegen.rs b/cranelift/isle/isle/src/codegen.rs index 32e291a4dc..ca983d922a 100644 --- a/cranelift/isle/isle/src/codegen.rs +++ b/cranelift/isle/isle/src/codegen.rs @@ -173,7 +173,7 @@ impl<'a> Codegen<'a> { fn type_name(&self, typeid: TypeId, by_ref: bool) -> String { 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, .. } => { let r = if by_ref { "&" } else { "" }; format!("{}{}", r, self.typeenv.syms[name.index()]) @@ -229,7 +229,7 @@ impl<'a> Codegen<'a> { fn const_int(&self, val: i64, ty: TypeId) -> String { 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!(), }; if is_bool { diff --git a/cranelift/isle/isle/src/sema.rs b/cranelift/isle/isle/src/sema.rs index ae87981b65..9b6e8dfde7 100644 --- a/cranelift/isle/isle/src/sema.rs +++ b/cranelift/isle/isle/src/sema.rs @@ -94,7 +94,7 @@ pub enum Type { /// /// These are always defined externally, and we allow literals of these /// types to pass through from ISLE source code to the emitted Rust code. - Primitive(TypeId, Sym), + Primitive(TypeId, Sym, Pos), /// A sum type. /// @@ -120,7 +120,14 @@ impl Type { /// Get the name of this `Type`. pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str { 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) => { let tid = TypeId(tyenv.type_map.len()); 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( 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; } + tyenv.type_map.insert(name, tid); } _ => {} @@ -619,7 +633,7 @@ impl TypeEnv { let name = self.intern(&ty.name).unwrap(); match &ty.ty { &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, ..) => { let mut variants = vec![];