anchor.diff:          {   By = groupBy.By |> rmap this.Expr
               Having = groupBy.Having |> Option.map this.Expr
           }
  -    member this.SelectCore(select : SelectCore) =
  +    member this.SelectCore(select : SelectCore, knownShape : InferredQueryShape option) =
           let checker, from =
               match select.From with
               | None -> this, None
  
positive.code:             | Not -> typeInference.Unify(operandType, InferredType.Boolean)
              | IsNull
              | NotNull -> result { return InferredType.Boolean }
  open TypeInferenceExtensions
  
  type TypeChecker(cxt : ITypeInferenceContext, scope : InferredSelectScope) =
  
negative.code:         {   Limit = this.Expr(limit.Limit, IntegerType Integer64)
              Offset = limit.Offset |> Option.map (fun e -> this.Expr(e, IntegerType Integer64))
          }
      member this.CompoundTerm(term : CompoundTerm, knownShape : InferredQueryShape option) : InfCompoundTerm =
          let info, value =
              match term.Value, knownShape with
              | Values vals, Some shape ->
                  let vals = vals |> rmap (fun w -> { WithSource.Value = rmap this.Expr w.Value; Source = w.Source })
                  let columns =
                      seq {
                          for rowIndex, row in vals |> Seq.indexed do
                              if row.Value.Count <> shape.Columns.Count then
                                  failAt row.Source <|
                                      sprintf "Incorrect number of columns (expected %d, got %d)"
                                          shape.Columns.Count row.Value.Count
                              for colVal, colShape in Seq.zip row.Value shape.Columns do
                                  cxt.Unify(colVal.Info.Type, colShape.Expr.Info.Type) |> resultOk row.Source
                                  if rowIndex > 0 then () else
                                  yield
                                      {   Expr = colVal
                                          FromAlias = None
                                          ColumnName = colShape.ColumnName
                                      }
                      } |> toReadOnlyList
                  TableLike
                      {   Table = CompoundTermResults
                          Query = { Columns = columns }
                      }, Values vals
              | Values vals, None ->
                  failAt term.Source "VALUES() clause can only be used when column names are implied by context"
              | Select select, knownShape ->
                  let select = this.SelectCore(select, knownShape)
                  select.Info, Select select
          {   Source = term.Source
              Value = value
              Info = info
          }
      member this.Compound(compound : CompoundExpr, knownShape : InferredQueryShape option) : InfCompoundExpr =
          let nested leftCompound rightTerm =
              match knownShape with
              | Some _ as shape ->
                  this.Compound(leftCompound, knownShape), this.CompoundTerm(rightTerm, knownShape)
              | None ->
                  let leftCompound = this.Compound(leftCompound, None)
                  leftCompound, this.CompoundTerm(rightTerm, Some leftCompound.Value.Info.Query)
          {   CompoundExpr.Source = compound.Source
              Value =
                  match compound.Value with
                  | CompoundTerm term -> CompoundTerm <| this.CompoundTerm(term, knownShape)
                  | Union (expr, term) -> Union <| nested expr term
                  | UnionAll (expr, term) -> UnionAll <| nested expr term
                  | Intersect (expr, term) -> Intersect <| nested expr term
                  | Except (expr, term) -> Except <| nested expr term
          }
      member this.Select(select : SelectStmt) : InfSelectStmt =
          {   Source = select.Source
  