<html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type"><style type="text/css">.lst-kix_ay8wo1jz5sry-5>li:before{content:"\0025a0   "}ol.lst-kix_81wbzl4od4r2-8.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-8 0}.lst-kix_ay8wo1jz5sry-4>li:before{content:"\0025cb   "}.lst-kix_ay8wo1jz5sry-6>li:before{content:"\0025cf   "}.lst-kix_um824w1i5wo5-4>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-8>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-8}.lst-kix_um824w1i5wo5-2>li:before{content:"-  "}.lst-kix_um824w1i5wo5-5>li:before{content:"-  "}.lst-kix_um824w1i5wo5-1>li:before{content:"-  "}.lst-kix_o48uop49q1mj-7>li:before{content:"-  "}.lst-kix_ay8wo1jz5sry-1>li:before{content:"\0025cb   "}.lst-kix_o48uop49q1mj-6>li:before{content:"-  "}.lst-kix_o48uop49q1mj-8>li:before{content:"-  "}.lst-kix_ay8wo1jz5sry-0>li:before{content:"  "}.lst-kix_ay8wo1jz5sry-8>li:before{content:"\0025a0   "}.lst-kix_ay8wo1jz5sry-7>li:before{content:"\0025cb   "}.lst-kix_um824w1i5wo5-3>li:before{content:"-  "}.lst-kix_o48uop49q1mj-3>li:before{content:"-  "}.lst-kix_o48uop49q1mj-2>li:before{content:"-  "}.lst-kix_o48uop49q1mj-4>li:before{content:"-  "}.lst-kix_o48uop49q1mj-5>li:before{content:"-  "}.lst-kix_o48uop49q1mj-1>li:before{content:"-  "}.lst-kix_um824w1i5wo5-7>li:before{content:"-  "}.lst-kix_5lely89nlm5f-7>li:before{content:"-  "}.lst-kix_um824w1i5wo5-6>li:before{content:"-  "}.lst-kix_um824w1i5wo5-8>li:before{content:"-  "}.lst-kix_5lely89nlm5f-6>li:before{content:"-  "}.lst-kix_5lely89nlm5f-8>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-1>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-0>li:before{content:"-  "}.lst-kix_5lely89nlm5f-3>li:before{content:"-  "}ol.lst-kix_81wbzl4od4r2-2.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-2 0}.lst-kix_rfzv2nw2zdyp-7>li:before{content:"-  "}.lst-kix_5lely89nlm5f-2>li:before{content:"-  "}.lst-kix_5lely89nlm5f-4>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-5>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-7>li:before{content:"-  "}.lst-kix_rfzv2nw2zdyp-6>li:before{content:"-  "}.lst-kix_5lely89nlm5f-1>li:before{content:"-  "}.lst-kix_5lely89nlm5f-5>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-2>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-6>li:before{content:"-  "}.lst-kix_rfzv2nw2zdyp-4>li:before{content:"-  "}ul.lst-kix_djklkkdjtwyh-7{list-style-type:none}ul.lst-kix_djklkkdjtwyh-6{list-style-type:none}.lst-kix_rfzv2nw2zdyp-3>li:before{content:"-  "}.lst-kix_rfzv2nw2zdyp-5>li:before{content:"-  "}.lst-kix_o48uop49q1mj-0>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-3>li:before{content:"-  "}ul.lst-kix_djklkkdjtwyh-8{list-style-type:none}ul.lst-kix_djklkkdjtwyh-3{list-style-type:none}ul.lst-kix_djklkkdjtwyh-2{list-style-type:none}ul.lst-kix_djklkkdjtwyh-5{list-style-type:none}.lst-kix_cp6bxtsqi6a6-4>li:before{content:"-  "}ul.lst-kix_djklkkdjtwyh-4{list-style-type:none}.lst-kix_rfzv2nw2zdyp-0>li:before{content:"-  "}.lst-kix_rfzv2nw2zdyp-1>li:before{content:"-  "}.lst-kix_rfzv2nw2zdyp-2>li:before{content:"-  "}.lst-kix_5lely89nlm5f-0>li:before{content:"-  "}.lst-kix_um824w1i5wo5-0>li:before{content:"-  "}.lst-kix_cp6bxtsqi6a6-8>li:before{content:"-  "}ul.lst-kix_5lely89nlm5f-4{list-style-type:none}ul.lst-kix_5lely89nlm5f-3{list-style-type:none}ul.lst-kix_5lely89nlm5f-2{list-style-type:none}ul.lst-kix_5lely89nlm5f-1{list-style-type:none}ul.lst-kix_5lely89nlm5f-0{list-style-type:none}ul.lst-kix_5lely89nlm5f-8{list-style-type:none}ul.lst-kix_5lely89nlm5f-7{list-style-type:none}ul.lst-kix_5lely89nlm5f-6{list-style-type:none}ul.lst-kix_5lely89nlm5f-5{list-style-type:none}ul.lst-kix_6qhps9sefnil-7{list-style-type:none}ul.lst-kix_6qhps9sefnil-8{list-style-type:none}ul.lst-kix_djklkkdjtwyh-1{list-style-type:none}ul.lst-kix_djklkkdjtwyh-0{list-style-type:none}ul.lst-kix_6qhps9sefnil-3{list-style-type:none}ul.lst-kix_6qhps9sefnil-4{list-style-type:none}ul.lst-kix_6qhps9sefnil-5{list-style-type:none}ul.lst-kix_6qhps9sefnil-6{list-style-type:none}ul.lst-kix_6qhps9sefnil-0{list-style-type:none}ul.lst-kix_6qhps9sefnil-1{list-style-type:none}ul.lst-kix_6qhps9sefnil-2{list-style-type:none}ol.lst-kix_81wbzl4od4r2-6{list-style-type:none}ol.lst-kix_81wbzl4od4r2-7{list-style-type:none}ol.lst-kix_81wbzl4od4r2-8{list-style-type:none}.lst-kix_rfzv2nw2zdyp-8>li:before{content:"-  "}ol.lst-kix_81wbzl4od4r2-2{list-style-type:none}ol.lst-kix_81wbzl4od4r2-3{list-style-type:none}ol.lst-kix_81wbzl4od4r2-4{list-style-type:none}ol.lst-kix_81wbzl4od4r2-5{list-style-type:none}ol.lst-kix_81wbzl4od4r2-7.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-7 0}ol.lst-kix_81wbzl4od4r2-0{list-style-type:none}ol.lst-kix_81wbzl4od4r2-1{list-style-type:none}li.li-bullet-2:before{margin-left:-18pt;white-space:nowrap;display:inline-block;min-width:18pt}ul.lst-kix_rfzv2nw2zdyp-1{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-2{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-3{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-4{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-5{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-6{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-7{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-8{list-style-type:none}ul.lst-kix_rfzv2nw2zdyp-0{list-style-type:none}ul.lst-kix_9qmrz6tdepc-6{list-style-type:none}ul.lst-kix_9qmrz6tdepc-7{list-style-type:none}.lst-kix_8kqnp1rikc31-0>li:before{content:"-  "}ul.lst-kix_9qmrz6tdepc-8{list-style-type:none}.lst-kix_8kqnp1rikc31-2>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-2>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-2}ul.lst-kix_9qmrz6tdepc-2{list-style-type:none}ol.lst-kix_81wbzl4od4r2-1.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-1 0}ul.lst-kix_9qmrz6tdepc-3{list-style-type:none}ul.lst-kix_9qmrz6tdepc-4{list-style-type:none}ul.lst-kix_9qmrz6tdepc-5{list-style-type:none}ul.lst-kix_9qmrz6tdepc-0{list-style-type:none}.lst-kix_8kqnp1rikc31-4>li:before{content:"-  "}.lst-kix_8kqnp1rikc31-6>li:before{content:"-  "}ul.lst-kix_9qmrz6tdepc-1{list-style-type:none}.lst-kix_vcgp1be9i72x-2>li:before{content:"\0025a0   "}ul.lst-kix_cp6bxtsqi6a6-2{list-style-type:none}ul.lst-kix_cp6bxtsqi6a6-3{list-style-type:none}.lst-kix_vcgp1be9i72x-4>li:before{content:"\0025cb   "}ul.lst-kix_cp6bxtsqi6a6-0{list-style-type:none}ul.lst-kix_cp6bxtsqi6a6-1{list-style-type:none}.lst-kix_vkugqbqlo8ky-7>li:before{content:"-  "}.lst-kix_vcgp1be9i72x-8>li:before{content:"\0025a0   "}ul.lst-kix_cp6bxtsqi6a6-8{list-style-type:none}ul.lst-kix_cp6bxtsqi6a6-6{list-style-type:none}ul.lst-kix_cp6bxtsqi6a6-7{list-style-type:none}.lst-kix_vcgp1be9i72x-6>li:before{content:"\0025cf   "}ul.lst-kix_cp6bxtsqi6a6-4{list-style-type:none}ul.lst-kix_cp6bxtsqi6a6-5{list-style-type:none}.lst-kix_81wbzl4od4r2-3>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-3}ul.lst-kix_vkugqbqlo8ky-0{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-1{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-2{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-3{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-4{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-5{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-6{list-style-type:none}li.li-bullet-1:before{margin-left:-18pt;white-space:nowrap;display:inline-block;min-width:18pt}.lst-kix_81wbzl4od4r2-4>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-4}ul.lst-kix_a17aea4cfg0-7{list-style-type:none}ul.lst-kix_a17aea4cfg0-8{list-style-type:none}ul.lst-kix_um824w1i5wo5-1{list-style-type:none}ul.lst-kix_um824w1i5wo5-0{list-style-type:none}ul.lst-kix_um824w1i5wo5-3{list-style-type:none}ul.lst-kix_um824w1i5wo5-2{list-style-type:none}.lst-kix_9qmrz6tdepc-5>li:before{content:"-  "}ul.lst-kix_um824w1i5wo5-5{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-7{list-style-type:none}ul.lst-kix_a17aea4cfg0-0{list-style-type:none}ul.lst-kix_um824w1i5wo5-4{list-style-type:none}ul.lst-kix_vkugqbqlo8ky-8{list-style-type:none}ul.lst-kix_a17aea4cfg0-1{list-style-type:none}ul.lst-kix_um824w1i5wo5-7{list-style-type:none}ul.lst-kix_a17aea4cfg0-2{list-style-type:none}ul.lst-kix_um824w1i5wo5-6{list-style-type:none}.lst-kix_9qmrz6tdepc-3>li:before{content:"-  "}ul.lst-kix_a17aea4cfg0-3{list-style-type:none}ul.lst-kix_a17aea4cfg0-4{list-style-type:none}ul.lst-kix_um824w1i5wo5-8{list-style-type:none}ul.lst-kix_a17aea4cfg0-5{list-style-type:none}ul.lst-kix_a17aea4cfg0-6{list-style-type:none}.lst-kix_9qmrz6tdepc-1>li:before{content:"-  "}.lst-kix_eom0zhdf11n2-0>li:before{content:"-  "}.lst-kix_87842qfl5vuj-7>li:before{content:"-  "}ol.lst-kix_81wbzl4od4r2-3.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-3 0}.lst-kix_4u9cncx1z8xi-0>li:before{content:"\0025cf   "}.lst-kix_eom0zhdf11n2-2>li:before{content:"-  "}.lst-kix_87842qfl5vuj-5>li:before{content:"-  "}.lst-kix_djklkkdjtwyh-6>li:before{content:"-  "}.lst-kix_4u9cncx1z8xi-8>li:before{content:"\0025a0   "}ul.lst-kix_8kqnp1rikc31-2{list-style-type:none}ul.lst-kix_8kqnp1rikc31-1{list-style-type:none}ul.lst-kix_8kqnp1rikc31-0{list-style-type:none}.lst-kix_djklkkdjtwyh-8>li:before{content:"-  "}ul.lst-kix_vcgp1be9i72x-7{list-style-type:none}ul.lst-kix_vcgp1be9i72x-6{list-style-type:none}ul.lst-kix_8kqnp1rikc31-8{list-style-type:none}ul.lst-kix_8kqnp1rikc31-7{list-style-type:none}ul.lst-kix_vcgp1be9i72x-8{list-style-type:none}ul.lst-kix_8kqnp1rikc31-6{list-style-type:none}ul.lst-kix_vcgp1be9i72x-3{list-style-type:none}ul.lst-kix_8kqnp1rikc31-5{list-style-type:none}ul.lst-kix_vcgp1be9i72x-2{list-style-type:none}ul.lst-kix_8kqnp1rikc31-4{list-style-type:none}ul.lst-kix_vcgp1be9i72x-5{list-style-type:none}ul.lst-kix_8kqnp1rikc31-3{list-style-type:none}ul.lst-kix_vcgp1be9i72x-4{list-style-type:none}.lst-kix_4u9cncx1z8xi-6>li:before{content:"\0025cf   "}ol.lst-kix_81wbzl4od4r2-4.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-4 0}.lst-kix_vkugqbqlo8ky-5>li:before{content:"-  "}.lst-kix_4u9cncx1z8xi-4>li:before{content:"\0025cb   "}.lst-kix_eom0zhdf11n2-6>li:before{content:"-  "}.lst-kix_eom0zhdf11n2-4>li:before{content:"-  "}.lst-kix_eom0zhdf11n2-8>li:before{content:"-  "}.lst-kix_87842qfl5vuj-3>li:before{content:"-  "}.lst-kix_vkugqbqlo8ky-3>li:before{content:"-  "}ul.lst-kix_vcgp1be9i72x-1{list-style-type:none}ul.lst-kix_vcgp1be9i72x-0{list-style-type:none}.lst-kix_4u9cncx1z8xi-2>li:before{content:"\0025a0   "}.lst-kix_ay8wo1jz5sry-3>li:before{content:"\0025cf   "}.lst-kix_87842qfl5vuj-1>li:before{content:"-  "}.lst-kix_vkugqbqlo8ky-1>li:before{content:"-  "}.lst-kix_a17aea4cfg0-1>li:before{content:"-  "}.lst-kix_a17aea4cfg0-0>li:before{content:"-  "}.lst-kix_a17aea4cfg0-4>li:before{content:"-  "}.lst-kix_a17aea4cfg0-3>li:before{content:"-  "}.lst-kix_a17aea4cfg0-2>li:before{content:"-  "}.lst-kix_djklkkdjtwyh-1>li:before{content:"-  "}.lst-kix_djklkkdjtwyh-2>li:before{content:"-  "}.lst-kix_djklkkdjtwyh-3>li:before{content:"-  "}.lst-kix_djklkkdjtwyh-4>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-7>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-7}.lst-kix_a17aea4cfg0-7>li:before{content:"-  "}.lst-kix_a17aea4cfg0-8>li:before{content:"-  "}ol.lst-kix_81wbzl4od4r2-5.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-5 0}.lst-kix_a17aea4cfg0-5>li:before{content:"-  "}.lst-kix_djklkkdjtwyh-0>li:before{content:"-  "}.lst-kix_a17aea4cfg0-6>li:before{content:"-  "}.lst-kix_6qhps9sefnil-5>li:before{content:"-  "}.lst-kix_6qhps9sefnil-6>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-5>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-5}.lst-kix_6qhps9sefnil-2>li:before{content:"-  "}.lst-kix_9qmrz6tdepc-7>li:before{content:"-  "}.lst-kix_6qhps9sefnil-3>li:before{content:"-  "}.lst-kix_6qhps9sefnil-4>li:before{content:"-  "}.lst-kix_9qmrz6tdepc-8>li:before{content:"-  "}ul.lst-kix_eom0zhdf11n2-6{list-style-type:none}ul.lst-kix_eom0zhdf11n2-7{list-style-type:none}ul.lst-kix_eom0zhdf11n2-4{list-style-type:none}ul.lst-kix_eom0zhdf11n2-5{list-style-type:none}ul.lst-kix_eom0zhdf11n2-2{list-style-type:none}ul.lst-kix_eom0zhdf11n2-3{list-style-type:none}ul.lst-kix_eom0zhdf11n2-0{list-style-type:none}ul.lst-kix_eom0zhdf11n2-1{list-style-type:none}.lst-kix_6qhps9sefnil-1>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-7>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-7,lower-latin) ". "}.lst-kix_6qhps9sefnil-0>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-8>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-8,lower-roman) ". "}ol.lst-kix_81wbzl4od4r2-6.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-6 0}ul.lst-kix_eom0zhdf11n2-8{list-style-type:none}.lst-kix_81wbzl4od4r2-2>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-2,lower-roman) ". "}.lst-kix_81wbzl4od4r2-3>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-3,decimal) ". "}ul.lst-kix_ay8wo1jz5sry-0{list-style-type:none}.lst-kix_81wbzl4od4r2-6>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-6,decimal) ". "}ul.lst-kix_ay8wo1jz5sry-1{list-style-type:none}ol.lst-kix_81wbzl4od4r2-0.start{counter-reset:lst-ctn-kix_81wbzl4od4r2-0 0}ul.lst-kix_ay8wo1jz5sry-2{list-style-type:none}.lst-kix_81wbzl4od4r2-4>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-4,lower-latin) ". "}.lst-kix_81wbzl4od4r2-5>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-5,lower-roman) ". "}ul.lst-kix_ay8wo1jz5sry-7{list-style-type:none}ul.lst-kix_ay8wo1jz5sry-8{list-style-type:none}.lst-kix_8kqnp1rikc31-8>li:before{content:"-  "}ul.lst-kix_ay8wo1jz5sry-3{list-style-type:none}ul.lst-kix_ay8wo1jz5sry-4{list-style-type:none}ul.lst-kix_ay8wo1jz5sry-5{list-style-type:none}ul.lst-kix_ay8wo1jz5sry-6{list-style-type:none}.lst-kix_8kqnp1rikc31-7>li:before{content:"-  "}.lst-kix_vcgp1be9i72x-0>li:before{content:"\0025cf   "}.lst-kix_6qhps9sefnil-8>li:before{content:"-  "}.lst-kix_6qhps9sefnil-7>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-0>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-0,decimal) ". "}.lst-kix_81wbzl4od4r2-1>li:before{content:"" counter(lst-ctn-kix_81wbzl4od4r2-1,lower-latin) ". "}.lst-kix_8kqnp1rikc31-1>li:before{content:"-  "}.lst-kix_8kqnp1rikc31-3>li:before{content:"-  "}.lst-kix_vcgp1be9i72x-1>li:before{content:"\0025cb   "}.lst-kix_vcgp1be9i72x-3>li:before{content:"\0025cf   "}.lst-kix_8kqnp1rikc31-5>li:before{content:"-  "}.lst-kix_vcgp1be9i72x-5>li:before{content:"\0025a0   "}.lst-kix_vkugqbqlo8ky-6>li:before{content:"-  "}.lst-kix_vkugqbqlo8ky-8>li:before{content:"-  "}.lst-kix_vcgp1be9i72x-7>li:before{content:"\0025cb   "}.lst-kix_9qmrz6tdepc-6>li:before{content:"-  "}.lst-kix_81wbzl4od4r2-1>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-1}.lst-kix_9qmrz6tdepc-4>li:before{content:"-  "}ul.lst-kix_4u9cncx1z8xi-7{list-style-type:none}ul.lst-kix_o48uop49q1mj-8{list-style-type:none}.lst-kix_87842qfl5vuj-8>li:before{content:"-  "}ul.lst-kix_4u9cncx1z8xi-8{list-style-type:none}ul.lst-kix_4u9cncx1z8xi-5{list-style-type:none}ul.lst-kix_4u9cncx1z8xi-6{list-style-type:none}ul.lst-kix_4u9cncx1z8xi-3{list-style-type:none}ul.lst-kix_o48uop49q1mj-4{list-style-type:none}.lst-kix_87842qfl5vuj-6>li:before{content:"-  "}ul.lst-kix_4u9cncx1z8xi-4{list-style-type:none}ul.lst-kix_o48uop49q1mj-5{list-style-type:none}.lst-kix_eom0zhdf11n2-1>li:before{content:"-  "}ul.lst-kix_4u9cncx1z8xi-1{list-style-type:none}ul.lst-kix_o48uop49q1mj-6{list-style-type:none}.lst-kix_9qmrz6tdepc-2>li:before{content:"-  "}ul.lst-kix_4u9cncx1z8xi-2{list-style-type:none}ul.lst-kix_o48uop49q1mj-7{list-style-type:none}ul.lst-kix_o48uop49q1mj-0{list-style-type:none}.lst-kix_87842qfl5vuj-4>li:before{content:"-  "}ul.lst-kix_4u9cncx1z8xi-0{list-style-type:none}ul.lst-kix_o48uop49q1mj-1{list-style-type:none}.lst-kix_eom0zhdf11n2-3>li:before{content:"-  "}ul.lst-kix_o48uop49q1mj-2{list-style-type:none}ul.lst-kix_o48uop49q1mj-3{list-style-type:none}.lst-kix_9qmrz6tdepc-0>li:before{content:"-  "}ul.lst-kix_87842qfl5vuj-2{list-style-type:none}ul.lst-kix_87842qfl5vuj-1{list-style-type:none}ul.lst-kix_87842qfl5vuj-0{list-style-type:none}.lst-kix_81wbzl4od4r2-0>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-0}.lst-kix_djklkkdjtwyh-5>li:before{content:"-  "}ul.lst-kix_87842qfl5vuj-8{list-style-type:none}ul.lst-kix_87842qfl5vuj-7{list-style-type:none}.lst-kix_81wbzl4od4r2-6>li{counter-increment:lst-ctn-kix_81wbzl4od4r2-6}ul.lst-kix_87842qfl5vuj-6{list-style-type:none}ul.lst-kix_87842qfl5vuj-5{list-style-type:none}ul.lst-kix_87842qfl5vuj-4{list-style-type:none}.lst-kix_djklkkdjtwyh-7>li:before{content:"-  "}ul.lst-kix_87842qfl5vuj-3{list-style-type:none}.lst-kix_4u9cncx1z8xi-7>li:before{content:"\0025cb   "}li.li-bullet-0:before{margin-left:-36pt;white-space:nowrap;display:inline-block;min-width:36pt}.lst-kix_87842qfl5vuj-0>li:before{content:"-  "}.lst-kix_eom0zhdf11n2-7>li:before{content:"-  "}.lst-kix_4u9cncx1z8xi-3>li:before{content:"\0025cf   "}.lst-kix_4u9cncx1z8xi-5>li:before{content:"\0025a0   "}.lst-kix_vkugqbqlo8ky-4>li:before{content:"-  "}.lst-kix_87842qfl5vuj-2>li:before{content:"-  "}.lst-kix_eom0zhdf11n2-5>li:before{content:"-  "}.lst-kix_4u9cncx1z8xi-1>li:before{content:"\0025cb   "}.lst-kix_ay8wo1jz5sry-2>li:before{content:"\0025a0   "}.lst-kix_vkugqbqlo8ky-0>li:before{content:"-  "}.lst-kix_vkugqbqlo8ky-2>li:before{content:"-  "}ol{margin:0;padding:0}table td,table th{padding:0}.c30{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:249.8pt;border-top-color:#000000;border-bottom-style:solid}.c7{border-right-style:solid;padding:5pt 5pt 5pt 5pt;border-bottom-color:#000000;border-top-width:1pt;border-right-width:1pt;border-left-color:#000000;vertical-align:top;border-right-color:#000000;border-left-width:1pt;border-top-style:solid;border-left-style:solid;border-bottom-width:1pt;width:86.2pt;border-top-color:#000000;border-bottom-style:solid}.c0{background-color:#b6d7a8;color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.c33{padding-top:0pt;padding-bottom:3pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c6{padding-top:18pt;padding-bottom:6pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c17{color:#434343;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:14pt;font-family:"Arial";font-style:normal}.c10{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.c31{padding-top:16pt;padding-bottom:4pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c5{padding-top:20pt;padding-bottom:6pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c34{color:#000000;font-weight:400;vertical-align:baseline;font-size:16pt;font-family:"Arial";font-style:normal}.c36{color:#000000;font-weight:400;vertical-align:baseline;font-size:26pt;font-family:"Arial";font-style:normal}.c1{padding-top:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left}.c44{color:#000000;font-weight:400;vertical-align:baseline;font-size:20pt;font-family:"Arial";font-style:normal}.c45{color:#000000;font-weight:400;vertical-align:baseline;font-size:10pt;font-family:"Arial";font-style:normal}.c19{font-weight:400;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.c42{color:#000000;font-weight:400;vertical-align:baseline;font-size:11pt;font-family:"Arial"}.c16{color:#000000;text-decoration:none;vertical-align:baseline;font-size:11pt;font-style:normal}.c52{border-spacing:0;border-collapse:collapse;margin-right:auto}.c21{background-color:#ea9999;-webkit-text-decoration-skip:none;text-decoration:line-through;text-decoration-skip-ink:none}.c28{color:#000000;vertical-align:baseline;font-size:11pt;font-style:normal}.c43{-webkit-text-decoration-skip:none;color:#000000;text-decoration:underline;text-decoration-skip-ink:none}.c11{text-decoration-skip-ink:none;-webkit-text-decoration-skip:none;color:#1155cc;text-decoration:underline}.c24{padding-top:0pt;padding-bottom:0pt;line-height:1.0;text-align:left}.c50{text-decoration-skip-ink:none;-webkit-text-decoration-skip:none;text-decoration:line-through}.c4{font-family:"Courier New";font-style:italic;font-weight:400}.c37{margin-left:72pt;list-style-position:inside;text-indent:90pt}.c40{color:#000000;vertical-align:baseline;font-size:16pt}.c12{color:inherit;text-decoration:inherit}.c8{font-weight:400;font-family:"Courier New"}.c3{margin-left:36pt;height:11pt}.c22{padding:0;margin:0}.c51{max-width:468pt;padding:72pt 72pt 72pt 72pt}.c48{margin-left:90pt;padding-left:18pt}.c38{height:0pt}.c29{margin-left:63pt}.c26{color:#6aa84f}.c25{font-weight:700}.c14{font-style:italic}.c23{height:11pt}.c35{text-indent:36pt}.c9{margin-left:22.5pt}.c18{padding-left:0pt}.c49{background-color:#93c47d}.c27{background-color:#ffffff}.c47{font-family:"Arial"}.c20{color:#1155cc}.c13{background-color:#b6d7a8}.c41{margin-left:49.5pt}.c32{text-decoration:none}.c15{margin-left:36pt}.c2{margin-left:18pt}.c39{margin-left:76.5pt}.c46{color:#000000}.title{padding-top:0pt;color:#000000;font-size:26pt;padding-bottom:3pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.subtitle{padding-top:0pt;color:#666666;font-size:15pt;padding-bottom:16pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}li{color:#000000;font-size:11pt;font-family:"Arial"}p{margin:0;color:#000000;font-size:11pt;font-family:"Arial"}h1{padding-top:20pt;color:#000000;font-size:20pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h2{padding-top:18pt;color:#000000;font-size:16pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h3{padding-top:16pt;color:#434343;font-size:14pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h4{padding-top:14pt;color:#666666;font-size:12pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h5{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h6{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;font-style:italic;orphans:2;widows:2;text-align:left}</style></head><body class="c27 c51 doc-content"><p class="c1 c23"><span class="c10"></span></p><table class="c52"><tr class="c38"><td class="c7" colspan="1" rowspan="1"><p class="c24"><span class="c10">Document</span></p></td><td class="c30" colspan="1" rowspan="1"><p class="c24"><span class="c10">P3396R1</span></p></td></tr><tr class="c38"><td class="c7" colspan="1" rowspan="1"><p class="c24"><span class="c10">Date</span></p></td><td class="c30" colspan="1" rowspan="1"><p class="c24"><span class="c10">2024-11-20</span></p></td></tr><tr class="c38"><td class="c7" colspan="1" rowspan="1"><p class="c24"><span class="c10">Reply &nbsp;To</span></p></td><td class="c30" colspan="1" rowspan="1"><p class="c24"><span class="c10">Lewis Baker &lt;lewissbaker@gmail.com&gt;</span></p></td></tr><tr class="c38"><td class="c7" colspan="1" rowspan="1"><p class="c24"><span class="c10">Audience</span></p></td><td class="c30" colspan="1" rowspan="1"><p class="c24"><span class="c10">LWG</span></p></td></tr></table><p class="c33 title" id="h.rymizjjb15qp"><span class="c32 c36">std::execution wording fixes</span></p><h1 class="c5" id="h.l90d3rras2e0"><span class="c44 c32">Abstract</span></h1><p class="c1"><span class="c10">When P2300R10 was merged into the working draft, a subsequent review of the github issue tracker discovered several outstanding issues relating to the wording that was in P2300R10 which were not addressed during the LWG review.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">Now that the P2300 wording has been merged into the working draft, addressing these issues needs to be done either via LWG issues or a paper. It was suggested that an omnibus paper containing the outstanding issues may be more efficiently processed by LWG than filing separate issues for each. This is that paper.</span></p><p class="c1 c23"><span class="c10"></span></p><h1 class="c5" id="h.eqb28x9ndfuf"><span class="c32 c44">Wording Issues</span></h1><p class="c1"><span class="c16 c25 c47">Note to editor: All editing instructions shown below are to be applied to the working draft. </span></p><h2 class="c6" id="h.u26lff35h8ka"><span>#1 The preconditions on </span><span class="c8">run_loop::run()</span><span class="c34 c32">&nbsp;are too strict</span></h2><p class="c1"><span class="c25">Source:</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/280&amp;sa=D&amp;source=editors&amp;ust=1732038204210292&amp;usg=AOvVaw2UE6I5qJzYScN7y-GnZtYr">https://github.com/cplusplus/sender-receiver/issues/280</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>In</span><span>&nbsp;[</span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop%23members&amp;sa=D&amp;source=editors&amp;ust=1732038204210555&amp;usg=AOvVaw1ZDPW19i7rJZrNLXBGwdf_">exec.run.loop.members</a></span><span>] </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop%23members-5&amp;sa=D&amp;source=editors&amp;ust=1732038204210655&amp;usg=AOvVaw0xORKjoal5IRIwGr537ueQ">p5</a></span><span>&nbsp;</span><span class="c10">the precondition for the run() member function states:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span class="c14">Preconditions:</span><span>&nbsp;</span><span class="c8">state</span><span>&nbsp;is </span><span class="c14 c32 c42">starting</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>However, one of the common use-cases is for algorithms like </span><span class="c8">sync_wait()</span><span>&nbsp;[</span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sync.wait&amp;sa=D&amp;source=editors&amp;ust=1732038204211090&amp;usg=AOvVaw2JXrjBGvallsLF33h7b22G">exec.sync.wait</a></span><span>]</span><span>&nbsp;which connects/starts an operation that calls </span><span class="c8">run_loop::finish()</span><span>&nbsp;upon completion, and once </span><span class="c8">start()</span><span>&nbsp;has returned, calls </span><span class="c8">run_loop::run()</span><span>&nbsp;to drive the event-loop until the operation finishes. In the case that the operation completes synchronously (or possibly just quickly on another thread), this can mean that the</span><span>&nbsp;</span><span class="c8">run_loop::finish()</span><span>&nbsp;function can potentially occur before the call to </span><span class="c8">run_loop::run()</span><span class="c10">.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>But as the call to </span><span class="c8">run_loop::finish()</span><span>&nbsp;transitions the state from </span><span class="c14">starting</span><span>&nbsp;to </span><span class="c14">finishing</span><span>&nbsp;this would mean that the subsequent call to </span><span class="c8">run_loop::run()</span><span>&nbsp;would fail to satisfy its preconditions, which require that the state is </span><span class="c14">starting</span><span class="c10">.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>As this is a use-case that needs to work - i.e. a prior call to </span><span class="c8">run_loop::finish()</span><span>&nbsp;should unblock a subsequent call to </span><span class="c8">run_loop::run()</span><span>&nbsp;- we need to modify the precondition for run_loop::run() to allow the state to be either </span><span class="c14">starting</span><span>&nbsp;or </span><span class="c14">finishing</span><span>. However, to allow us to continue to distinguish the case where </span><span class="c8">run()</span><span>&nbsp;has already been called and has returned, we need to add an additional </span><span class="c14">finished</span><span>&nbsp;state. Also, to prevent </span><span class="c8">finish()</span><span>&nbsp; from being called again after </span><span class="c8">run()</span><span>&nbsp;has returned and</span><span>&nbsp;thus making it valid to then call </span><span class="c8">run_loop::run()</span><span>&nbsp;again</span><span>, we need to add a pre-condition to </span><span class="c8">finish()</span><span>&nbsp;that checks that </span><span class="c8">finish()</span><span class="c10">&nbsp;has not been called before.</span></p><h3 class="c31" id="h.92wrd4s8oqmm"><span class="c17">Proposed Resolution</span></h3><p class="c1"><span>Modify</span><span>&nbsp;</span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop.general%232&amp;sa=D&amp;source=editors&amp;ust=1732038204212504&amp;usg=AOvVaw0ukLmTvhUlhpcXuQlM4y0B">[exec.run.loop.general] p2</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span>A </span><span class="c8">run_loop</span><span>&nbsp;instance has an associated</span><span><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop%23def:count&amp;sa=D&amp;source=editors&amp;ust=1732038204212835&amp;usg=AOvVaw2Q22VA73EsF1JaJSAgEevH">&nbsp;</a></span><span class="c14">count</span><span>&nbsp;that corresponds to the number of work items that are in its queue</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop%23general-2.sentence-1&amp;sa=D&amp;source=editors&amp;ust=1732038204213008&amp;usg=AOvVaw1UdVFCeqyo4tCHV80MYpMO">.</a></span></p><p class="c1 c15"><span>Additionally, a </span><span class="c8">run_loop</span><span>&nbsp;instance has an associated state that can be one of</span><span><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop%23def:starting&amp;sa=D&amp;source=editors&amp;ust=1732038204213324&amp;usg=AOvVaw3Sq-PQppwv4qVQN2igC8Tq">&nbsp;</a></span><span class="c14">s</span><span class="c14">tarting</span><span>, </span><span class="c14">running</span><span>,</span><span class="c21">&nbsp;or</span><span>&nbsp;</span><span class="c14">finishing</span><span class="c13">, or </span><span class="c14 c13">finished</span><span>.</span></p><p class="c1 c3"><span class="c10"></span></p><p class="c1"><span class="c10">Modify [exec.run.loop.members] p1 as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span class="c4">run-loop-opstate-base</span><span class="c8">* </span><span class="c4">pop-front</span><span class="c16 c8">();</span></p><p class="c1 c29"><span class="c8"><br></span><span class="c14">Effects</span><span>:</span><span class="c14">&nbsp;</span><span>Blocks ([defns.block]) until one of the following conditions is </span><span class="c8">true</span><span class="c10">:</span></p><ul class="c22 lst-kix_djklkkdjtwyh-0 start"><li class="c1 c37"><span class="c4">count</span><span>&nbsp;is </span><span class="c8">0</span><span>&nbsp;and </span><span class="c4">state</span><span>&nbsp;is </span><span class="c14">finishing</span><span>, in which case </span><span class="c4">pop-front</span><span class="c13">&nbsp;</span><span class="c13">sets </span><span class="c4 c13">state</span><span class="c13">&nbsp;to </span><span class="c13 c14">finished</span><span class="c13">&nbsp;and</span><span class="c26">&nbsp;</span><span>returns </span><span class="c8">nullptr</span><span class="c10">; or</span></li><li class="c1 c48 li-bullet-0"><span class="c4">count</span><span>&nbsp;is greater than </span><span class="c8">0</span><span>, in which case an item is removed from the front of the queue, </span><span class="c4">count</span><span>&nbsp;is decremented by </span><span class="c8">1</span><span class="c10">, and the removed item is returned.<br></span></li></ul><p class="c1"><span class="c10">Modify [exec.run.loop.members] p5/6 as follows:</span></p><p class="c1 c3"><span class="c10"></span></p><p class="c1 c15"><span class="c16 c8">void run();</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c29"><span class="c14">Preconditions</span><span>:</span><span class="c14">&nbsp;</span><span class="c4">state</span><span>&nbsp;is</span><span class="c26">&nbsp;</span><span class="c13">one of</span><span class="c13">&nbsp;</span><span class="c14">starting</span><span class="c13">&nbsp;or </span><span class="c14 c13">finishing</span><span class="c10">.</span></p><p class="c1 c29"><span><br></span><span class="c14">Effects</span><span>: </span><span class="c13">If </span><span class="c4 c13">state</span><span class="c13">&nbsp;is </span><span class="c14 c13">starting</span><span class="c13">, </span><span class="c21">S</span><span class="c13">s</span><span>ets the </span><span class="c4">state</span><span>&nbsp;to </span><span class="c14">running</span><span class="c13">, otherwise leaves </span><span class="c4 c13">state</span><span class="c13">&nbsp;unchanged</span><span class="c10">. Then, equivalent to:</span></p><p class="c1 c39"><span class="c8">while (auto* op = </span><span class="c4">pop-front</span><span class="c16 c8">()) {</span></p><p class="c1 c39"><span class="c8">&nbsp; &nbsp;op-&gt;</span><span class="c4">execute</span><span class="c16 c8">();</span></p><p class="c1 c39"><span class="c16 c8">}</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Modify </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.run.loop.members%238&amp;sa=D&amp;source=editors&amp;ust=1732038204215505&amp;usg=AOvVaw2VKoF3-b8q1asVNLVvicUu">[exec.run.loop.members] p8/9</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span class="c16 c8">void finish();</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c29"><span class="c14 c13">Preconditions: </span><span class="c4 c13">state</span><span class="c13">&nbsp;is one of </span><span class="c14 c13">starting</span><span class="c13">&nbsp;or </span><span class="c14 c13">running</span><span class="c13">.</span><span class="c19 c26 c32"><br></span></p><p class="c1 c29"><span class="c14">Effects</span><span>: Changes </span><span class="c4">state</span><span>&nbsp;to </span><span class="c14">finishing</span><span>.<br><br></span><span class="c14">Synchronization</span><span>: </span><span class="c8">finish</span><span>&nbsp;synchronizes with the </span><span class="c4">pop-front</span><span>&nbsp;operation that returns </span><span class="c8">nullptr</span><span>.</span></p><h2 class="c6" id="h.kygjtmxbs8wl"><span>#2 </span><span class="c8">noexcept</span><span>&nbsp;clause of </span><span class="c14">basic-state</span><span class="c34 c32">&nbsp;constructor is incomplete</span></h2><p class="c1"><span class="c25">Source:</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/279&amp;sa=D&amp;source=editors&amp;ust=1732038204216346&amp;usg=AOvVaw1txA4aSq0VEf3PRnPkJqeX">https://github.com/cplusplus/sender-receiver/issues/279</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>In </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.snd.expos%2328&amp;sa=D&amp;source=editors&amp;ust=1732038204216533&amp;usg=AOvVaw3Vo6sCcyjlPuW5Ydk6n-zI">[exec.snd.expos] p28</a></span><span>, it specifies the expression in the </span><span class="c8">noexcept</span><span>&nbsp;clause of the constructor of </span><span class="c4">basic-state</span><span class="c10">&nbsp;as:</span></p><p class="c1 c9"><span class="c8">is_nothrow_move_constructible_v&lt;Rcvr&gt; &amp;&amp;<br></span><span class="c4">nothrow-callable</span><span class="c8">&lt;decltype(</span><span class="c4">impls-for</span><span class="c8">&lt;tag_of_t&lt;Sndr&gt;&gt;::get-state), Sndr, Rcvr&amp;&gt;</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>However, this doesn&rsquo;t take into account the fact that the return-type of </span><span class="c4">get-state</span><span>&nbsp;might return a reference which is used to initialize a data-member of the decayed return type of </span><span class="c4">get-state</span><span>&nbsp;and thus might call a constructor.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The state member of </span><span class="c4">basic-state</span><span>&nbsp;has type </span><span class="c4">state-type</span><span class="c8">&lt;Sndr, Rcvr&gt;</span><span>&nbsp;where </span><span class="c4">state-type</span><span class="c10">&nbsp;is defined as:</span></p><p class="c1 c9"><span class="c8">template&lt;class Sndr, class Rcvr&gt; // </span><span class="c4">exposition only<br></span><span class="c8">using </span><span class="c4">state-type</span><span class="c8">&nbsp;= decay_t&lt;</span><span class="c4">call-result-t</span><span class="c8">&lt;<br> &nbsp; &nbsp;decltype(</span><span class="c4">impls-for</span><span class="c8">&lt;tag_of_t&lt;Sndr&gt;&gt;::</span><span class="c4">get-state</span><span class="c16 c8">), Sndr, Rcvr&amp;&gt;&gt;;</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">The default get-state implementation is defined as equivalent to:</span></p><p class="c1 c9"><span class="c16 c8">[]&lt;class Sndr, class Rcvr&gt;(Sndr&amp;&amp; sndr, Rcvr&amp; rcvr) noexcept -&gt; decltype(auto) {</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; auto&amp; [_, data, ...child] = sndr;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; return std::forward_like&lt;Sndr&gt;(data);</span></p><p class="c1 c9"><span class="c16 c8">}</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Which for senders like those returned from </span><span class="c8">execution::then(src, f)</span><span>, results in passing a reference to the </span><span class="c4">data</span><span>&nbsp;member initialized from </span><span class="c8">f</span><span>. If a const-lvalue sender is passed to </span><span class="c8">execution::connect()</span><span>, then a const-lvalue-reference to the </span><span class="c4">data</span><span>&nbsp;member will be returned from get-state and will be used to initialize the </span><span class="c4">state</span><span>&nbsp;member of </span><span class="c4">basic-state</span><span class="c10">, resulting in a call to the copy-constructor for the function-object.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>This can make the </span><span class="c4">basic-state</span><span>&nbsp;constructor potentially throwing, even though the </span><span class="c8">noexcept</span><span>&nbsp;specification of the constructor evaluates to </span><span class="c8">noexcept(true)</span><span class="c10">.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">For example:</span></p><p class="c1 c9"><span class="c16 c8">std::string s = &ldquo;a really long string that doesn&rsquo;t trigger small object optimization&rdquo;;<br>const auto sndr = std::execution::then(std::execution::just(),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [s=std::move(s)] noexcept { return std::move(s); });<br>auto op = sndr.connect(some_receiver{});</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">To fix this, we need to add an extra expression to the expression of the noexcept specifier that takes the potential call to a constructor here into account. Note that it also needs to handle the case where the data-member is initialized directly through copy-elision (i.e. where the return-type and decayed return-type are identical and thus copy-elision is guaranteed and an additional call to the constructor will not occur.</span></p><h3 class="c31" id="h.3xk5qbhdgoa9"><span class="c17">Proposed Resolution</span></h3><p class="c1"><span>Modify</span><span>&nbsp;</span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23snd.expos-28&amp;sa=D&amp;source=editors&amp;ust=1732038204219050&amp;usg=AOvVaw17oMJfbLNb6thdZBA1W43_">[exec.snd.expos] p28</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c3"><span class="c10"></span></p><p class="c1 c15"><span>The expression in the </span><span class="c8">noexcept</span><span>&nbsp;clause of the constructor of </span><span class="c4">basic-state</span><span class="c10">&nbsp;is:<br></span></p><p class="c1 c41"><span class="c8">is_nothrow_move_constructible_v&lt;Rcvr&gt; &amp;&amp;<br></span><span class="c4">nothrow-callable</span><span class="c8">&lt;decltype(</span><span class="c4">impls-for</span><span class="c8">&lt;tag_of_t&lt;Sndr&gt;&gt;::</span><span class="c4">get-state</span><span class="c8">), Sndr, Rcvr&amp;&gt;</span><span class="c8 c13">&nbsp;&amp;&amp;<br>(same_as&lt;</span><span class="c4 c13">state-type</span><span class="c8 c13">&lt;Sndr, Rcvr&gt;, </span><span class="c4 c13">get-state-result</span><span class="c8 c13">&gt; ||<br> is_nothrow_constructible_v&lt;</span><span class="c4 c13">state-type</span><span class="c8 c13">&lt;Sndr, Rcvr&gt;, </span><span class="c4 c13">get-state-result</span><span class="c16 c8 c13">&gt;)</span></p><p class="c1 c23 c41"><span class="c16 c8 c13"></span></p><p class="c1 c15"><span class="c13">Where </span><span class="c4 c13">get-state-result</span><span class="c13">&nbsp;is </span><span class="c4 c13">call-result-t</span><span class="c8 c13">&lt;decltype(</span><span class="c4 c13">impls-for</span><span class="c8 c13">&lt;tag_of_t&lt;Sndr&gt;&gt;::</span><span class="c4 c13">get-state</span><span class="c8 c13">), Sndr, Rcvr&amp;&gt;</span><span class="c0">.</span></p><p class="c1 c23 c41"><span class="c16 c8 c13"></span></p><h2 class="c6" id="h.kkovlovv29b0"><span class="c34 c32">#3 Definition of an async operation&rsquo;s environment&rsquo;s ownership seems incorrect</span></h2><p class="c1"><span class="c25">Source:</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/271&amp;sa=D&amp;source=editors&amp;ust=1732038204220146&amp;usg=AOvVaw2jRaQMaBjFKDhqdlSfuyfd">https://github.com/cplusplus/sender-receiver/issues/271</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>In</span><span>&nbsp;</span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.async.ops%234&amp;sa=D&amp;source=editors&amp;ust=1732038204220367&amp;usg=AOvVaw0PD7ScI32DG2eMr2fBfgIW">[exec.async.ops] p4</a></span><span class="c10">&nbsp;it states:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span>An asynchronous operation has an associated environment.</span></p><p class="c1 c15"><span>An </span><span class="c14">environment</span><span>&nbsp;is a queryable object (</span><span>[exec.queryable]</span><span>) representing the execution-time properties of the operation&#39;s caller</span><span>.</span></p><p class="c1 c15"><span>The caller of an asynchronous operation is its parent operation or the function that created it.</span></p><p class="c1 c15"><span>An asynchronous operation&#39;s operation state owns the operation&#39;s environment.</span></p><p class="c1 c3"><span class="c10"></span></p><p class="c1"><span class="c10">The last sentence &ldquo;An asynchronous operation&rsquo;s operation state owns the operation&rsquo;s environment&rdquo; does not seem to reflect the actual nature of the relationship.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">An operation&rsquo;s environment is provided to it by its caller via the receiver, and while the child operation state takes ownership of the receiver, usually storing it as a data-member, the environment returned by the receiver&rsquo;s get_env() member function typically has reference semantics - with the actual state of the environment stored across several parent operation-states. Destroying the operation-state does not necessarily destroy the environment or the resources it provides access to.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">Further, the environment returned by the receiver&rsquo;s get_env() function is often constructed on-demand, so saying that the receiver &ldquo;owns&rdquo; the environment - and by proxy, since the operation-state owns the receiver, that the operation-state owns the environment - seems like a stretch.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">The actual relationship is more one of the caller provides a receiver during connect() which provides access to the environment for the duration of the operation. It is not valid to access the environment after the operation has completed as the caller may release resources referenced by the environment upon completion of a child operation.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">I propose we either just don&rsquo;t say anything about the ownership of the environment, or alternatively say something about the validity of the environment.</span></p><h3 class="c31" id="h.y65acsjoug2"><span class="c17">Proposed Resolution</span></h3><p class="c1"><span>Modify </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.async.ops%234&amp;sa=D&amp;source=editors&amp;ust=1732038204221549&amp;usg=AOvVaw0EbuKrXwJ1HXthPlohRhmw">[exec.async.ops] p4</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span>An asynchronous operation has an associated environment.</span></p><p class="c1 c15"><span>An </span><span class="c14">environment</span><span>&nbsp;is a queryable object ([exec.queryable]) representing the execution-time properties of the operation&#39;s caller.</span></p><p class="c1 c15"><span>The caller of an asynchronous operation is its parent operation or the function that created it.</span></p><p class="c1 c15"><span class="c19 c21 c46">An asynchronous operation&#39;s operation state owns the operation&#39;s environment.</span></p><p class="c1 c23"><span class="c10"></span></p><h2 class="c6" id="h.ejp877p45hl5"><span class="c34 c32">#4 scheduler semantic requirements imply swapability but concept does not require it</span></h2><p class="c1"><span class="c25">Source:</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/270&amp;sa=D&amp;source=editors&amp;ust=1732038204222140&amp;usg=AOvVaw3rAhbzNU7Q7HcD0sw3_6gk">https://github.com/cplusplus/sender-receiver/issues/270</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The scheduler concept is defined in </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sched&amp;sa=D&amp;source=editors&amp;ust=1732038204222304&amp;usg=AOvVaw1tbg-4Lhi-Aya7HWpTZRV_">[exec.sched]</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c9"><span class="c16 c8">template&lt;class Sch&gt;</span></p><p class="c1 c9"><span class="c16 c8">concept scheduler =</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;derived_from&lt;typename remove_cvref_t&lt;Sch&gt;::scheduler_concept, scheduler_t&gt; &amp;&amp;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queryable&lt;Sch&gt; &amp;&amp;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requires(Sch&amp;&amp; sch) {</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ schedule(std::forward&lt;Sch&gt;(sch)) } -&gt; sender;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ auto(get_completion_scheduler&lt;set_value_t&gt;(</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get_env(schedule(std::forward&lt;Sch&gt;(sch))))) }</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&gt; same_as&lt;remove_cvref_t&lt;Sch&gt;&gt;;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &amp;&amp;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;equality_comparable&lt;remove_cvref_t&lt;Sch&gt;&gt; &amp;&amp;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copy_constructible&lt;remove_cvref_t&lt;Sch&gt;&gt;;</span></p><p class="c1 c23 c9"><span class="c16 c8"></span></p><p class="c1"><span>However, </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sched%233&amp;sa=D&amp;source=editors&amp;ust=1732038204223162&amp;usg=AOvVaw1e4YgAyN9zmwxi4k8eT-mC">[exec.sched] p3</a></span><span class="c10">&nbsp;also states:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span>None of a scheduler&#39;s copy constructor, destructor, equality comparison, or </span><span class="c8">swap</span><span>&nbsp;member functions shall exit via an exception</span><span>.</span></p><p class="c1 c15"><span>None of these member functions, nor a scheduler type&#39;s </span><span class="c8">schedule</span><span>&nbsp;function, shall introduce data races as a result of potentially concurrent (</span><span>[intro.races]</span><span>) invocations of those functions from different threads</span><span>.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The wording for p3 mentions a swap() member function, but the concept does not require a </span><span class="c8">swap</span><span>&nbsp;member-function, or the </span><span class="c8">swappable</span><span class="c10">&nbsp;concept.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Should the </span><span class="c8">scheduler</span><span>&nbsp;concept also require </span><span class="c8">swappable&lt;Sch&gt;</span><span class="c10">?</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Also, the scheduler concept does not require move-assignability of schedulers, so the default </span><span class="c8">std::swap()</span><span class="c10">&nbsp;implementation is not necessarily going to work for types that minimally implement the concept.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Should the concept also require the type to be </span><span class="c8">movable</span><span>? Or possibly even </span><span class="c8">copyable</span><span>?<br>Note that </span><span class="c8">copyable</span><span>&nbsp;requires </span><span class="c8">movable</span><span>&nbsp;which requires </span><span class="c8">swappable</span><span class="c10">.</span></p><h3 class="c31" id="h.vdf6be5yafd8"><span>Proposed Resolution</span></h3><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Modify the scheduler concept in </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sched&amp;sa=D&amp;source=editors&amp;ust=1732038204224473&amp;usg=AOvVaw2mJJ9U9AzSYv7VIHkQAUKr">[exec.sched]</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c9"><span class="c16 c8">template&lt;class Sch&gt;</span></p><p class="c1 c9"><span class="c16 c8">concept scheduler =</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;derived_from&lt;typename remove_cvref_t&lt;Sch&gt;::scheduler_concept, scheduler_t&gt; &amp;&amp;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;queryable&lt;Sch&gt; &amp;&amp;</span></p><p class="c1 c9"><span class="c8 c16">&nbsp; &nbsp;requires(Sch&amp;&amp; sch) {</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp;{ schedule(std::forward&lt;Sch&gt;(sch)) } -&gt; sender;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp;{ auto(get_completion_scheduler&lt;set_value_t&gt;(</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_env(schedule(std::forward&lt;Sch&gt;(sch))))) }</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp; &nbsp; &nbsp; -&gt; same_as&lt;remove_cvref_t&lt;Sch&gt;&gt;;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;} &amp;&amp;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; &nbsp;equality_comparable&lt;remove_cvref_t&lt;Sch&gt;&gt; &amp;&amp;</span></p><p class="c1 c9"><span class="c8">&nbsp; &nbsp;</span><span class="c21 c8">copy_constructible&lt;remove_cvref_t&lt;Sch&gt;&gt;;<br></span><span class="c8">&nbsp; &nbsp;</span><span class="c16 c8 c13">copyable&lt;remove_cvref_t&lt;Sch&gt;&gt;;</span></p><p class="c1 c23 c9"><span class="c16 c8 c13"></span></p><p class="c1"><span>We may also want to adjust p3 to refer to &ldquo;</span><span class="c8">swap</span><span>&nbsp;operation&rdquo;, or &ldquo;</span><span class="c8">swap</span><span>&nbsp;function&rdquo;, rather than &ldquo;</span><span class="c8">swap</span><span>&nbsp;member-function&rdquo; as the latter is not guaranteed to be used by a call to </span><span class="c8">std::ranges::swap()</span><span class="c10">.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Modify </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sched%233&amp;sa=D&amp;source=editors&amp;ust=1732038204225512&amp;usg=AOvVaw3G9h-vmkm6rV_WW9Puk2ny">[exec.sched] p3</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c15"><span class="c21">None of a scheduler&#39;s copy constructor, destructor,, equality comparison, or </span><span class="c21 c8">swap</span><span class="c21">&nbsp;member functions</span><span>&nbsp;</span><span class="c13">No operation required by </span><span class="c8 c13">copyable&lt;remove_cvref_t&lt;Sch&gt;&gt;</span><span class="c13">&nbsp;and </span><span class="c8 c13">equality_comparable&lt;remove_cvref_t&lt;Sch&gt;&gt;</span><span>&nbsp;shall exit via an exception.</span></p><p class="c1 c15"><span>None of these </span><span class="c21">member functions</span><span class="c13">operations</span><span>, nor a scheduler type&#39;s </span><span class="c8">schedule</span><span>&nbsp;function, shall introduce data races as a result of potentially concurrent ([intro.races]) invocations of those </span><span class="c21">functions</span><span class="c13">operations</span><span class="c10">&nbsp;from different threads.</span></p><p class="c1 c3"><span class="c10"></span></p><p class="c1"><span class="c10">NOTE to editor: The &nbsp;proposed resolution here also addresses #8.</span></p><h2 class="c6" id="h.d4f04w3t3pqe"><span>#5 </span><span class="c4">operation-state-task</span><span class="c32 c34">&nbsp;exposition-only type does not need a move constructor</span></h2><p class="c1 c27"><span class="c25">Source:</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/236&amp;sa=D&amp;source=editors&amp;ust=1732038204226383&amp;usg=AOvVaw0N95z9_k-9aZsyayzWqikP">https://github.com/cplusplus/sender-receiver/issues/236</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Section </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.connect%234&amp;sa=D&amp;source=editors&amp;ust=1732038204226672&amp;usg=AOvVaw21zxw-hc7ehJ_EuTwi4bxi">[exec.connect] p4</a></span><span>&nbsp;defines the </span><span class="c4">operation-state-task</span><span>&nbsp;exposition-only type as having a move-constructor which can transfer ownership of the </span><span class="c8">coroutine_handle</span><span class="c10">&nbsp;to another instance.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>However, as the </span><span class="c4">operation-state-task</span><span>&nbsp;class is modeling the </span><span class="c8">operation_state</span><span class="c10">&nbsp;concept, which does not require the object to be move-constructible, the move-constructor defined in this class is unnecessary.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">I suggest we instead mark the move-constructor as deleted. This can also simplify the destructor, which no longer needs to handle a moved-from state.</span></p><h3 class="c31" id="h.8gwujh3lsupp"><span>Proposed Resolution</span></h3><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Modify </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23connect-4&amp;sa=D&amp;source=editors&amp;ust=1732038204227626&amp;usg=AOvVaw3clDihaoAxM0GSfl_SW8JD">[exec.connect] p4</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c9"><span>Let </span><span class="c4">operation-state-task</span><span class="c10">&nbsp;be the following exposition-only class:</span></p><p class="c1 c23 c9"><span class="c10"></span></p><p class="c1 c15"><span class="c16 c8">namespace std::execution {</span></p><p class="c1 c15"><span class="c8">&nbsp; struct </span><span class="c4">operation-state-task</span><span class="c16 c8">&nbsp;{</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; using operation_state_concept = operation_state_t;</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; using promise_type = </span><span class="c4">connect-awaitable-promise</span><span class="c16 c8">;</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; explicit </span><span class="c4">operation-state-task</span><span class="c16 c8">(coroutine_handle&lt;&gt; h) noexcept : coro(h) {}</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; </span><span class="c4">operation-state-task</span><span class="c8">(</span><span class="c4">operation-state-task</span><span class="c8">&amp;&amp; o) </span><span class="c21 c8">noexcept</span><span class="c16 c8 c13">= delete;</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; </span><span class="c21 c8 c28">: coro(exchange(o.coro, {})) {}</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; </span><span class="c8">~operation-state-task() { </span><span class="c21 c8">if (coro) </span><span class="c16 c8">coro.destroy(); }</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; void start() &amp; noexcept {</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; &nbsp; coro.resume();</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; }</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c16 c8">&nbsp; private:</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; coroutine_handle&lt;&gt; coro; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// exposition only</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; };</span></p><p class="c1 c15"><span class="c16 c8">}</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c23"><span class="c10"></span></p><h2 class="c6" id="h.cdi4mtjee0vj"><span class="c34 c32">#6 [exec.general] Wording for AS-EXCEPT-PTR should use &#39;Precondition:&#39; instead of &#39;Mandates:&#39; for runtime properties</span></h2><p class="c1 c27"><span class="c25">Source:</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/234&amp;sa=D&amp;source=editors&amp;ust=1732038204229456&amp;usg=AOvVaw3Z280tuPDDUm1YwKWGt9vB">https://github.com/cplusplus/sender-receiver/issues/234</a></span></p><p class="c1 c23 c27"><span class="c10"></span></p><p class="c1"><span>At </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23general-8&amp;sa=D&amp;source=editors&amp;ust=1732038204229754&amp;usg=AOvVaw0fmSlJ2PEckrKi-NiCPNji">[exec.general] p8</a></span><span>&nbsp;</span><span>The definition of the exposition-only </span><span class="c8">AS-EXCEPT-PTR</span><span>&nbsp;has a case for when the error is already an </span><span class="c8">exception_ptr</span><span class="c10">&nbsp;that has the following requirement:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c35"><span class="c14">Mandates</span><span class="c8">: err != exception_ptr() </span><span>is </span><span class="c8">true</span><span class="c10">.</span></p><p class="c1 c23 c35"><span class="c16 c8"></span></p><p class="c1"><span class="c10">&quot;Mandates&quot; clauses are usually for things which are ill-formed and can be detected at compile-time.</span></p><p class="c1"><span>However this is a runtime property and so should probably be a </span><span class="c14">Precondition</span><span>: instead.</span></p><h3 class="c31" id="h.2jds0pelkcgn"><span class="c17">Proposed Resolution</span></h3><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Change </span><span>&ldquo;</span><span class="c14">Mandates&rdquo;</span><span>&nbsp;in</span><span>&nbsp;</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23general-8.1.sentence-2&amp;sa=D&amp;source=editors&amp;ust=1732038204231005&amp;usg=AOvVaw1KRiqYlwrxtuJotatdl0jv">[exec.general] p8.1.sentence-2</a></span><span>, as indicated:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c35"><span class="c21 c14">Mandates</span><span class="c14 c13">Precondition</span><span>:</span><span class="c8">&nbsp;</span><span class="c8 c13">!</span><span class="c8">err </span><span class="c21 c8">!= exception_ptr() </span><span>is </span><span class="c21 c8">true</span><span class="c8 c13">false</span><span>.</span><span class="c10">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p class="c1 c23"><span class="c10"></span></p><h2 class="c6" id="h.ykn9ai19mq8a"><span>#7 [exec.schedule.from] Potential access to destroyed state in </span><span class="c4">impls-for</span><span class="c8">::</span><span class="c4 c32 c40">complete</span></h2><p class="c1"><span>Source: </span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/233&amp;sa=D&amp;source=editors&amp;ust=1732038204231657&amp;usg=AOvVaw1U5FC2wvygp-8g4QSJ6dl5">https://github.com/cplusplus/sender-receiver/issues/233</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The current specification of </span><span class="c8">schedule_from</span><span>&nbsp;algorithm has the following definition for </span><span class="c4">impls-for</span><span class="c8">&lt;schedule_from_t&gt;::</span><span class="c4">complete</span><span class="c10">:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c9"><span class="c16 c8">[]&lt;class Tag, class... Args&gt;(auto, auto&amp; state, auto&amp; rcvr, Tag, Args&amp;&amp;... args) noexcept<br> &nbsp; &nbsp;-&gt; void {</span></p><p class="c1 c9"><span class="c8">&nbsp; using result_t = </span><span class="c4">decayed-tuple</span><span class="c16 c8">&lt;Tag, Args...&gt;;</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; constexpr bool nothrow = is_nothrow_constructible_v&lt;result_t, Tag, Args...&gt;;</span></p><p class="c1 c23 c9"><span class="c16 c8"></span></p><p class="c1 c9"><span class="c8">&nbsp; </span><span class="c4">TRY-EVAL</span><span class="c16 c8">(std::move(rcvr), [&amp;]() noexcept(nothrow) {</span></p><p class="c1 c9"><span class="c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state.</span><span class="c4">async-result</span><span class="c16 c8">.template emplace&lt;result_t&gt;(Tag(), std::forward&lt;Args&gt;(args)...);</span></p><p class="c1 c9"><span class="c16 c8">&nbsp; }());</span></p><p class="c1 c23 c9"><span class="c16 c8"></span></p><p class="c1 c9"><span class="c8">&nbsp; if (state.</span><span class="c4">async-result</span><span class="c16 c8">.valueless_by_exception())</span></p><p class="c1 c9"><span class="c16 c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;</span></p><p class="c1 c9"><span class="c8">&nbsp; if (state.</span><span class="c4">async-result</span><span class="c16 c8">.index() == 0)</span></p><p class="c1 c9"><span class="c16 c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;</span></p><p class="c1 c23 c9"><span class="c16 c8"></span></p><p class="c1 c9"><span class="c8">&nbsp; start(state.</span><span class="c4">op-state</span><span class="c16 c8">);</span></p><p class="c1 c9"><span class="c16 c8">};</span></p><p class="c1 c23 c9"><span class="c16 c8"></span></p><p class="c1"><span>The call to </span><span class="c4">TRY-EVAL</span><span>&nbsp;here will invoke </span><span class="c8">set_error()</span><span>&nbsp;on the receiver if the construction of </span><span class="c8">result_t</span><span class="c10">&nbsp;throws an exception.</span></p><p class="c1"><span>As the call to </span><span class="c8">set_error()</span><span>&nbsp;can potentially end up destroying the operation-state, the subsequent access of </span><span class="c8">state.</span><span class="c4">async-result</span><span class="c8">.valueless_by_exception()</span><span>&nbsp;is potentially accessing a dangling reference to </span><span class="c8">state</span><span class="c10">.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Instead, we need to have this function </span><span class="c8">return;</span><span>&nbsp;after </span><span class="c8">set_error()</span><span>&nbsp;is called. This may mean we need to directly define the expansion of </span><span class="c4">TRY-EVAL</span><span class="c10">&nbsp;instead of using the exposition-only macro.</span></p><h3 class="c31" id="h.a2zvhma42esi"><span class="c17">Proposed Resolution</span></h3><p class="c1"><span>Modify</span><span>&nbsp;</span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.schedule.from%2311&amp;sa=D&amp;source=editors&amp;ust=1732038204233747&amp;usg=AOvVaw2uT8-7B2N4AucOmgPWBK-U">[exec.schedule.from] p11</a></span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c2"><span>The member </span><span class="c4">impls-for</span><span class="c8">&lt;schedule_from_t&gt;::</span><span class="c4">complete</span><span class="c10">&nbsp;is initialized with a callable object equivalent to the following lambda:</span></p><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1 c15"><span class="c16 c8">[]&lt;class Tag, class... Args&gt;(auto, auto&amp; state, auto&amp; rcvr, Tag, Args&amp;&amp;... args) noexcept</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; -&gt; void {</span></p><p class="c1 c15"><span class="c8">&nbsp; using result_t = </span><span class="c4">decayed-tuple</span><span class="c16 c8">&lt;Tag, Args...&gt;;</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; constexpr bool nothrow = is_nothrow_constructible_v&lt;result_t, Tag, Args...&gt;;</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c8">&nbsp; </span><span class="c21 c8">TRY-EVAL(rcvr, [&amp;]() noexcept(nothrow) {<br></span><span class="c8">&nbsp; </span><span class="c16 c8 c13">try {</span></p><p class="c1 c15"><span class="c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state.</span><span class="c4">async-result</span><span class="c8">.template emplace&lt;result_t&gt;(Tag(), std::forward&lt;Args&gt;(args)...);<br> &nbsp;</span><span class="c8 c13">} catch (...) {<br></span><span class="c8">&nbsp; &nbsp; </span><span class="c8 c13">if constexpr (!nothrow) {<br></span><span class="c8">&nbsp; &nbsp; &nbsp; </span><span class="c8 c13">set_error(std::move(rcvr), current_exception());<br></span><span class="c8">&nbsp; &nbsp; &nbsp; </span><span class="c8 c13">return;<br></span><span class="c8">&nbsp; &nbsp; </span><span class="c8 c13">}<br></span><span class="c8">&nbsp; </span><span class="c16 c8 c13">}</span></p><p class="c1 c15"><span class="c8">&nbsp; </span><span class="c21 c28 c8">}());</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c8">&nbsp; </span><span class="c21 c8">if (state.</span><span class="c21 c4">async-result</span><span class="c21 c28 c8">.valueless_by_exception())</span></p><p class="c1 c15"><span class="c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="c21 c28 c8">return;</span></p><p class="c1 c15"><span class="c8">&nbsp; </span><span class="c21 c8">if (state.</span><span class="c21 c4">async-result</span><span class="c21 c28 c8">.index() == 0)</span></p><p class="c1 c15"><span class="c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="c21 c28 c8">return;</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c8">&nbsp; start(state.</span><span class="c4">op-state</span><span class="c16 c8">);</span></p><p class="c1 c15"><span class="c16 c8">};</span></p><p class="c1 c3"><span class="c16 c8"></span></p><h2 class="c6" id="h.vilg5lho2io"><span class="c34 c32">#8 scheduler concept should require that move-constructor does not exit with an exception</span></h2><p class="c1"><span>Source: </span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/116&amp;sa=D&amp;source=editors&amp;ust=1732038204236970&amp;usg=AOvVaw0bI_OMxOmS5dS6TKe4VdrY">https://github.com/cplusplus/sender-receiver/issues/116</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sched%233&amp;sa=D&amp;source=editors&amp;ust=1732038204237255&amp;usg=AOvVaw0xviGQdkiV69Y5yxR0COGB">[exec.sched] p3</a></span><span class="c10">&nbsp;states:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c2"><span>None of a scheduler&#39;s copy constructor, destructor, equality comparison, or swap member functions shall exit via an exception</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.sched%233.sentence-1&amp;sa=D&amp;source=editors&amp;ust=1732038204237579&amp;usg=AOvVaw3WOmur4eqzP3VGDQHO5gJO">.</a></span></p><p class="c1 c2"><span>None of these member functions, nor a scheduler type&#39;s </span><span class="c8">schedule</span><span>&nbsp;function, shall introduce data races as a result of potentially concurrent (</span><span>[intro.races]</span><span class="c10">) invocations of those functions from different threads.</span></p><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1"><span class="c10">The scheduler concept requires the type to be std::copy_constructible, which &nbsp;subsumes std::move_constructible. The above paragraph requires the scheduler&rsquo;s copy-constructor to not exit via an exception, but does not require the move-constructor to not exit via an exception.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">Further, the std::copy_constructible concept subsumes std::destructible, which already requires that the destructor is declared noexcept. Thus the above paragraph is redundantly requiring the destructor to not exit with an exception, which is already enforced by requiring the destructor to be noexcept.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">Note that this has potential interactions with issue #4 listed above in this document, which suggests changing the std::copy_constructible requirement to std::copyable. If this is the case, then we may also want to explicitly list the copy-assignment and move-assignment operations as also not throwing exceptions.</span></p><h3 class="c31" id="h.bj21hunwzy90"><span class="c17">Proposed Resolution</span></h3><p class="c1"><span>Addressed by the resolution of #4.</span></p><p class="c1 c23 c2"><span class="c10"></span></p><h2 class="c6" id="h.ibjh2uempcx"><span>#9 [exec.bulk] wording should indicate that </span><span class="c8">f</span><span>&nbsp;is called with </span><span class="c8">i</span><span class="c34 c32">&nbsp;= [0, &hellip;, shape-1]</span></h2><p class="c1"><span>Source: </span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/102&amp;sa=D&amp;source=editors&amp;ust=1732038204238799&amp;usg=AOvVaw00ssqx8A-zKoQdNkaU1uVw">https://github.com/cplusplus/sender-receiver/issues/102</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The current wording for </span><span class="c20"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec.bulk%236.1&amp;sa=D&amp;source=editors&amp;ust=1732038204239064&amp;usg=AOvVaw0PTt4fYWKU3nONIje5KGJM">[exec.bulk] p6.1</a></span><span class="c10">&nbsp;is:</span></p><p class="c1 c23"><span class="c10"></span></p><ul class="c22 lst-kix_5lely89nlm5f-0 start"><li class="c1 c15 c18 li-bullet-1"><span>on a value completion operation, invokes </span><span class="c8">f(i, args...)</span><span>&nbsp;for every </span><span class="c8">i</span><span>&nbsp;of type </span><span class="c8">Shape</span><span>&nbsp;from </span><span class="c8">0</span><span>&nbsp;to </span><span class="c8">shape</span><span>, where </span><span class="c8">args</span><span class="c10">&nbsp;is a pack of lvalue subexpressions referring to the value completion result datums of the input sender, and</span></li></ul><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span class="c10">It is not clear from this wording that the intent is to have f invoked with i = 0, i = 1, &hellip; up to i = shape-1, but not invoked with i = shape.</span></p><h3 class="c31" id="h.zc9loc8ticwp"><span class="c17">Proposed Resolution</span></h3><p class="c1"><span class="c10">Modify [exec.bulk] p6.1 as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><ul class="c22 lst-kix_5lely89nlm5f-0"><li class="c1 c18 c15 li-bullet-2"><span>on a value completion operation, invokes </span><span class="c8">f(i, args...)</span><span>&nbsp;for every </span><span class="c8">i</span><span>&nbsp;of type </span><span class="c8">Shape</span><span>&nbsp;</span><span class="c21">from </span><span class="c8 c21">0</span><span class="c21">&nbsp;to </span><span class="c21 c8">shape</span><span class="c13">in [</span><span class="c8 c13">0</span><span class="c13">, </span><span class="c8 c13">shape</span><span class="c13">)</span><span>, where </span><span class="c8">args</span><span class="c10">&nbsp;is a pack of lvalue subexpressions referring to the value completion result datums of the input sender, and</span></li></ul><p class="c1 c23"><span class="c13 c32 c45"></span></p><h2 class="c6" id="h.s470071pwj0o"><span class="c34 c32">#10 The use of JOIN-ENV leads to inefficient implementations of composed environments</span></h2><p class="c1"><span>Source: </span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://github.com/cplusplus/sender-receiver/issues/229&amp;sa=D&amp;source=editors&amp;ust=1732038204240474&amp;usg=AOvVaw1y3kd160yHDRnsAeEWfzle">https://github.com/cplusplus/sender-receiver/issues/229</a></span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The current wording for the exposition-only </span><span class="c4">write-env</span><span class="c8">()</span><span>&nbsp;function (</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23snd.expos-43&amp;sa=D&amp;source=editors&amp;ust=1732038204240727&amp;usg=AOvVaw0u5gMSkYfGoBIU4hXu9Lvp">[exec.snd.expos]</a></span><span>), as well as </span><span class="c8">let_value</span><span>, </span><span class="c8">let_error</span><span>, </span><span class="c8">let_stopped</span><span>&nbsp;(</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23let-6&amp;sa=D&amp;source=editors&amp;ust=1732038204240932&amp;usg=AOvVaw2FQ7AWNxUEBqji5UVCBl6J">[exec.let]</a></span><span>), </span><span class="c8">when_all</span><span>&nbsp;and </span><span class="c8">when_all_with_variant</span><span>&nbsp;(</span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23when.all-6&amp;sa=D&amp;source=editors&amp;ust=1732038204241124&amp;usg=AOvVaw3T-d3xwbx4qxetf7do_kBI">[exec.when.all]</a></span><span>) defines the </span><span class="c8">get_env()</span><span>&nbsp;operation on receivers passed to child operations in terms of the exposition-only </span><span class="c8">JOIN-ENV</span><span class="c10">&nbsp;helper.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The </span><span class="c4">JOIN-ENV</span><span>&nbsp;helper </span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23snd.expos-4&amp;sa=D&amp;source=editors&amp;ust=1732038204241467&amp;usg=AOvVaw3VrYDEXsGixImqLuOxpcci">[exec.snd.expos] p4</a></span><span class="c10">&nbsp;is defined as follows:</span></p><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1 c2"><span>For two queryable objects </span><span class="c8">env1</span><span>&nbsp;and </span><span class="c8">env2</span><span>, a query object </span><span class="c8">q</span><span>, and a pack of subexpressions </span><span class="c8">as</span><span>, </span><span class="c4">JOIN-ENV</span><span class="c8">(env1, env2)</span><span>&nbsp;is an expression </span><span class="c8">env3</span><span>&nbsp;whose type satisfies </span><span class="c8">queryable</span><span>&nbsp;such that </span><span class="c8">env3.query(q, as&hellip;)</span><span class="c10">&nbsp;is expression-equivalent to:</span></p><p class="c1 c23 c2"><span class="c10"></span></p><ul class="c22 lst-kix_o48uop49q1mj-0 start"><li class="c1 c18 c15 li-bullet-2"><span class="c8">env.query(q, as&hellip;)</span><span class="c10">&nbsp;if that expression is well-formed,</span></li><li class="c1 c18 c15 li-bullet-2"><span>otherwise, </span><span class="c8">env2.query(q, as&hellip;)</span><span class="c10">&nbsp;if that expression is well-formed,</span></li><li class="c1 c18 c15 li-bullet-1"><span>otherwise, </span><span class="c8">env3.query(q, as&hellip;)</span><span class="c10">&nbsp;is ill-formed.</span></li></ul><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1"><span>And then we have usage in, e.g. </span><span class="c11"><a class="c12" href="https://www.google.com/url?q=https://eel.is/c%2B%2Bdraft/exec%23when.all-6&amp;sa=D&amp;source=editors&amp;ust=1732038204242361&amp;usg=AOvVaw0DXAFbiqjQiSuqAmv8ph9O">[exec.when.all] p6</a></span><span class="c10">&nbsp;that states:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c2"><span>The member </span><span class="c4">impls-for</span><span class="c8">&lt;when_all_t&gt;::</span><span class="c4">get-env</span><span class="c10">&nbsp;is initialized with a callable object equivalent to the following lambda expression:</span></p><p class="c1 c15"><span class="c8">[]&lt;class State, class Rcvr&gt;(auto&amp;&amp;, State&amp; state, const Receiver&amp; rcvr) noexcept {<br> &nbsp;return </span><span class="c4">JOIN-ENV</span><span class="c8">(<br> &nbsp; &nbsp;</span><span class="c4">MAKE-ENV</span><span class="c8">(get_stop_token, state.</span><span class="c4">stop_src</span><span class="c16 c8">.get_token()), get_env(rcvr));<br>}</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>The problem with the current formulation is that this forces implementations to evaluate the environments eagerly. As </span><span class="c8">env1</span><span>&nbsp;and </span><span class="c8">env2</span><span>&nbsp;are specified to be &lsquo;objects&rsquo; this means that it must evaluate the argument expressions once to produce the object, and since this might be a temporary, the object must be stored in the returned object. However, if we apply this same approach recursively over a tree of such senders, then we end up with every call to </span><span class="c8">get_env()</span><span class="c10">&nbsp;at the leaf level potentially copying the entire set of environment values of every ancestor environment.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>For example, if we apply </span><span class="c8">when_all()</span><span>&nbsp;to a nesting depth of 5, then at the leaf operation level, the call to the leaf receiver&rsquo;s </span><span class="c8">get_env()</span><span class="c10">&nbsp;will return an environment that contains a stop-token plus the parent environment. The parent-environment contains a stop-token plus its parent environment, which contains a stop-token and its parent environment, etc. until the returned environment contains 5 separate stop-token objects, only one of which is returned if someone queries for the stop-token, and none of which are used if the caller is querying for something else.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>Ideally, the places where we use JOIN-ENV would permit implementations to return </span><span>a </span><span class="c8">queryable</span><span>&nbsp;object that only calls </span><span class="c8">get_env()</span><span class="c10">&nbsp;on the parent receiver&rsquo;s environment if the query is not satisfied immediately by the parent operation state.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>We may be able to better express this by instead describing the behavior of queries on the queryable returned from get_env() rather than describing </span><span class="c8">get_env()</span><span class="c10">&nbsp;in code.</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1"><span>For example, by saying it returns an object, </span><span class="c8">env</span><span>, of unspecified type modeling </span><span class="c8">queryable</span><span class="c10">&nbsp;such that:</span></p><ul class="c22 lst-kix_a17aea4cfg0-0 start"><li class="c1 c18 c15 li-bullet-2"><span class="c8">env.query(get_stop_token)</span><span>&nbsp;is expression-equivalent to &lsquo;</span><span class="c8">state.stop_src.get_token()</span><span class="c10">&rsquo;</span></li><li class="c1 c18 c15 li-bullet-1"><span>given a query object, </span><span class="c8">q</span><span>, of decayed type other than </span><span class="c8">get_stop_token_t</span><span>, </span><span class="c8">env.query(q)</span><span>&nbsp;is expression-equivalent to </span><span class="c8">get_env(rcvr).query(q)</span></li></ul><h3 class="c31" id="h.73cceoj3khf0"><span>Proposed Resolution</span></h3><p class="c1"><span class="c10">Modify [exec.when.all] p6 as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c2"><span>The member </span><span class="c4">impls-for</span><span class="c8">&lt;when_all_t&gt;::</span><span class="c4">get-env</span><span class="c10">&nbsp;is initialized with a callable object equivalent to the following lambda expression:</span></p><p class="c1 c15"><span class="c8">[]&lt;class State, class Rcvr&gt;(auto&amp;&amp;, State&amp; state, const Receiver&amp; rcvr) noexcept {<br> &nbsp;return </span><span class="c8 c13">/* see below */</span><span class="c21 c4">JOIN-ENV</span><span class="c21 c8">(</span><span class="c8 c50"><br> &nbsp; &nbsp;</span><span class="c21 c4">MAKE-ENV</span><span class="c21 c8">(get_stop_token, state.</span><span class="c21 c4">stop_src</span><span class="c21 c8">.get_token()), get_env(rcvr))</span><span class="c16 c8">;<br>}</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c2"><span class="c13">Returns an object </span><span class="c8 c13">e</span><span class="c0">&nbsp;such that:</span></p><ul class="c22 lst-kix_9qmrz6tdepc-0 start"><li class="c1 c18 c15 li-bullet-1"><span class="c8 c13">decltype(e)</span><span class="c13">&nbsp;models </span><span class="c8 c13">queryable</span><span class="c0">&nbsp;; and</span></li></ul><ul class="c22 lst-kix_eom0zhdf11n2-0 start"><li class="c1 c18 c15 li-bullet-2"><span class="c8 c13">e.query(get_stop_token)</span><span class="c13">&nbsp;is expression-equivalent to </span><span class="c8 c13">state.</span><span class="c4 c13">stop_src</span><span class="c8 c13">.get_token()</span><span class="c0">; and</span></li><li class="c1 c18 c15 li-bullet-2"><span class="c13">given a query object, </span><span class="c8 c13">q</span><span class="c13">, with type other than </span><span class="c14 c13">cv</span><span class="c13">&nbsp;</span><span class="c8 c13">stop_token_t</span><span class="c13">, </span><span class="c8 c13">e.query(q)</span><span class="c13">&nbsp;is expression-equivalent to </span><span class="c16 c8 c13">get_env(rcvr).query(q)</span></li></ul><p class="c1 c23"><span class="c16 c8 c49"></span></p><p class="c1"><span class="c10">Modify [exec.let] p6 as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c2"><span>Let </span><span class="c4">receiver2</span><span class="c10">&nbsp;denote the following exposition-only class template:</span></p><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1 c15"><span class="c16 c8">namespace std::execution {</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; template&lt;class Rcvr, class Env&gt;</span></p><p class="c1 c15"><span class="c8">&nbsp; struct </span><span class="c4">receiver2</span><span class="c16 c8">&nbsp;{</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; using receiver_concept = receiver_t;</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; template&lt;class... Args&gt;</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; void set_value(Args&amp;&amp;... args) &amp;&amp; noexcept {</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; &nbsp; execution::set_value(std::move(</span><span class="c4">rcvr</span><span class="c16 c8">), std::forward&lt;Args&gt;(args)...);</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; }</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; template&lt;class Error&gt;</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; void set_error(Error&amp;&amp; err) &amp;&amp; noexcept {</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; &nbsp; execution::set_error(std::move(</span><span class="c4">rcvr</span><span class="c16 c8">), std::forward&lt;Error&gt;(err));</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; }</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; void set_stopped() &amp;&amp; noexcept {</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; &nbsp; execution::set_stopped(std::move(</span><span class="c4">rcvr</span><span class="c16 c8">));</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; }</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; decltype(auto) get_env() const noexcept {</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; &nbsp; return </span><span class="c8 c13">/* see below */</span><span class="c21 c8">JOIN-ENV(env, FWD-ENV(execution::get_env(rcvr)))</span><span class="c16 c8">;</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; }</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; Rcvr&amp; </span><span class="c4">rcvr</span><span class="c16 c8">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// exposition only</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; Env </span><span class="c4">env</span><span class="c16 c8">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// exposition only</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; };</span></p><p class="c1 c15"><span class="c16 c8">}</span></p><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1 c2"><span class="c13">Where </span><span class="c4 c13">receiver2</span><span class="c8 c13">::get_env()</span><span class="c13">&nbsp;returns an object, </span><span class="c8 c13">e</span><span class="c0">, such that:</span></p><ul class="c22 lst-kix_rfzv2nw2zdyp-0 start"><li class="c1 c18 c15 li-bullet-2"><span class="c8 c13">decltype(e)</span><span class="c13">&nbsp;models </span><span class="c8 c13">queryable</span><span class="c0">&nbsp;; and</span></li><li class="c1 c18 c15 li-bullet-2"><span class="c13">Given a query object, </span><span class="c8 c13">q</span><span class="c13">, the expression </span><span class="c8 c13">e.query(q)</span><span class="c13">&nbsp;is expression-equivalent to </span><span class="c4 c13">env</span><span class="c8 c13">.query(q)</span><span class="c13">&nbsp;if that expression is valid, otherwise </span><span class="c8 c13">e.query(q)</span><span class="c13">&nbsp;is expression-equivalent to </span><span class="c8 c13">get_env(</span><span class="c4 c13">rcvr</span><span class="c8 c13">).query(q)</span><span class="c0">.</span></li></ul><p class="c1 c23 c2"><span class="c0"></span></p><p class="c1"><span class="c10">Modify [exec.snd.expos] p43 as follows:</span></p><p class="c1 c23"><span class="c10"></span></p><p class="c1 c2"><span>Remarks: The exposition-only class template </span><span class="c4">impls-for</span><span>&nbsp;([exec.snd.general]) is specialized for </span><span class="c4">write-env-t</span><span class="c10">&nbsp;as follows:</span></p><p class="c1 c23 c2"><span class="c10"></span></p><p class="c1 c15"><span class="c16 c8">template&lt;&gt;</span></p><p class="c1 c15"><span class="c8">struct </span><span class="c4">impls-for</span><span class="c8">&lt;</span><span class="c4">write-env-t</span><span class="c8">&gt; : </span><span class="c4">default-impls</span><span class="c16 c8">&nbsp;{</span></p><p class="c1 c15"><span class="c8">&nbsp; static constexpr auto </span><span class="c4">get-env</span><span class="c16 c8">&nbsp;=</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; [](auto, const auto&amp; state, const auto&amp; rcvr) noexcept {</span></p><p class="c1 c15"><span class="c8">&nbsp; &nbsp; &nbsp; return </span><span class="c8 c13">/* see below */</span><span class="c21 c4">JOIN-ENV</span><span class="c21 c8">(state, get_env(rcvr))</span><span class="c16 c8">;</span></p><p class="c1 c15"><span class="c16 c8">&nbsp; &nbsp; };</span></p><p class="c1 c15"><span class="c16 c8">};</span></p><p class="c1 c3"><span class="c16 c8"></span></p><p class="c1 c2"><span class="c13">Where </span><span class="c4 c13">impls-for</span><span class="c8 c13">&lt;</span><span class="c4 c13">write-env-t</span><span class="c8 c13">&gt;::</span><span class="c4 c13">get-env</span><span class="c0">&nbsp;returns an object, e, such that:</span></p><ul class="c22 lst-kix_um824w1i5wo5-0 start"><li class="c1 c18 c15 li-bullet-1"><span class="c8 c13">decltype(e)</span><span class="c13">&nbsp;models </span><span class="c8 c13">queryable</span><span class="c0">&nbsp;; and</span></li><li class="c1 c18 c15 li-bullet-2"><span class="c13">Given a query object, </span><span class="c8 c13">q</span><span class="c13">, the expression </span><span class="c8 c13">e.query(q)</span><span class="c13">&nbsp;is expression-equivalent to </span><span class="c8 c13">state.query(q)</span><span class="c13">&nbsp;if that expression is valid, otherwise, </span><span class="c8 c13">e.query(q)</span><span class="c13">&nbsp;is expression-equivalent to </span><span class="c8 c13">get_env(rcvr).query(q)</span><span class="c13">.</span></li></ul></body></html>