diff --git a/src/infer.rs b/src/infer.rs index d00e756..a8ff279 100644 --- a/src/infer.rs +++ b/src/infer.rs @@ -8,7 +8,7 @@ use crate::{ errors::{format_err, Result}, scope::{CaseInsensitiveIdent, Scope, ScopeHandle}, tokenizer::{Literal, LiteralValue}, - types::{ColumnType, SimpleType, TableType, Type, TypeVar, ValueType}, + types::{ColumnType, SimpleType, TableType, Type, ValueType}, }; // TODO: Remember this rather scary example. Verify BigQuery supports it @@ -42,7 +42,7 @@ pub trait InferTypes { } impl InferTypes for ast::SqlProgram { - type Type = Option>; + type Type = Option; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { let mut ty = None; @@ -70,7 +70,7 @@ impl InferTypes for ast::SqlProgram { } impl InferTypes for ast::Statement { - type Type = Option>; + type Type = Option; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { match self { @@ -118,7 +118,7 @@ impl InferTypes for ast::CreateTableStatement { let column_decls = columns .node_iter() .map(|column| { - let ty = ValueType::::try_from(&column.data_type)?; + let ty = ValueType::try_from(&column.data_type)?; Ok(ColumnType { name: column.name.clone(), ty, @@ -165,7 +165,7 @@ impl InferTypes for ast::DropTableStatement { } impl InferTypes for ast::QueryStatement { - type Type = TableType; + type Type = TableType; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { let ast::QueryStatement { query_expression } = self; @@ -174,7 +174,7 @@ impl InferTypes for ast::QueryStatement { } impl InferTypes for ast::QueryExpression { - type Type = TableType; + type Type = TableType; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { match self { @@ -189,7 +189,7 @@ impl InferTypes for ast::QueryExpression { } impl InferTypes for ast::SelectExpression { - type Type = TableType; + type Type = TableType; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { // In order of type inference: @@ -247,7 +247,7 @@ impl InferTypes for ast::SelectExpression { } impl InferTypes for ast::Expression { - type Type = ValueType; + type Type = ValueType; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { match self { @@ -262,7 +262,7 @@ impl InferTypes for ast::Expression { } impl InferTypes for LiteralValue { - type Type = ValueType; + type Type = ValueType; fn infer_types(&mut self, scope: &ScopeHandle) -> Result<(Self::Type, ScopeHandle)> { let simple_ty = match self { @@ -289,7 +289,7 @@ mod tests { use super::*; - fn infer(sql: &str) -> Result<(Option>, ScopeHandle)> { + fn infer(sql: &str) -> Result<(Option, ScopeHandle)> { let mut program = match parse_sql(Path::new("test.sql"), sql) { Ok(program) => program, Err(e) => { diff --git a/src/types.rs b/src/types.rs index df93ef1..780caaa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -33,14 +33,23 @@ use crate::{ /// Sometimes we want concrete types, and sometimes we want types with type /// variables. This trait convers both those cases. -pub trait TypeVarSupport: fmt::Display {} +pub trait TypeVarSupport: fmt::Display + Sized { + /// Convert a [`TypeVar`] into a [`SimpleType`], if possible. + fn simple_type_from_type_var(tv: TypeVar) -> Result, &'static str>; +} /// This type can never be instantiated. We use this to represent a type variable with /// all type variables resolved. #[derive(Clone, Debug, PartialEq, Eq)] pub enum ResolvedTypeVarsOnly {} -impl TypeVarSupport for ResolvedTypeVarsOnly {} +impl TypeVarSupport for ResolvedTypeVarsOnly { + fn simple_type_from_type_var(_tv: TypeVar) -> Result, &'static str> { + // This will be a parser error with `"expected "` prepended. So it's + // hard to word well. + Err("something other than a type variable") + } +} impl fmt::Display for ResolvedTypeVarsOnly { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -76,7 +85,11 @@ impl TypeVar { } } -impl TypeVarSupport for TypeVar {} +impl TypeVarSupport for TypeVar { + fn simple_type_from_type_var(tv: TypeVar) -> Result, &'static str> { + Ok(SimpleType::Parameter(tv)) + } +} impl fmt::Display for TypeVar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -92,7 +105,7 @@ pub enum Type { Argument(ArgumentType), /// The type of a table, as seen in `CREATE TABLE` statements, or /// as returned from a sub-`SELECT`, or as passed to `UNNEST`. - Table(TableType), + Table(TableType), /// A function type. Function(FunctionType), } @@ -229,11 +242,11 @@ impl fmt::Display for StructElementType { /// A table type. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct TableType { - pub columns: Vec>, +pub struct TableType { + pub columns: Vec, } -impl fmt::Display for TableType { +impl fmt::Display for TableType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "TABLE<")?; for (i, column) in self.columns.iter().enumerate() { @@ -249,13 +262,13 @@ impl fmt::Display for TableType { /// A column type. #[derive(Clone, Debug, PartialEq, Eq)] -pub struct ColumnType { +pub struct ColumnType { pub name: Ident, - pub ty: ValueType, + pub ty: ValueType, pub not_null: bool, } -impl fmt::Display for ColumnType { +impl fmt::Display for ColumnType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} {}", BigQueryName(&self.name.name), self.ty)?; if self.not_null { @@ -441,21 +454,21 @@ peg::parser! { (name, ty) } - pub rule ty() -> Type + pub rule ty() -> Type = t:argument_type() { Type::Argument(t) } / t:table_type() { Type::Table(t) } / t:function_type() { Type::Function(t) } - rule argument_type() -> ArgumentType + rule argument_type() -> ArgumentType = "Agg" _? "<" _? t:value_type() _? ">" { ArgumentType::Aggregating(t) } / t:value_type() { ArgumentType::Value(t) } - rule value_type() -> ValueType + rule value_type() -> ValueType = t:simple_type() { ValueType::Simple(t) } / "ARRAY" _? "<" _? t:simple_type() _? ">" { ValueType::Array(Box::new(t)) } // Longest match first. - rule simple_type() -> SimpleType + rule simple_type() -> SimpleType = "BOOL" { SimpleType::Bool } / "BYTES" { SimpleType::Bytes } / "DATETIME" { SimpleType::Datetime } @@ -471,9 +484,9 @@ peg::parser! { / "TIME" { SimpleType::Time } / "STRUCT" _? "<" _? fields:(struct_field() ** (_? "," _?)) _? ">" { SimpleType::Struct(StructType { fields }) } - / type_var:type_var() { SimpleType::Parameter(type_var) } + / type_var:type_var() {? TV::simple_type_from_type_var(type_var) } - rule struct_field() -> StructElementType + rule struct_field() -> StructElementType = t:value_type() { StructElementType { name: None, ty: t } } / name:ident() _ t:value_type() { StructElementType { name: Some(name), ty: t } } @@ -513,14 +526,14 @@ peg::parser! { / ".." _? rest_params:value_type() { (Vec::new(), Some(rest_params)) } / { (Vec::new(), None) } - rule table_type() -> TableType + rule table_type() -> TableType = "TABLE" _? "<" _? columns:(column_type() ** (_? "," _?)) _? ">" { TableType { columns } } - rule column_type() -> ColumnType - = name:ident() _ t:value_type() not_null:not_null() { - ColumnType { name, ty: t, not_null } + rule column_type() -> ColumnType + = name:ident() _ ty:value_type() not_null:not_null() { + ColumnType { name, ty, not_null } } rule not_null() -> bool