Skip to content

Commit 2594d56

Browse files
committed
Introduce the new phantomdata/phantomfn markers and integrate them
into variance inference; fix various bugs in variance inference so that it considers the correct set of constraints; modify infer to consider the results of variance inference for type arguments.
1 parent dfc5c0f commit 2594d56

38 files changed

+1522
-503
lines changed

src/libcore/fmt/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use any;
1616
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
1717
use char::CharExt;
1818
use iter::{Iterator, IteratorExt};
19-
use marker::{Copy, Sized};
19+
use marker::{Copy, PhantomData, Sized};
2020
use mem;
2121
use option::Option;
2222
use option::Option::{Some, None};
@@ -914,6 +914,11 @@ impl Debug for () {
914914
f.pad("()")
915915
}
916916
}
917+
impl<T> Debug for PhantomData<T> {
918+
fn fmt(&self, f: &mut Formatter) -> Result {
919+
f.pad("PhantomData")
920+
}
921+
}
917922

918923
#[stable(feature = "rust1", since = "1.0.0")]
919924
impl<T: Copy + Debug> Debug for Cell<T> {

src/libcore/marker.rs

+85-210
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
#![stable(feature = "rust1", since = "1.0.0")]
2727

2828
use clone::Clone;
29+
use cmp;
30+
use option::Option;
31+
use hash::Hash;
32+
use hash::Hasher;
2933

3034
/// Types able to be transferred across thread boundaries.
3135
#[unstable(feature = "core",
@@ -42,15 +46,15 @@ pub unsafe trait Send: 'static {
4246
#[lang="send"]
4347
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
4448
#[cfg(not(stage0))]
45-
pub unsafe trait Send {
49+
pub unsafe trait Send : MarkerTrait {
4650
// empty.
4751
}
4852

4953
/// Types with a constant size known at compile-time.
5054
#[stable(feature = "rust1", since = "1.0.0")]
5155
#[lang="sized"]
5256
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
53-
pub trait Sized {
57+
pub trait Sized : MarkerTrait {
5458
// Empty.
5559
}
5660

@@ -155,7 +159,7 @@ pub trait Sized {
155159
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
156160
#[stable(feature = "rust1", since = "1.0.0")]
157161
#[lang="copy"]
158-
pub trait Copy {
162+
pub trait Copy : MarkerTrait {
159163
// Empty.
160164
}
161165

@@ -208,216 +212,10 @@ pub trait Copy {
208212
reason = "will be overhauled with new lifetime rules; see RFC 458")]
209213
#[lang="sync"]
210214
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
211-
pub unsafe trait Sync {
215+
pub unsafe trait Sync : MarkerTrait {
212216
// Empty
213217
}
214218

215-
/// A marker type that indicates to the compiler that the instances
216-
/// of the type itself owns instances of the type parameter `T`.
217-
///
218-
/// This is used to indicate that one or more instances of the type
219-
/// `T` could be dropped when instances of the type itself is dropped,
220-
/// though that may not be apparent from the other structure of the
221-
/// type itself. For example, the type may hold a `*mut T`, which the
222-
/// compiler does not automatically treat as owned.
223-
#[unstable(feature = "core",
224-
reason = "Newly added to deal with scoping and destructor changes")]
225-
#[lang="phantom_data"]
226-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
227-
pub struct PhantomData<T: ?Sized>;
228-
229-
impl<T: ?Sized> Copy for PhantomData<T> {}
230-
impl<T: ?Sized> Clone for PhantomData<T> {
231-
fn clone(&self) -> PhantomData<T> { *self }
232-
}
233-
234-
/// A marker type whose type parameter `T` is considered to be
235-
/// covariant with respect to the type itself. This is (typically)
236-
/// used to indicate that an instance of the type `T` is being stored
237-
/// into memory and read from, even though that may not be apparent.
238-
///
239-
/// For more information about variance, refer to this Wikipedia
240-
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
241-
///
242-
/// *Note:* It is very unusual to have to add a covariant constraint.
243-
/// If you are not sure, you probably want to use `InvariantType`.
244-
///
245-
/// # Example
246-
///
247-
/// Given a struct `S` that includes a type parameter `T`
248-
/// but does not actually *reference* that type parameter:
249-
///
250-
/// ```ignore
251-
/// use std::mem;
252-
///
253-
/// struct S<T> { x: *() }
254-
/// fn get<T>(s: &S<T>) -> T {
255-
/// unsafe {
256-
/// let x: *T = mem::transmute(s.x);
257-
/// *x
258-
/// }
259-
/// }
260-
/// ```
261-
///
262-
/// The type system would currently infer that the value of
263-
/// the type parameter `T` is irrelevant, and hence a `S<int>` is
264-
/// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
265-
/// any `U`). But this is incorrect because `get()` converts the
266-
/// `*()` into a `*T` and reads from it. Therefore, we should include the
267-
/// a marker field `CovariantType<T>` to inform the type checker that
268-
/// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
269-
/// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
270-
/// for some lifetime `'a`, but not the other way around).
271-
#[unstable(feature = "core",
272-
reason = "likely to change with new variance strategy")]
273-
#[lang="covariant_type"]
274-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
275-
pub struct CovariantType<T: ?Sized>;
276-
277-
impl<T: ?Sized> Copy for CovariantType<T> {}
278-
impl<T: ?Sized> Clone for CovariantType<T> {
279-
fn clone(&self) -> CovariantType<T> { *self }
280-
}
281-
282-
/// A marker type whose type parameter `T` is considered to be
283-
/// contravariant with respect to the type itself. This is (typically)
284-
/// used to indicate that an instance of the type `T` will be consumed
285-
/// (but not read from), even though that may not be apparent.
286-
///
287-
/// For more information about variance, refer to this Wikipedia
288-
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
289-
///
290-
/// *Note:* It is very unusual to have to add a contravariant constraint.
291-
/// If you are not sure, you probably want to use `InvariantType`.
292-
///
293-
/// # Example
294-
///
295-
/// Given a struct `S` that includes a type parameter `T`
296-
/// but does not actually *reference* that type parameter:
297-
///
298-
/// ```
299-
/// use std::mem;
300-
///
301-
/// struct S<T> { x: *const () }
302-
/// fn get<T>(s: &S<T>, v: T) {
303-
/// unsafe {
304-
/// let x: fn(T) = mem::transmute(s.x);
305-
/// x(v)
306-
/// }
307-
/// }
308-
/// ```
309-
///
310-
/// The type system would currently infer that the value of
311-
/// the type parameter `T` is irrelevant, and hence a `S<int>` is
312-
/// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
313-
/// any `U`). But this is incorrect because `get()` converts the
314-
/// `*()` into a `fn(T)` and then passes a value of type `T` to it.
315-
///
316-
/// Supplying a `ContravariantType` marker would correct the
317-
/// problem, because it would mark `S` so that `S<T>` is only a
318-
/// subtype of `S<U>` if `U` is a subtype of `T`; given that the
319-
/// function requires arguments of type `T`, it must also accept
320-
/// arguments of type `U`, hence such a conversion is safe.
321-
#[unstable(feature = "core",
322-
reason = "likely to change with new variance strategy")]
323-
#[lang="contravariant_type"]
324-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
325-
pub struct ContravariantType<T: ?Sized>;
326-
327-
impl<T: ?Sized> Copy for ContravariantType<T> {}
328-
impl<T: ?Sized> Clone for ContravariantType<T> {
329-
fn clone(&self) -> ContravariantType<T> { *self }
330-
}
331-
332-
/// A marker type whose type parameter `T` is considered to be
333-
/// invariant with respect to the type itself. This is (typically)
334-
/// used to indicate that instances of the type `T` may be read or
335-
/// written, even though that may not be apparent.
336-
///
337-
/// For more information about variance, refer to this Wikipedia
338-
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
339-
///
340-
/// # Example
341-
///
342-
/// The Cell type is an example of an `InvariantType` which uses unsafe
343-
/// code to achieve "interior" mutability:
344-
///
345-
/// ```
346-
/// struct Cell<T> { value: T }
347-
/// ```
348-
///
349-
/// The type system would infer that `value` is only read here
350-
/// and never written, but in fact `Cell` uses unsafe code to achieve
351-
/// interior mutability. In order to get correct behavior, the
352-
/// `InvariantType` marker must be applied.
353-
#[unstable(feature = "core",
354-
reason = "likely to change with new variance strategy")]
355-
#[lang="invariant_type"]
356-
#[derive(PartialEq, Eq, PartialOrd, Ord)]
357-
pub struct InvariantType<T: ?Sized>;
358-
359-
#[unstable(feature = "core",
360-
reason = "likely to change with new variance strategy")]
361-
impl<T: ?Sized> Copy for InvariantType<T> {}
362-
#[unstable(feature = "core",
363-
reason = "likely to change with new variance strategy")]
364-
impl<T: ?Sized> Clone for InvariantType<T> {
365-
fn clone(&self) -> InvariantType<T> { *self }
366-
}
367-
368-
/// As `CovariantType`, but for lifetime parameters. Using
369-
/// `CovariantLifetime<'a>` indicates that it is ok to substitute
370-
/// a *longer* lifetime for `'a` than the one you originally
371-
/// started with (e.g., you could convert any lifetime `'foo` to
372-
/// `'static`). You almost certainly want `ContravariantLifetime`
373-
/// instead, or possibly `InvariantLifetime`. The only case where
374-
/// it would be appropriate is that you have a (type-casted, and
375-
/// hence hidden from the type system) function pointer with a
376-
/// signature like `fn(&'a T)` (and no other uses of `'a`). In
377-
/// this case, it is ok to substitute a larger lifetime for `'a`
378-
/// (e.g., `fn(&'static T)`), because the function is only
379-
/// becoming more selective in terms of what it accepts as
380-
/// argument.
381-
///
382-
/// For more information about variance, refer to this Wikipedia
383-
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
384-
#[unstable(feature = "core",
385-
reason = "likely to change with new variance strategy")]
386-
#[lang="covariant_lifetime"]
387-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
388-
pub struct CovariantLifetime<'a>;
389-
390-
/// As `ContravariantType`, but for lifetime parameters. Using
391-
/// `ContravariantLifetime<'a>` indicates that it is ok to
392-
/// substitute a *shorter* lifetime for `'a` than the one you
393-
/// originally started with (e.g., you could convert `'static` to
394-
/// any lifetime `'foo`). This is appropriate for cases where you
395-
/// have an unsafe pointer that is actually a pointer into some
396-
/// memory with lifetime `'a`, and thus you want to limit the
397-
/// lifetime of your data structure to `'a`. An example of where
398-
/// this is used is the iterator for vectors.
399-
///
400-
/// For more information about variance, refer to this Wikipedia
401-
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
402-
#[unstable(feature = "core",
403-
reason = "likely to change with new variance strategy")]
404-
#[lang="contravariant_lifetime"]
405-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
406-
pub struct ContravariantLifetime<'a>;
407-
408-
/// As `InvariantType`, but for lifetime parameters. Using
409-
/// `InvariantLifetime<'a>` indicates that it is not ok to
410-
/// substitute any other lifetime for `'a` besides its original
411-
/// value. This is appropriate for cases where you have an unsafe
412-
/// pointer that is actually a pointer into memory with lifetime `'a`,
413-
/// and this pointer is itself stored in an inherently mutable
414-
/// location (such as a `Cell`).
415-
#[unstable(feature = "core",
416-
reason = "likely to change with new variance strategy")]
417-
#[lang="invariant_lifetime"]
418-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
419-
pub struct InvariantLifetime<'a>;
420-
421219
/// A type which is considered "not POD", meaning that it is not
422220
/// implicitly copyable. This is typically embedded in other types to
423221
/// ensure that they are never copied, even if they lack a destructor.
@@ -435,6 +233,83 @@ pub struct NoCopy;
435233
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
436234
pub struct Managed;
437235

236+
macro_rules! impls{
237+
($t: ident) => (
238+
impl<T:?Sized, S: Hasher> Hash<S> for $t<T> {
239+
#[inline]
240+
fn hash(&self, _: &mut S) {
241+
}
242+
}
243+
244+
impl<T:?Sized> cmp::PartialEq for $t<T> {
245+
fn eq(&self, _other: &$t<T>) -> bool {
246+
true
247+
}
248+
}
249+
250+
impl<T:?Sized> cmp::Eq for $t<T> {
251+
}
252+
253+
impl<T:?Sized> cmp::PartialOrd for $t<T> {
254+
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
255+
Option::Some(cmp::Ordering::Equal)
256+
}
257+
}
258+
259+
impl<T:?Sized> cmp::Ord for $t<T> {
260+
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
261+
cmp::Ordering::Equal
262+
}
263+
}
264+
265+
impl<T:?Sized> Copy for $t<T> { }
266+
267+
impl<T:?Sized> Clone for $t<T> {
268+
fn clone(&self) -> $t<T> {
269+
$t
270+
}
271+
}
272+
)
273+
}
274+
275+
/// `MarkerTrait` is intended to be used as the supertrait for traits
276+
/// that don't have any methods but instead serve just to designate
277+
/// categories of types. An example would be the `Send` trait, which
278+
/// indicates types that are sendable: `Send` does not itself offer
279+
/// any methods, but instead is used to gate access to data.
280+
///
281+
/// FIXME. Better documentation needed here!
282+
pub trait MarkerTrait : PhantomFn<Self> { }
283+
impl<T:?Sized> MarkerTrait for T { }
284+
285+
/// `PhantomFn` is a marker trait for use with traits that do not
286+
/// include any methods.
287+
///
288+
/// FIXME. Better documentation needed here!
289+
#[lang="phantom_fn"]
290+
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
291+
292+
#[cfg(stage0)] // built into the trait matching system after stage0
293+
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
294+
295+
/// Specific to stage0. You should not be seeing these docs!
296+
#[cfg(stage0)]
297+
#[lang="covariant_type"] // only relevant to stage0
298+
pub struct PhantomData<T:?Sized>;
299+
300+
/// `PhantomData` is a way to tell the compiler about fake fields.
301+
/// The idea is that if the compiler encounters a `PhantomData<T>`
302+
/// instance, it will behave *as if* an instance of the type `T` were
303+
/// present for the purpose of various automatic analyses.
304+
///
305+
/// FIXME. Better documentation needed here!
306+
#[cfg(not(stage0))]
307+
#[lang="phantom_data"]
308+
pub struct PhantomData<T:?Sized>;
309+
310+
impls! { PhantomData }
311+
312+
438313
#[cfg(not(stage0))]
439314
mod impls {
440315
use super::{Send, Sync, Sized};

0 commit comments

Comments
 (0)