`std::pmr::polymorphic_allocator` is a non-propagating allocator: `std::allocator_traits<std::pmr::polymorphic_allocator>::propagate_on_container_move_assignment::value` is `false` and correspondingly, it has its move assignment operator deleted. Since `basic_memory_buffer::operator=(basic_memory_buffer&& other)` unconditionally calls https://github.com/fmtlib/fmt/blob/40626af88bd7df9a5fb80be7b25ac85b122d6c21/include/fmt/format.h#L829-L830 for both propagating and non-propagating allocators, a snippet like this won't compile: ```c++ std::pmr::unsynchronized_pool_resource r1; using pmr_memory_buffer = fmt::basic_memory_buffer<char,10,std::pmr::polymorphic_allocator<char>>; pmr_memory_buffer b1{ &r1 }; pmr_memory_buffer b2{ &r1 }; ...... b2 = std::move( b1 ); ``` A bit more practical snippet can be found here: [Compiler Explorer](https://www.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:1,endLineNumber:23,positionColumn:1,positionLineNumber:23,selectionStartColumn:1,selectionStartLineNumber:23,startColumn:1,startLineNumber:23),source:'%23include+%3Cfmt/format.h%3E%0A%23include+%3Cstring%3E%0A%23include+%3Cmemory_resource%3E%0A%0Aint+main()+%7B%0A++++//+Ensure+no+allocations+are+made+from+the+default+resource%0A++++std::pmr::set_default_resource(std::pmr::null_memory_resource())%3B%0A%0A++++std::pmr::unsynchronized_pool_resource+r1%3B%0A++++%0A++++using+pmr_memory_buffer+%3D+fmt::basic_memory_buffer%3Cchar,10,std::pmr::polymorphic_allocator%3Cchar%3E%3E%3B%0A+%0A++++pmr_memory_buffer+b%7B%26r1%7D%3B%0A++++std::pmr::string+s1+%7B+%22s1............................%22,+%26r1+%7D%3B%0A++++fmt::format_to(std::back_inserter(b),+%22s1:+%7B%7D%22,+s1)%3B%0A%0A++++std::pmr::vector%3Cpmr_memory_buffer%3E+bv+%7B%26r1%7D%3B%0A%0A++++//+This+does+not+compile+because+pmr::polymorphic_allocator+does+not+have+a+move+ctor%0A++++//+because+it!'s+a+non-propagaing+allocator%0A++++bv.push_back+(+std::move(b)+)%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:executor,i:(argsPanelShown:'1',compilationPanelShown:'0',compiler:g151,compilerName:'',compilerOutShown:'0',execArgs:'',execStdin:'',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!((name:fmt,ver:trunk)),options:'',overrides:!(),runtimeTools:!(),source:1,stdinPanelShown:'1',wrap:'1'),l:'5',n:'0',o:'Executor+x86-64+gcc+15.1+(C%2B%2B,+Editor+%231)',t:'0')),header:(),k:50,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4). It was inspired by the way `fmt::memory_buffer` class is used in [spdlog](https://github.com/gabime/spdlog). Its `ringbuffer_sink` [declares](https://github.com/gabime/spdlog/blob/287333ee00555aaece5a5cf6acc9040563c6f642/include/spdlog/sinks/ringbuffer_sink.h#L59) a circular buffer of basically `fmt::memory_buffer`s, and `move()`ing instances of `fmt::memory_buffer`s into it when they are ready. I'm considering a fix where the move-propagating allocators will behave as before, whereas those that don't propagate on move will check whether the allocators (and the memory resources) are the same for the source and for the target. If source and target allocator instances are the same, `move()` can proceed as usual, passing ownership of the underlying buffer. If the allocators are different, the buffer is then copied. That would replicate the behaviour of standard library containers.