@@ -738,8 +738,11 @@ def replace(
738738 # If we cannot replace with own dtype, convert to ObjectBlock and
739739 # retry
740740 if not self ._can_hold_element (to_replace ):
741- # TODO: we should be able to infer at this point that there is
742- # nothing to replace
741+ if not isinstance (to_replace , list ):
742+ if inplace :
743+ return [self ]
744+ return [self .copy ()]
745+
743746 # GH 22083, TypeError or ValueError occurred within error handling
744747 # causes infinite loop. Cast and retry only if not objectblock.
745748 if is_object_dtype (self ):
@@ -764,14 +767,27 @@ def replace(
764767 filtered_out = ~ self .mgr_locs .isin (filter )
765768 mask [filtered_out .nonzero ()[0 ]] = False
766769
770+ if not mask .any ():
771+ if inplace :
772+ return [self ]
773+ return [self .copy ()]
774+
767775 try :
768776 blocks = self .putmask (mask , value , inplace = inplace )
777+ # Note: it is _not_ the case that self._can_hold_element(value)
778+ # is always true at this point. In particular, that can fail
779+ # for:
780+ # "2u" with bool-dtype, float-dtype
781+ # 0.5 with int64-dtype
782+ # np.nan with int64-dtype
769783 except (TypeError , ValueError ):
770784 # GH 22083, TypeError or ValueError occurred within error handling
771785 # causes infinite loop. Cast and retry only if not objectblock.
772786 if is_object_dtype (self ):
773787 raise
774788
789+ assert not self ._can_hold_element (value ), value
790+
775791 # try again with a compatible block
776792 block = self .astype (object )
777793 return block .replace (
@@ -924,6 +940,7 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0, transpose=False)
924940
925941 # if we are passed a scalar None, convert it here
926942 if not is_list_like (new ) and isna (new ) and not self .is_object :
943+ # FIXME: make sure we have compatible NA
927944 new = self .fill_value
928945
929946 if self ._can_hold_element (new ):
0 commit comments