Skip to content

Conversation

ghost
Copy link

@ghost ghost commented Mar 14, 2015

@ghost
Copy link
Author

ghost commented Mar 14, 2015

For better readability and to retain more of the proper CamelCase and snake_case looks for traits, structs and functions, we could change them from being the prefix opt- and mut- to being the postfix -opt and -mut respectively.

@mahkoh
Copy link
Contributor

mahkoh commented Mar 14, 2015

👍 Maybe not this syntax, but being generic over mutability is often useful. I believe that all Deref and DerefMut implementations in the rust repo are exactly the same except that the mut one has mut in it.

@ghost
Copy link
Author

ghost commented Mar 14, 2015

@mahkoh I thought about putting opt in template parameters, right after lifetime parameters and before type parameters, and opt would implicitly default to being "nothing" (instead of to being mut). That still leaves us with the question of how to rename the mut versions of methods and free functions so that they're different from the non-mut versions.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this syntax is ambiguous between self.opt - bar() and self.opt-bar()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@reem Who do you mean it's ambiguous to?

  • The parser
  • The compiler
  • Programmer who is reading quickly and doesn't have syntax highlighting

It shouldn't be ambiguous to the first two, because the opt keyword followed by one or more white space followed by - would always be a compile-time error.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the parser, but I guess it's not ambiguous if you ban the ambiguity ;)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the use of - note: allowing - in identifiers is one of the alternatives in #940 (though I can't say many people seem interested).

@reem
Copy link

reem commented Mar 14, 2015

Being generic over mutability is definitely useful, but I think a lot of careful thought is necessary before we settle on any specific incarnation; there are both many conceptual consistency and practical issues that need to be considered.

Unfortunately, I'm not convinced this proposal is up to dealing with the magnitude of this challenge. For instance, it doesn't cover abstracting over the "by-value" mode at all, meaning it can't be used to collapse the Fn traits due to FnOnce and isn't clearly extensible for future reference types like &own or even existing ones like Box, which is needed to collapse FnBox/Invoke.

@lambda-fairy
Copy link
Contributor

I agree with @reem in that it needs much more thought. Such extensions tend to have tricky edge cases which aren't apparent from a few simple examples.

I also don't see a mention of HKT, which may solve the same problem in a more general way.

@blaenk
Copy link
Contributor

blaenk commented Mar 16, 2015

I would really love to have this functionality, but not in the proposed form. I completely agree with @reem and @lfairy, especially regarding HKT and a potentially more general solution.

@Ericson2314
Copy link
Contributor

Yeah what we want to do is parametrize the capabilities of pointer types. This proposal suffers from the similar expressiveness issues as Any -> Any w.r.t ∀a. a -> a. I hear the Disciple language (http://trac.ouroborus.net/ddc/) has done some interesting work with parametric regions and effects; I recommend anybody wanting to take up this problem consult their work first. To be clear, the problem is very real and fixing it will allow us to consolidate various APIs quite dramatically, but sadly this proposal isn't up to the task.

@glaebhoerl
Copy link
Contributor

Another source of inspiration might be this presentation and the many references mentioned in it. In particular I wonder if we couldn't think of our reference types as being a combination of a pointer plus the capability to access it, after a similar fashion as suggested therein:

struct Ptr<'a> { addr: usize } // on its own, can't be read nor written
impl<'a> Copy for Ptr<'a>

struct SharedAccessCap<'a, T>;
impl<'a, T> Copy for SharedAccesssCap<'a, T>

struct MutAccessCap<'a, T>;
// no Copy

intrinsic fn read_shared<'a, T>(ptr: Ptr<'a>, cap: SharedAccessCap<'a, T>) -> T
intrinsic fn read_mut<'a, T>(ptr: Ptr<'a>, cap: MutAccessCap<'a, T>) -> (T, MutAccessCap<'a, T>)
intrinsic fn write_mut<'a, T>(ptr: Ptr<'a>, cap: MutAccessCap<'a, T>, val: T) -> MutAccessCap<'a, T>
intrinsic fn downgrade<'a, T>(cap: MutAccessCap<'a, T>) -> SharedAccessCap<'a, T>

type &'a     T = (Ptr<'a>, SharedAccessCap<'a, T>)
type &'a mut T = (Ptr<'a>, MutAccessCap<'a, T>)

...or something like that.

I suspect this couldn't really work as-is, because our lifetimes aren't quite the same thing as their regions (I believe it's possible for two disjoint pieces of memory to have the same lifetime?), but perhaps the idea could still be useful somehow. (I'm an expert on neither.)

(It gets harder if you also wish to consider &move and &out - but then again, code which could be generic over two or more reference types out of which at least one is &move or &out seems like it would be uncommon.)

@Ericson2314
Copy link
Contributor

@glaebhoerl cool slides! Also I'd guess that code that partially assigns + refines a pointer can be generic over various combinations of &mut, &out, and &in.

@brson brson self-assigned this Mar 19, 2015
@nikomatsakis
Copy link
Contributor

There's no question that there are many types that could usefully generalize over mut and shared. However, I think the best answer here is not to jump to a special-purpose kind of generalization, but rather to lean on type generalization, perhaps augmented with HKT in the future. After all, writing code is generic over mut/non-mut is possible today, though not fully general, by using type parameters:

struct Foo<R: Deref> {
    reference: R
}

this struct can be used with &T or &mut T and -- even better -- with Box<T> and Rc<T> too. (Here T could be written R::Output.)

@brson
Copy link
Contributor

brson commented Apr 6, 2015

I'm also concerned about the unknowns here and think this duality is something we've lived with for a long time and can continue to do so. As @nikomatsakis there are potential other solutions. Let's not be hasty.

Thanks for the thought-provoking RFC, but we're not going to pursue this avenue.

@brson brson closed this Apr 6, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants