diff --git a/accepted/future-releases/extension-types/feature-specification.md b/accepted/future-releases/extension-types/feature-specification.md
index 0ef63a337b..a5c928e687 100644
--- a/accepted/future-releases/extension-types/feature-specification.md
+++ b/accepted/future-releases/extension-types/feature-specification.md
@@ -15,6 +15,10 @@ information about the process, including in their change logs.
[1]: https://github.com/dart-lang/language/blob/master/working/1426-extension-types/feature-specification-views.md
[2]: https://github.com/dart-lang/language/blob/master/working/extension_structs/overview.md
+2023.10.06
+ - Added updated special-case inference rules for number types,
+ which are extension-type aware.
+
2023.09.11
- Add missing rule about getter/setter signature correspondence.
@@ -602,6 +606,91 @@ If _Dm_ is a method with function type `F`, and `args` exists, the static
analysis of the extension type member invocation is the same as that of an
invocation with argument part `args` of a function with the given type.
+#### Static analysis of extension member invocations on numbers
+
+The specification have special rules for some operations on numbers,
+a hard-coded set of dependent typing rules that makes it much more
+convenient to work with `num` subtypes.
+
+Those rules are updated, because extension types break two assumptions
+that the existing rules were written under:
+* Invoking a member named, for example, `+` on a non-bottom subtype of `int`
+ always invokes the known and trusted `int` member,
+ which always has the same signature.
+* There is no non-bottom type which is a subtype of both `int` and `double`.
+
+Extension type methods should not be special-cased,
+the rules changes are to *avoid* that happening.
+
+The rules are changed to the following phrasing:
+
+> **Binary operators**:
+> Let `e` be an expression of one of the forms `e1 + e2`, `e1 - e2`, `e1 * e2`,
+> or `e1 % e2`, or a normal invocation of the form `e1.remainder(e2)`,
+> where the static type of `e1` is a type *T*,
+> and *C* is the greatest closure of the context type scheme of `e`.
+>
+> If the corresponding member of *T* is not an extension type member,
+> and:
+> * either *T* \<: `num`, not *T* \<: `double`, and the function signature
+> of the corresponding member of *T* is `num Function(num)`,
+> * or *T* \<: `double`, not *T* \<: `int`, and the function signature
+> of the corresponding member of *T* is `double Function(num)`,
+>
+> then use the following rules for type inference instead of the default rules:
+>
+> * If `int` \<: *C*, not `double` \<: *C*, and *T* \<: `int`
+> then the context type of `e2` is `int`.
+> * If `double` \<: *C*, not `int` \<: *C*, and not *T* \<: `double`,
+> then the context type of `e2` is `double`.
+> * Otherwise, the context type of `e2` is `num`.
+>
+> Let *S* be the static type of `e2`.
+> If *S* is assignable to `num`, then:
+> * If *T* \<: `double` then the static type of `e` is `double`.
+> _This includes *S* being `dynamic` or `Never`._
+> * If *T* \<: `int`, *S* \<: `int`, and not *S* \<: `double`,
+> then the static type of `e` is `int`.
+> * Otherwise, if *S* \<: `double` and not *S* \<:`int`,
+> then the static type of `e` is `double`.
+> * Otherwise the static type of *e* is `num`.
+>
+> **Clamp**:
+> Let `e` be a normal invocation of the form `e1.clamp(e2, e3)`,
+> where the static type of `e1` is *T*1,
+> and *C* is the greatest closure of the context type scheme of `e`.
+>
+> If *T*1 \<: `num`, and not both
+> *T*1 \<: `int` and *T*1 \<: `double`,
+> *T*1.clamp
is not an extension type member,
+> and its function signature is `num Function(num, num)`, then
+> use the following rules for type inference instead of the default rules:
+>
+> * If `int` \<: *C*, not `double` \<: *C*, and *T*1 \<: `int`,
+> then the context type of both `e2` and `e3` is `int`.
+> * If `double` \<: *C*, not `int` \<: *C*, *T*1 \<: `double`,
+> then the context type of both `e2` and `e3` is `double`.
+> * Otherwise the context type of `e2` and `e3` is `num`.
+>
+> Let *T*2 and *T*3 be the static types of `e2` and
+> `e3` respectively.
+> If *T*2 and *T*3 are both
+> assignable of `num`, and neither is both a subtype of `int` and `double`,
+> then:
+> * If *T*1, *T*2 and *T*3 are all
+> subtypes of `int`, then the static type of `e` is `int`.
+> * If *T*1, *T*2 and *T*3 are all
+> subtypes of `double`, then the static type of `e` is `double`.
+> * Otherwise the static type of `e` is `num`.
+
+_These changes preserve the current behavior of all existing code,
+because the new restrictions are only excluding cases that couldn't
+exist before extension types._
+_An extension type which subtypes both `int` and `double` gets no promotion,
+nor does one which subtypes, for example, `int` and another interface in a way
+which changes the signature of the relevant members in the combined interface.
+Such extension types would necessarily have `Never` as representation type,
+so they are not useful for anything except complicating type inference._
### Dynamic Semantics of an Extension Type Member Invocation