Zulip Chat Archive

Stream: lean4

Topic: Emulating type ascriptions


Eric Wieser (Mar 23 2025 at 23:31):

Why does this copy-paste implementation of ( :) not behave the same way as ( :)?

import Lean

open Lean Elab Term

/-- A version of `(t :)` that does not process `·`s in `t`.

This should be preferred inside macros. -/
syntax (name := withNoExpectedType) "with_no_expected_type(" term ")" : term

@[term_elab withNoExpectedType, inherit_doc withNoExpectedType]
def elabWithNoExpectedType : TermElab
  -- copied from `elabTypeAscription`
  | `(with_no_expected_type($e)), expectedType? => do
    let e  withSynthesize (postpone := .no) <| elabTerm e none
    ensureHasType expectedType? e
  | _, _ => throwUnsupportedSyntax

-- works
/--
error: unsolved goals
p : Prop
h : p
⊢ ¬p
-/
#guard_msgs in
example {p : Prop} {h : p} :  {h : True}, 0 = 0 := by
  refine (absurd h ?_ :)

-- extra `True` hypothesis
/--
error: unsolved goals
p : Prop
h : p
h✝ : True
⊢ ¬p
-/
#guard_msgs in
example {p : Prop} {h : p} :  {h : True}, 0 = 0 := by
  refine with_no_expected_type(absurd h ?_)

Aaron Liu (Mar 23 2025 at 23:35):

lambda autoinsertion

Aaron Liu (Mar 23 2025 at 23:35):

I'll investigate

Aaron Liu (Mar 24 2025 at 01:00):

The difference seems to be in private def useImplicitLambda

Eric Wieser (Mar 24 2025 at 01:16):

Or rather, in blockImplicitLambda; thanks for finding that!

Eric Wieser (Mar 24 2025 at 01:18):

So I guess the answer is to add no_implicit_lambda

Eric Wieser (Mar 24 2025 at 13:00):

I can't seem to make this work:

import Lean

open Lean Elab Term Parser

/-- A set of parentheses which does not process `·` -/
@[term_parser]
def withoutCDot := leading_parser
  "without_cdot(" >> (withoutPosition (withoutForbidden (termParser >> optional (" :" >> optional (ppSpace >> termParser))))) >> ")"

@[term_elab withoutCDot, inherit_doc withoutCDot]
def elabWithoutCDot : TermElab
  -- copied from `elabTypeAscription`, with extra mkNoImplicitLambdaAnnotation
  | `(without_cdot($e : $type)), _ => do
    let type  withSynthesize (postpone := .yes) <| elabType type
    let type := mkNoImplicitLambdaAnnotation type
    let e  elabTerm e type
    ensureHasType type e
  | `(without_cdot($e :)), expectedType? => do
    let e  withSynthesize (postpone := .no) <| elabTerm e none
    ensureHasType (mkNoImplicitLambdaAnnotation <$> expectedType?) e
  | `(without_cdot($e)), expectedType? => do
    elabTerm e expectedType?
  | _, _ => throwUnsupportedSyntax

-- extra `True` hypothesis
/--
error: unsolved goals
p : Prop
h : p
⊢ ¬p
-/
#guard_msgs in
example {p : Prop} {h : p} :  {h : True}, 0 = 0 := by
  -- works only if you backspace `without_cdot`
  refine without_cdot(absurd h ?_ :)

Eric Wieser (Mar 24 2025 at 13:06):

Ah, I made this work with an intermediate elaborator, PR to mathlib incoming :)

Eric Wieser (Mar 24 2025 at 13:14):

#23257


Last updated: May 02 2025 at 03:31 UTC