Thanks a lot for such a detailed answer Arthur. 

I had originally written a much bigger paper with more motivational examples and comparisons to alternatives design, but I figured no one would have taken the time to read it thoroughly, so I made it about 4x shorter, which was I guess too much. 

I think i should explain where I'm coming from with these ideas : 
We lack ways to do customizations points and interface adaptation in C++ (this talk of JeanHeyde Meneide sums up current practice pretty well, and none are satisfactory). In my opinion this will continue to be the case until we get something along the lines of type-classes (and this paper provides some reason for that) but I don't think further work will be done on concept_map anytime soon. 
At the same time, the incomprehensible, unhygienic rules of look-up continue to damage codebases. 
All of these problems boil down to a context-dependent association between types and symbols : they are intrinsically linked, and a proper solution must be a joint solution. This is a fundamental weakness of C++ and I find the fact that almost no propositions has been done to address this (except this paper) a bit worrying : along with reflection/metaprogramming (which might themselves offer a way out), this is one of the first issues with C++ right now, one that every developer from novice to library writer wrestle with. 

Now onto addressing your points : 

(1, 2) Thanks for explaining how to do motivational examples properly, I'll try to remedy to this in a future version 

(3) This idea of "associated anonymous namespace" is precisely to provide a migration away from current ADL. The new proposed rule for ADL should only be something that is adopted is the far future, once most programmers have adopted the practice of putting non-members in the associated anonymous namespace (and in order for that to happen, there should be some immediate benefits to doing so, for example by prioritizing (see (15)) the functions found in the associated anonymous namespace over any viable overload elsewhere). 

(4, 5) You're right, those examples were not very good. 

(6) The intent behind declaring a type-namespace final is to make the symbols set of a type more observable, but I haven't really thought it through and the same could be achieved by grepping an anonymous associated namespace in a codebase. I'll ditch this part. 

(8) What i wanted to say in this part is : when the override of a virtual namespace N refer to N, N is considered as non-virtual : no specialization is ever considered. This is solely for supporting reuse/partial override. This is indeed completely at odds with how templates usually works. 

(9) There is no necessary relations between the name of a namespace specialization and its primary (i adopted the same logics as Matt Calabrese paper here, linked above)

(12) Oh... just when i thought i knew everything there is to know about how C++ look-up works. I had not taken that into account. 
>What should the effect of "not using namespace N;" be, if namespace N hadn't been "using-ed" to begin with?
No effect, this should just exclude every symbols from N from the current set : if there is no intersection, that's ok as the intent is realized. 

(14) I adopted the notation "namespace(T)" with the idea that until the proposed rule for ADL is adopted (so in +10 years), the set of symbols associated with T will be a superset of the associated anonymous namespace. I.e. "namespace<T>" is a subset of "namespace(T)", until the rule is adopted. 

(15) by prioritization i meant : if a function X from a namespace N is prioritized, then upon unqualified call to X, N::X will always be called if possible, regardless of whether or not a better match exists elsewhere. (the same rule with which members/non-members would be prioritized w.r.t. notation in Bjarne UFC proposal) 

I hope this makes a better case for these ideas. 

Regards, 
-Jean-Baptiste


Le sam. 19 déc. 2020 à 02:22, Arthur O'Dwyer <arthur.j.odwyer@gmail.com> a écrit :
On Thu, Dec 17, 2020 at 5:07 PM Jean-Baptiste Vallon Hoarau via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
>
> Recently i've been pondering on ADL, customization points and interface adaptation quite a bit.
> (TLDR there's a paper embedded in this email that try to address these problems, let me know what you think)

I've read your attached paper, "Type-namespace and symbols set control." I think:
(1) It's got way too many new features bundled together in one paper. Are they all needed, or are you sneaking in some "nice-to-haves" among the "must-haves"? Which are which?
(2) The features are poorly motivated. I mostly understand what each of them does, physically, but I don't understand why I as a C++ programmer would want to do those things. I recommend using "Tony Tables" to show (on the left) today's C++20 code that accomplishes some realistic task, and then (on the right) how the same task would be solved in a simpler or more robust way using your new features.  The important thing in a Tony Table is that the left-hand column must be real code that people are writing today. If your proposal simplifies the writing of only some pieces of code that people don't actually want to write, then your proposal doesn't help.
(3) I don't see a migration path from "C++20 ADL" to "your thing." IIUC, you are essentially proposing to take today's working code

    namespace N {
        struct A {};
        void swap(A&, A&);
    } // namespace N

    void test() {
        N::A a, b;
        using std::swap;
        swap(a, b);  // should call N::swap, not std::swap
    }

and silently break it.  You write:
"In order for a function F to be implicitly included in the set of available functions for unqualified look-up, F must be available in the associated anonymous type-namespaces of the types of the arguments."
So, either you are proposing a rule by which N::swap becomes "available in the associated anonymous type-namespace" of N::A, or else you're proposing to break this existing code. I don't see the former; I suspect the latter, which is a non-starter for WG21.

Longer/nittier comments:

(4) Your moo(cow) example in section 1.1 is isomorphic to
https://quuxplusone.github.io/blog/2018/08/13/fixing-adl-field-test/#update-tomasz-kami-ski-points-ou
No less a personage than Herb Sutter has also proposed breaking this code, in P0934R0 "A Modest Proposal: Fixing ADL."  But, if you're proposing to break it, you should clearly and explicitly say so, and show this example (or something like it). Your current example with names like `my_type` and `moo` is too contrived.

(5) Also in that example, you say "Under the current ADL rules..." but that's meaningless, as your example code uses syntax that is not C++20 syntax — `template<class T> namespace <my_type<T>>` and so on. So there's no way of telling what the "current" rules would make of it.

(6) You write: "An anonymous type-namespace can be extended, unless declared `final`."  This is meaningless. Namespaces can't be declared `final` today, and I don't see any grammar in your proposal that would make it possible in the future. For another thing, namespaces are open by definition; suppose I have two translation units, and in one I define `namespace A final { int foo(); }` and in the other I define `namespace A { int bar(); }`. Neither TU is aware of the other. Are you proposing that this should just be IFNDR?

(7) In section 1.2's example, I recommend getting rid of the functions' bodies. Just put their declarations:
    template <class T>
    virtual namespace plot_traits { 
        Point2D get_plot_point(T&, int);
        int get_num_points(T&);
    }
    template <class T>
    namespace complex_plot final : override plot_traits<std::vector<std::complex<T>>> {
        Point2D get_plot_point(T&, int);
        // OK as plot_traits<...> inside a plot_traits override always refer to the primary namespace
        using plot_traits<std::vector<std::complex<T>>>::get_num_points;
    }
Incidentally, I've moved the `final` keyword to a more appropriate place (I assume that's what you intended).

(8) Your code comment there is completely at odds with how templates work anywhere else in the language. Normally, when I have a template with some partial specializations, the partial specializations are there specifically to avoid instantiating the primary template for some problematic type. You seem to be proposing that when plot_traits<X> refers to plot_traits<X>, the compiler should take that as a sort of "super class reference," and go and instantiate the next most specialized specialization of the template. What happens if there are multiple partial specializations available, and it's not clear which one is the next most specialized?

(9) Finally, where did the identifier `complex_plot` spring from?  What is its purpose?  What is the relationship between this "specialization" of namespace plot_traits<T> and the actual namespace complex_plot?
    namespace complex_plot { int baz(); }

(10) The punchline of section 1.2 seems to be that after jumping through all of these hoops, we can then use plot_traits<T>::get_num_points(t) exactly as if plot_traits were defined as a plain old traits class, like `iterator_traits` or `regex_traits`:

    template<class T>
    struct plot_traits;

So what's the purpose of all this new syntax?  What does it buy us?  Certainly not simplicity!

(11) In section 1.3, you should read https://brevzin.github.io/c++/2019/04/13/ufcs-history/ and then eliminate section 1.3.

(12) Section 2.1, "not using", is interesting.
Do you understand the subtle difference between "using N::foo;" and "using namespace N;"?  (I owe a blog post on this subject, although honestly I don't understand the reason it was done this way to begin with. Asked on SO: https://stackoverflow.com/questions/65365681/why-does-cs-using-namespace-work-the-way-it-does )
What should the effect of "not using namespace N;" be, if namespace N hadn't been "using-ed" to begin with?

(13) Section 2.2 lacks motivation. Remember, "motivation" isn't "Without this feature, my sample code won't compile!" and it isn't "This keyword kind of looks like it might do X, so let's make it do that."  You should write a Tony Table, showing some real code from your codebase on the left, and then showing how you want to be able to write it, on the right. Make sure the snippet is long enough that it's "falsifiable." You want the reader to be able to say, "Ah, yes, I agree that that is the best possible way to write that code in C++20, and I could not do better myself; and furthermore, I agree that the right-hand snippet is better."  If your snippet is too short and contrived, the reader will simply disagree that the left-hand snippet is reasonable.

(14) Section 2.3, I don't understand how this `namespace(T)` relates back to your original idea of having an "anonymous associated namespace" named `namespace<T>`. Are `namespace(T)` and `namespace<T>` the same thing? If so, pick one name and stick to it. Don't make two names for the same notion.

(15) Section 2.4 lacks motivation, and also lacks rigor — what do you mean by "prioritization" in this context? (But first, write a Tony Table! If you can't do that, then there's no point trying to explain what you meant by "prioritization.")

(16) Section 2.4 also seems to be assuming some kind of UFCS. In C++ today, `t.blah()` never calls a free function.

(17) Section 2.5 lacks motivation.
See D&E section 17.4, where Stroustrup writes:
> ...the original design allowed for several member names to be mentioned in a single using-declaration:
>     using X::(f,g,h);
> This is syntactically ugly, and so were all the alternatives we considered. ... Having used namespaces
> a bit, I found far less need for such lists than I had expected. I also tended to overlook such lists when
> reading code because they resembled function declarations too much, so I fell into the habit of using
> repeated using-declarations instead:
>     using X::f;
>     using X::g;
>     using X::h;
> Consequently, there is no special form of a using-declaration that specifies a list of member names.

I buy Stroustrup's logic.


Bottom line: I'm glad you're aware that lookup in C++ is a big mess with no logic. But it seems like you're just throwing a grab-bag of additional widgets at the wall, without actually trying to solve any existing problem. And you're proposing silent code breakage with no migration path.

HTH,
Arthur