Skip to content

Commit b627b3f

Browse files
digama0Komyyy
authored andcommitted
feat: opaque_repr attr to suppress "trivial structure" opt (pt 2)
1 parent 559da7c commit b627b3f

File tree

8 files changed

+57
-0
lines changed

8 files changed

+57
-0
lines changed

Diff for: src/Init/Core.lean

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ attribute [simp] namedPattern
3838
Thunks are "lazy" values that are evaluated when first accessed using `Thunk.get/map/bind`.
3939
The value is then stored and not recomputed for all further accesses. -/
4040
-- NOTE: the runtime has special support for the `Thunk` type to implement this behavior
41+
@[opaque_repr]
4142
structure Thunk (α : Type u) : Type u where
4243
/-- Constructs a new thunk from a function `Unit → α`
4344
that will be called when the thunk is forced. -/
@@ -359,6 +360,7 @@ possibly being computed on another thread. This is similar to `Future` in Scala,
359360
360361
The tasks have an overridden representation in the runtime.
361362
-/
363+
@[opaque_repr]
362364
structure Task (α : Type u) : Type u where
363365
/-- `Task.pure (a : α)` constructs a task that is already resolved with value `a`. -/
364366
pure ::

Diff for: src/Init/Data/ByteArray/Basic.lean

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Init.Data.UInt.Basic
1010
import Init.Data.Option.Basic
1111
universe u
1212

13+
@[opaque_repr]
1314
structure ByteArray where
1415
data : Array UInt8
1516

Diff for: src/Init/Data/Float.lean

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ opaque floatSpec : FloatSpec := {
2626
decLe := fun _ _ => inferInstanceAs (Decidable True)
2727
}
2828

29+
@[opaque_repr]
2930
structure Float where
3031
val : floatSpec.float
3132

Diff for: src/Init/Data/FloatArray/Basic.lean

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Init.Data.Float
99
import Init.Data.Option.Basic
1010
universe u
1111

12+
@[opaque_repr]
1213
structure FloatArray where
1314
data : Array Float
1415

Diff for: src/Init/Data/Int/Basic.lean

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ and larger numbers use an arbitrary precision "bignum" library
3737
(usually [GMP](https://gmplib.org/)). A "small number" is an integer
3838
that can be encoded with 63 bits (31 bits on 32-bits architectures).
3939
-/
40+
@[opaque_repr]
4041
inductive Int : Type where
4142
/-- A natural number is an integer (`0` to `∞`). -/
4243
| ofNat : Nat → Int

Diff for: src/Init/Prelude.lean

+8
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,7 @@ This type is special-cased by both the kernel and the compiler:
10411041
to 2^63 directly and larger numbers use an arbitrary precision "bignum"
10421042
library (usually [GMP](https://gmplib.org/)).
10431043
-/
1044+
@[opaque_repr]
10441045
inductive Nat where
10451046
/-- `Nat.zero`, normally written `0 : Nat`, is the smallest natural number.
10461047
This is one of the two constructors of `Nat`. -/
@@ -1820,6 +1821,7 @@ abbrev UInt8.size : Nat := 256
18201821
The type of unsigned 8-bit integers. This type has special support in the
18211822
compiler to make it actually 8 bits rather than wrapping a `Nat`.
18221823
-/
1824+
@[opaque_repr]
18231825
structure UInt8 where
18241826
/-- Unpack a `UInt8` as a `Nat` less than `2^8`.
18251827
This function is overridden with a native implementation. -/
@@ -1859,6 +1861,7 @@ abbrev UInt16.size : Nat := 65536
18591861
The type of unsigned 16-bit integers. This type has special support in the
18601862
compiler to make it actually 16 bits rather than wrapping a `Nat`.
18611863
-/
1864+
@[opaque_repr]
18621865
structure UInt16 where
18631866
/-- Unpack a `UInt16` as a `Nat` less than `2^16`.
18641867
This function is overridden with a native implementation. -/
@@ -1898,6 +1901,7 @@ abbrev UInt32.size : Nat := 4294967296
18981901
The type of unsigned 32-bit integers. This type has special support in the
18991902
compiler to make it actually 32 bits rather than wrapping a `Nat`.
19001903
-/
1904+
@[opaque_repr]
19011905
structure UInt32 where
19021906
/-- Unpack a `UInt32` as a `Nat` less than `2^32`.
19031907
This function is overridden with a native implementation. -/
@@ -1974,6 +1978,7 @@ abbrev UInt64.size : Nat := 18446744073709551616
19741978
The type of unsigned 64-bit integers. This type has special support in the
19751979
compiler to make it actually 64 bits rather than wrapping a `Nat`.
19761980
-/
1981+
@[opaque_repr]
19771982
structure UInt64 where
19781983
/-- Unpack a `UInt64` as a `Nat` less than `2^64`.
19791984
This function is overridden with a native implementation. -/
@@ -2040,6 +2045,7 @@ for the platform's architecture.
20402045
For example, if running on a 32-bit machine, USize is equivalent to UInt32.
20412046
Or on a 64-bit machine, UInt64.
20422047
-/
2048+
@[opaque_repr]
20432049
structure USize where
20442050
/-- Unpack a `USize` as a `Nat` less than `USize.size`.
20452051
This function is overridden with a native implementation. -/
@@ -2323,6 +2329,7 @@ def List.get {α : Type u} : (as : List α) → Fin as.length → α
23232329
The compiler overrides the data representation of this type to a byte sequence,
23242330
and both `String.utf8ByteSize` and `String.length` are cached and O(1).
23252331
-/
2332+
@[opaque_repr]
23262333
structure String where
23272334
/-- Pack a `List Char` into a `String`. This function is overridden by the
23282335
compiler and is O(n) in the length of the list. -/
@@ -2547,6 +2554,7 @@ as they are used "linearly" all updates will be performed destructively on the
25472554
array, so it has comparable performance to mutable arrays in imperative
25482555
programming languages.
25492556
-/
2557+
@[opaque_repr]
25502558
structure Array (α : Type u) where
25512559
/-- Convert a `List α` into an `Array α`. This function is overridden
25522560
to `List.toArray` and is O(n) in the length of the list. -/

Diff for: tests/lean/opaqueReprAttr.lean

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
namespace MkAndValAreOptimizedAway
2+
3+
structure MyZero where
4+
val : Nat
5+
6+
def MyZero.valImpl (_self : MyZero) : Nat := 0
7+
attribute [implemented_by MyZero.valImpl] MyZero.val
8+
9+
unsafe def MyZero.mkImpl (_val : Nat) : MyZero := unsafeCast 0
10+
attribute [implemented_by MyZero.mkImpl] MyZero.mk
11+
12+
#eval (MyZero.mk 1).val -- 1
13+
14+
end MkAndValAreOptimizedAway
15+
16+
namespace UsingAttr
17+
18+
@[opaque_repr]
19+
structure MyZero where
20+
val : Nat
21+
22+
def MyZero.valImpl (_self : MyZero) : Nat := 0
23+
attribute [implemented_by MyZero.valImpl] MyZero.val
24+
25+
unsafe def MyZero.mkImpl (_val : Nat) : MyZero := unsafeCast 0
26+
attribute [implemented_by MyZero.mkImpl] MyZero.mk
27+
28+
#eval (MyZero.mk 1).val -- 0
29+
30+
-- FIXME: it would be nice if we didn't have to override casesOn too
31+
@[inline] def MyZero.casesOnImpl {motive : MyZero → Sort u} (t : MyZero)
32+
(mk : ∀ val, motive { val }) : motive t := mk _
33+
attribute [implemented_by MyZero.casesOnImpl] MyZero.casesOn
34+
35+
-- we need a blackBox here because the compiler will optimize
36+
-- `(MyZero.mk n).casesOn f` to `f n` otherwise (and this is desirable, even for opaque_repr types)
37+
@[noinline] def blackBox := @id
38+
#eval ((blackBox (MyZero.mk 1)).casesOn fun n => n : Nat) -- 0
39+
40+
end UsingAttr

Diff for: tests/lean/opaqueReprAttr.lean.expected.out

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
1
2+
0
3+
0

0 commit comments

Comments
 (0)