python / python/cpython

Comment for bounded_lru_cache_wrapper seems incorrect

オープン
#94,879 コメント 8 件 リアクション 0 件 担当者 3 名 GitHub で見る

@tim-one がすでに取り組んでいます。

2022年7月17日 から。

extension-modules type-bug
主要言語
Python
スター
77.2k
フォーク
36k
PR マージ指標
PR 指標を取得中

説明

https://github.com/python/cpython/blob/c22f134211743cd5ad14cec1dd4f527bee542b4c/Modules/_functoolsmodule.c#L975-L976
However the __eq__ method call actually could be made for the deletion of the oldest entry.

from functools import lru_cache

class A:
    def __init__(self, name):
        self.name = name
        self.counter = []

    def __hash__(self):
        return 0 # mock hash collision
    
    def __eq__(self, __o: 'A'):
        self.counter.append(__o.name)
        return self is __o

@lru_cache(maxsize=2)
def foo(_):
    return 0

a, b, c = A('a'), A('b'), A('c')

foo(a)
foo(b)

# make 'b' be the oldest-used entry
# but not the oldest-inserted entry
foo(a)
a.counter.clear()

foo(c) # will evict 'b'

# The assertion shows that
# 'a' was compared with 'b' for the deletion of 'b'
assert 'b' in a.counter
print(a.counter) # ['c', 'c', 'b', 'c']

It seems that reentrant here might cause the assertion in L1092 failed:
https://github.com/python/cpython/blob/c22f134211743cd5ad14cec1dd4f527bee542b4c/Modules/_functoolsmodule.c#L1092-L1099
Since link has been extracted but hasn't been popped from cache dict, link list could be empty while cache dict is full.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。