Auto merge of #23938 - nikomatsakis:invariant, r=pnkfelix

There are still some remnants we could remove from the compiler (e.g. references to "subtraitrefs"; traits still have variance entries in the variance table), but this removes all user-visible bits I believe.

r? @pnkfelix 

Fixes #22806 (since such traits would no longer exist)
This commit is contained in:
bors 2015-04-03 12:59:11 +00:00
commit 2615106a46
61 changed files with 332 additions and 583 deletions

View file

@ -192,13 +192,16 @@ struct TyDesc {
align: usize
}
trait AllTypes { fn dummy(&self) { } }
impl<T:?Sized> AllTypes for T { }
unsafe fn get_tydesc<T>() -> *const TyDesc {
use std::raw::TraitObject;
let ptr = &*(1 as *const T);
// Can use any trait that is implemented for all types.
let obj = mem::transmute::<&marker::MarkerTrait, TraitObject>(ptr);
let obj = mem::transmute::<&AllTypes, TraitObject>(ptr);
obj.vtable as *const TyDesc
}

View file

@ -35,6 +35,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[allow(deprecated)]
pub unsafe trait Send : MarkerTrait {
// empty.
}
@ -50,6 +51,7 @@ impl !Send for Managed { }
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[allow(deprecated)]
pub trait Sized : MarkerTrait {
// Empty.
}
@ -203,6 +205,7 @@ pub trait Copy : Clone {
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
#[allow(deprecated)]
pub unsafe trait Sync : MarkerTrait {
// Empty
}
@ -269,84 +272,41 @@ fn clone(&self) -> $t<T> {
)
}
/// `MarkerTrait` is intended to be used as the supertrait for traits
/// that don't have any methods but instead serve just to designate
/// categories of types. An example would be the `Send` trait, which
/// indicates types that are sendable: `Send` does not itself offer
/// any methods, but instead is used to gate access to data.
///
/// FIXME. Better documentation needed here!
#[stable(feature = "rust1", since = "1.0.0")]
/// `MarkerTrait` is deprecated and no longer needed.
#[unstable(feature = "core", reason = "deprecated")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(stage0)]
pub trait MarkerTrait : PhantomFn<Self,Self> { }
// ~~~~~ <-- FIXME(#22806)?
//
// Marker trait has been made invariant so as to avoid inf recursion,
// but we should ideally solve the underlying problem. That's a bit
// complicated.
/// `MarkerTrait` is deprecated and no longer needed.
#[unstable(feature = "core", reason = "deprecated")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait MarkerTrait { }
#[allow(deprecated)]
impl<T:?Sized> MarkerTrait for T { }
/// `PhantomFn` is a marker trait for use with traits that contain
/// type or lifetime parameters that do not appear in any of their
/// methods. In that case, you can either remove those parameters, or
/// add a `PhantomFn` supertrait that reflects the signature of
/// methods that compiler should "pretend" exists. This most commonly
/// occurs for traits with no methods: in that particular case, you
/// can extend `MarkerTrait`, which is equivalent to
/// `PhantomFn<Self>`.
///
/// # Examples
///
/// As an example, consider a trait with no methods like `Even`, meant
/// to represent types that are "even":
///
/// ```rust,ignore
/// trait Even { }
/// ```
///
/// In this case, because the implicit parameter `Self` is unused, the
/// compiler will issue an error. The only purpose of this trait is to
/// categorize types (and hence instances of those types) as "even" or
/// not, so if we *were* going to have a method, it might look like:
///
/// ```rust,ignore
/// trait Even {
/// fn is_even(self) -> bool { true }
/// }
/// ```
///
/// Therefore, we can model a method like this as follows:
///
/// ```
/// use std::marker::PhantomFn;
/// trait Even : PhantomFn<Self> { }
/// ```
///
/// Another equivalent, but clearer, option would be to use
/// `MarkerTrait`:
///
/// ```
/// # #![feature(core)]
/// use std::marker::MarkerTrait;
/// trait Even : MarkerTrait { }
/// ```
///
/// # Parameters
///
/// - `A` represents the type of the method's argument. You can use a
/// tuple to represent "multiple" arguments. Any types appearing here
/// will be considered "contravariant".
/// - `R`, if supplied, represents the method's return type. This defaults
/// to `()` as it is rarely needed.
///
/// # Additional reading
///
/// More details and background can be found in [RFC 738][738].
///
/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
#[lang="phantom_fn"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
#[unstable(feature = "core", reason = "deprecated")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(stage0)]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
#[unstable(feature = "core", reason = "deprecated")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(not(stage0))]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
#[allow(deprecated)]
#[cfg(not(stage0))]
impl<A:?Sized,R:?Sized,T:?Sized> PhantomFn<A,R> for T { }
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
/// even though it does not. This allows you to inform the compiler about certain safety properties
@ -444,6 +404,7 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
/// [1]: http://en.wikipedia.org/wiki/Parametricity
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[allow(deprecated)]
pub trait Reflect : MarkerTrait {
}

View file

@ -14,6 +14,7 @@
use ops::Deref;
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[allow(deprecated)]
pub unsafe trait Zeroable : MarkerTrait {}
unsafe impl<T:?Sized> Zeroable for *const T {}

View file

@ -321,7 +321,6 @@ pub fn collect_language_items(krate: &ast::Crate,
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
OwnedBoxLangItem, "owned_box", owned_box;
PhantomFnItem, "phantom_fn", phantom_fn;
PhantomDataItem, "phantom_data", phantom_data;
// Deprecated:

View file

@ -138,11 +138,10 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
match predicate {
ty::Predicate::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type.
Some(data.def_id()) != tcx.lang_items.phantom_fn() &&
data.0.trait_ref.substs.types.get_slice(TypeSpace)
.iter()
.cloned()
.any(is_self)
data.0.trait_ref.substs.types.get_slice(TypeSpace)
.iter()
.cloned()
.any(is_self)
}
ty::Predicate::Projection(..) |
ty::Predicate::TypeOutlives(..) |

View file

@ -836,14 +836,6 @@ fn assemble_candidates<'o>(&mut self,
ambiguous: false
};
// Check for the `PhantomFn` trait. This is really just a
// special annotation that is *always* considered to match, no
// matter what the type parameters are etc.
if self.tcx().lang_items.phantom_fn() == Some(obligation.predicate.def_id()) {
candidates.vec.push(PhantomFnCandidate);
return Ok(candidates);
}
// Other bounds. Consider both in-scope bounds from fn decl
// and applicable impls. There is a certain set of precedence rules here.

View file

@ -122,11 +122,11 @@ fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R,
relate_substs(relation, opt_variances, a_subst, b_subst)
}
fn relate_substs<'a,'tcx,R>(relation: &mut R,
variances: Option<&ty::ItemVariances>,
a_subst: &Substs<'tcx>,
b_subst: &Substs<'tcx>)
-> RelateResult<'tcx, Substs<'tcx>>
fn relate_substs<'a,'tcx:'a,R>(relation: &mut R,
variances: Option<&ty::ItemVariances>,
a_subst: &Substs<'tcx>,
b_subst: &Substs<'tcx>)
-> RelateResult<'tcx, Substs<'tcx>>
where R: TypeRelation<'a,'tcx>
{
let mut substs = Substs::empty();
@ -161,11 +161,11 @@ fn relate_substs<'a,'tcx,R>(relation: &mut R,
Ok(substs)
}
fn relate_type_params<'a,'tcx,R>(relation: &mut R,
variances: Option<&[ty::Variance]>,
a_tys: &[Ty<'tcx>],
b_tys: &[Ty<'tcx>])
-> RelateResult<'tcx, Vec<Ty<'tcx>>>
fn relate_type_params<'a,'tcx:'a,R>(relation: &mut R,
variances: Option<&[ty::Variance]>,
a_tys: &[Ty<'tcx>],
b_tys: &[Ty<'tcx>])
-> RelateResult<'tcx, Vec<Ty<'tcx>>>
where R: TypeRelation<'a,'tcx>
{
if a_tys.len() != b_tys.len() {
@ -264,10 +264,10 @@ fn relate<R>(relation: &mut R,
}
}
fn relate_arg_vecs<'a,'tcx,R>(relation: &mut R,
a_args: &[Ty<'tcx>],
b_args: &[Ty<'tcx>])
-> RelateResult<'tcx, Vec<Ty<'tcx>>>
fn relate_arg_vecs<'a,'tcx:'a,R>(relation: &mut R,
a_args: &[Ty<'tcx>],
b_args: &[Ty<'tcx>])
-> RelateResult<'tcx, Vec<Ty<'tcx>>>
where R: TypeRelation<'a,'tcx>
{
if a_args.len() != b_args.len() {
@ -629,10 +629,10 @@ fn relate<R>(relation: &mut R,
///////////////////////////////////////////////////////////////////////////
// Error handling
pub fn expected_found<'a,'tcx,R,T>(relation: &mut R,
a: &T,
b: &T)
-> ty::expected_found<T>
pub fn expected_found<'a,'tcx:'a,R,T>(relation: &mut R,
a: &T,
b: &T)
-> ty::expected_found<T>
where R: TypeRelation<'a,'tcx>, T: Clone
{
expected_found_bool(relation.a_is_expected(), a, b)

View file

@ -117,15 +117,10 @@ fn check_item_well_formed(&mut self, item: &ast::Item) {
self.check_variances_for_type_defn(item, ast_generics);
}
ast::ItemTrait(_, ref ast_generics, _, ref items) => {
ast::ItemTrait(_, _, _, ref items) => {
let trait_predicates =
ty::lookup_predicates(ccx.tcx, local_def(item.id));
reject_non_type_param_bounds(
ccx.tcx,
item.span,
&trait_predicates);
self.check_variances(item, ast_generics, &trait_predicates,
self.tcx().lang_items.phantom_fn());
reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) {
if !items.is_empty() {
ccx.tcx.sess.span_err(
@ -287,30 +282,7 @@ fn check_variances_for_type_defn(&self,
ast_generics: &ast::Generics)
{
let item_def_id = local_def(item.id);
let predicates = ty::lookup_predicates(self.tcx(), item_def_id);
self.check_variances(item,
ast_generics,
&predicates,
self.tcx().lang_items.phantom_data());
}
fn check_variances(&self,
item: &ast::Item,
ast_generics: &ast::Generics,
ty_predicates: &ty::GenericPredicates<'tcx>,
suggested_marker_id: Option<ast::DefId>)
{
let variance_lang_items = &[
self.tcx().lang_items.phantom_fn(),
self.tcx().lang_items.phantom_data(),
];
let item_def_id = local_def(item.id);
let is_lang_item = variance_lang_items.iter().any(|n| *n == Some(item_def_id));
if is_lang_item {
return;
}
let ty_predicates = ty::lookup_predicates(self.tcx(), item_def_id);
let variances = ty::item_variances(self.tcx(), item_def_id);
let mut constrained_parameters: HashSet<_> =
@ -331,7 +303,7 @@ fn check_variances(&self,
continue;
}
let span = self.ty_param_span(ast_generics, item, space, index);
self.report_bivariance(span, param_ty.name, suggested_marker_id);
self.report_bivariance(span, param_ty.name);
}
for (space, index, &variance) in variances.regions.iter_enumerated() {
@ -342,7 +314,7 @@ fn check_variances(&self,
assert_eq!(space, TypeSpace);
let span = ast_generics.lifetimes[index].lifetime.span;
let name = ast_generics.lifetimes[index].lifetime.name;
self.report_bivariance(span, name, suggested_marker_id);
self.report_bivariance(span, name);
}
}
@ -377,14 +349,14 @@ fn ty_param_span(&self,
fn report_bivariance(&self,
span: Span,
param_name: ast::Name,
suggested_marker_id: Option<ast::DefId>)
param_name: ast::Name)
{
self.tcx().sess.span_err(
span,
&format!("parameter `{}` is never used",
param_name.user_string(self.tcx())));
let suggested_marker_id = self.tcx().lang_items.phantom_data();
match suggested_marker_id {
Some(def_id) => {
self.tcx().sess.fileline_help(

View file

@ -18,34 +18,121 @@
//! defined on type `X`, we only consider the definition of the type `X`
//! and the definitions of any types it references.
//!
//! We only infer variance for type parameters found on *types*: structs,
//! enums, and traits. We do not infer variance for type parameters found
//! on fns or impls. This is because those things are not type definitions
//! and variance doesn't really make sense in that context.
//!
//! It is worth covering what variance means in each case. For structs and
//! enums, I think it is fairly straightforward. The variance of the type
//! We only infer variance for type parameters found on *data types*
//! like structs and enums. In these cases, there is fairly straightforward
//! explanation for what variance means. The variance of the type
//! or lifetime parameters defines whether `T<A>` is a subtype of `T<B>`
//! (resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B`
//! (resp. `'a` and `'b`). (FIXME #3598 -- we do not currently make use of
//! the variances we compute for type parameters.)
//! (resp. `'a` and `'b`).
//!
//! ### Variance on traits
//! We do not infer variance for type parameters found on traits, fns,
//! or impls. Variance on trait parameters can make indeed make sense
//! (and we used to compute it) but it is actually rather subtle in
//! meaning and not that useful in practice, so we removed it. See the
//! addendum for some details. Variances on fn/impl parameters, otoh,
//! doesn't make sense because these parameters are instantiated and
//! then forgotten, they don't persist in types or compiled
//! byproducts.
//!
//! The meaning of variance for trait parameters is more subtle and worth
//! expanding upon. There are in fact two uses of the variance values we
//! compute.
//! ### The algorithm
//!
//! #### Trait variance and object types
//! The basic idea is quite straightforward. We iterate over the types
//! defined and, for each use of a type parameter X, accumulate a
//! constraint indicating that the variance of X must be valid for the
//! variance of that use site. We then iteratively refine the variance of
//! X until all constraints are met. There is *always* a sol'n, because at
//! the limit we can declare all type parameters to be invariant and all
//! constraints will be satisfied.
//!
//! The first is for object types. Just as with structs and enums, we can
//! decide the subtyping relationship between two object types `&Trait<A>`
//! and `&Trait<B>` based on the relationship of `A` and `B`. Note that
//! for object types we ignore the `Self` type parameter -- it is unknown,
//! and the nature of dynamic dispatch ensures that we will always call a
//! As a simple example, consider:
//!
//! enum Option<A> { Some(A), None }
//! enum OptionalFn<B> { Some(|B|), None }
//! enum OptionalMap<C> { Some(|C| -> C), None }
//!
//! Here, we will generate the constraints:
//!
//! 1. V(A) <= +
//! 2. V(B) <= -
//! 3. V(C) <= +
//! 4. V(C) <= -
//!
//! These indicate that (1) the variance of A must be at most covariant;
//! (2) the variance of B must be at most contravariant; and (3, 4) the
//! variance of C must be at most covariant *and* contravariant. All of these
//! results are based on a variance lattice defined as follows:
//!
//! * Top (bivariant)
//! - +
//! o Bottom (invariant)
//!
//! Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the
//! optimal solution. Note that there is always a naive solution which
//! just declares all variables to be invariant.
//!
//! You may be wondering why fixed-point iteration is required. The reason
//! is that the variance of a use site may itself be a function of the
//! variance of other type parameters. In full generality, our constraints
//! take the form:
//!
//! V(X) <= Term
//! Term := + | - | * | o | V(X) | Term x Term
//!
//! Here the notation V(X) indicates the variance of a type/region
//! parameter `X` with respect to its defining class. `Term x Term`
//! represents the "variance transform" as defined in the paper:
//!
//! If the variance of a type variable `X` in type expression `E` is `V2`
//! and the definition-site variance of the [corresponding] type parameter
//! of a class `C` is `V1`, then the variance of `X` in the type expression
//! `C<E>` is `V3 = V1.xform(V2)`.
//!
//! ### Constraints
//!
//! If I have a struct or enum with where clauses:
//!
//! struct Foo<T:Bar> { ... }
//!
//! you might wonder whether the variance of `T` with respect to `Bar`
//! affects the variance `T` with respect to `Foo`. I claim no. The
//! reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t
//! `Foo`. And then we have a `Foo<X>` that is upcast to `Foo<Y>`, where
//! `X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold. In that
//! case, the upcast will be illegal, but not because of a variance
//! failure, but rather because the target type `Foo<Y>` is itself just
//! not well-formed. Basically we get to assume well-formedness of all
//! types involved before considering variance.
//!
//! ### Addendum: Variance on traits
//!
//! As mentioned above, we used to permit variance on traits. This was
//! computed based on the appearance of trait type parameters in
//! method signatures and was used to represent the compatibility of
//! vtables in trait objects (and also "virtual" vtables or dictionary
//! in trait bounds). One complication was that variance for
//! associated types is less obvious, since they can be projected out
//! and put to myriad uses, so it's not clear when it is safe to allow
//! `X<A>::Bar` to vary (or indeed just what that means). Moreover (as
//! covered below) all inputs on any trait with an associated type had
//! to be invariant, limiting the applicability. Finally, the
//! annotations (`MarkerTrait`, `PhantomFn`) needed to ensure that all
//! trait type parameters had a variance were confusing and annoying
//! for little benefit.
//!
//! Just for historical reference,I am going to preserve some text indicating
//! how one could interpret variance and trait matching.
//!
//! #### Variance and object types
//!
//! Just as with structs and enums, we can decide the subtyping
//! relationship between two object types `&Trait<A>` and `&Trait<B>`
//! based on the relationship of `A` and `B`. Note that for object
//! types we ignore the `Self` type parameter -- it is unknown, and
//! the nature of dynamic dispatch ensures that we will always call a
//! function that is expected the appropriate `Self` type. However, we
//! must be careful with the other type parameters, or else we could end
//! up calling a function that is expecting one type but provided another.
//! must be careful with the other type parameters, or else we could
//! end up calling a function that is expecting one type but provided
//! another.
//!
//! To see what I mean, consider a trait like so:
//!
@ -135,104 +222,24 @@
//!
//! These conditions are satisfied and so we are happy.
//!
//! ### The algorithm
//! #### Variance and associated types
//!
//! The basic idea is quite straightforward. We iterate over the types
//! defined and, for each use of a type parameter X, accumulate a
//! constraint indicating that the variance of X must be valid for the
//! variance of that use site. We then iteratively refine the variance of
//! X until all constraints are met. There is *always* a sol'n, because at
//! the limit we can declare all type parameters to be invariant and all
//! constraints will be satisfied.
//!
//! As a simple example, consider:
//!
//! enum Option<A> { Some(A), None }
//! enum OptionalFn<B> { Some(|B|), None }
//! enum OptionalMap<C> { Some(|C| -> C), None }
//!
//! Here, we will generate the constraints:
//!
//! 1. V(A) <= +
//! 2. V(B) <= -
//! 3. V(C) <= +
//! 4. V(C) <= -
//!
//! These indicate that (1) the variance of A must be at most covariant;
//! (2) the variance of B must be at most contravariant; and (3, 4) the
//! variance of C must be at most covariant *and* contravariant. All of these
//! results are based on a variance lattice defined as follows:
//!
//! * Top (bivariant)
//! - +
//! o Bottom (invariant)
//!
//! Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the
//! optimal solution. Note that there is always a naive solution which
//! just declares all variables to be invariant.
//!
//! You may be wondering why fixed-point iteration is required. The reason
//! is that the variance of a use site may itself be a function of the
//! variance of other type parameters. In full generality, our constraints
//! take the form:
//!
//! V(X) <= Term
//! Term := + | - | * | o | V(X) | Term x Term
//!
//! Here the notation V(X) indicates the variance of a type/region
//! parameter `X` with respect to its defining class. `Term x Term`
//! represents the "variance transform" as defined in the paper:
//!
//! If the variance of a type variable `X` in type expression `E` is `V2`
//! and the definition-site variance of the [corresponding] type parameter
//! of a class `C` is `V1`, then the variance of `X` in the type expression
//! `C<E>` is `V3 = V1.xform(V2)`.
//!
//! ### Constraints
//!
//! If I have a struct or enum with where clauses:
//!
//! struct Foo<T:Bar> { ... }
//!
//! you might wonder whether the variance of `T` with respect to `Bar`
//! affects the variance `T` with respect to `Foo`. I claim no. The
//! reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t
//! `Foo`. And then we have a `Foo<X>` that is upcast to `Foo<Y>`, where
//! `X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold. In that
//! case, the upcast will be illegal, but not because of a variance
//! failure, but rather because the target type `Foo<Y>` is itself just
//! not well-formed. Basically we get to assume well-formedness of all
//! types involved before considering variance.
//!
//! ### Associated types
//!
//! Any trait with an associated type is invariant with respect to all
//! of its inputs. To see why this makes sense, consider what
//! subtyping for a trait reference means:
//! Traits with associated types -- or at minimum projection
//! expressions -- must be invariant with respect to all of their
//! inputs. To see why this makes sense, consider what subtyping for a
//! trait reference means:
//!
//! <T as Trait> <: <U as Trait>
//!
//! means that if I know that `T as Trait`,
//! I also know that `U as
//! Trait`. Moreover, if you think of it as
//! dictionary passing style, it means that
//! a dictionary for `<T as Trait>` is safe
//! to use where a dictionary for `<U as
//! Trait>` is expected.
//! means that if I know that `T as Trait`, I also know that `U as
//! Trait`. Moreover, if you think of it as dictionary passing style,
//! it means that a dictionary for `<T as Trait>` is safe to use where
//! a dictionary for `<U as Trait>` is expected.
//!
//! The problem is that when you can
//! project types out from `<T as Trait>`,
//! the relationship to types projected out
//! of `<U as Trait>` is completely unknown
//! unless `T==U` (see #21726 for more
//! details). Making `Trait` invariant
//! ensures that this is true.
//!
//! *Historical note: we used to preserve this invariant another way,
//! by tweaking the subtyping rules and requiring that when a type `T`
//! appeared as part of a projection, that was considered an invariant
//! location, but this version does away with the need for those
//! somewhat "special-case-feeling" rules.*
//! The problem is that when you can project types out from `<T as
//! Trait>`, the relationship to types projected out of `<U as Trait>`
//! is completely unknown unless `T==U` (see #21726 for more
//! details). Making `Trait` invariant ensures that this is true.
//!
//! Another related reason is that if we didn't make traits with
//! associated types invariant, then projection is no longer a
@ -383,7 +390,6 @@ fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec<ty::Variance>)> {
let all = vec![
(tcx.lang_items.phantom_fn(), vec![ty::Contravariant, ty::Covariant]),
(tcx.lang_items.phantom_data(), vec![ty::Covariant]),
(tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]),
@ -520,6 +526,9 @@ fn visit_item(&mut self, item: &ast::Item) {
self.add_inferreds_for_item(item.id, false, generics);
}
ast::ItemTrait(_, ref generics, _, _) => {
// Note: all inputs for traits are ultimately
// constrained to be invariant. See `visit_item` in
// the impl for `ConstraintContext` below.
self.add_inferreds_for_item(item.id, true, generics);
visit::walk_item(self, item);
}
@ -644,39 +653,9 @@ fn visit_item(&mut self, item: &ast::Item) {
ast::ItemTrait(..) => {
let trait_def = ty::lookup_trait_def(tcx, did);
let predicates = ty::lookup_super_predicates(tcx, did);
self.add_constraints_from_predicates(&trait_def.generics,
predicates.predicates.as_slice(),
self.covariant);
let trait_items = ty::trait_items(tcx, did);
for trait_item in &*trait_items {
match *trait_item {
ty::MethodTraitItem(ref method) => {
self.add_constraints_from_predicates(
&method.generics,
method.predicates.predicates.get_slice(FnSpace),
self.contravariant);
self.add_constraints_from_sig(
&method.generics,
&method.fty.sig,
self.covariant);
}
ty::TypeTraitItem(ref data) => {
// Any trait with an associated type is
// invariant with respect to all of its
// inputs. See length discussion in the comment
// on this module.
let projection_ty = ty::mk_projection(tcx,
trait_def.trait_ref.clone(),
data.name);
self.add_constraints_from_ty(&trait_def.generics,
projection_ty,
self.invariant);
}
}
}
self.add_constraints_from_trait_ref(&trait_def.generics,
&trait_def.trait_ref,
self.invariant);
}
ast::ItemExternCrate(_) |
@ -1045,69 +1024,6 @@ fn add_constraints_from_substs(&mut self,
}
}
fn add_constraints_from_predicates(&mut self,
generics: &ty::Generics<'tcx>,
predicates: &[ty::Predicate<'tcx>],
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_generics({})",
generics.repr(self.tcx()));
for predicate in predicates.iter() {
match *predicate {
ty::Predicate::Trait(ty::Binder(ref data)) => {
self.add_constraints_from_trait_ref(generics, &*data.trait_ref, variance);
}
ty::Predicate::Equate(ty::Binder(ref data)) => {
// A == B is only true if A and B are the same
// types, not subtypes of one another, so this is
// an invariant position:
self.add_constraints_from_ty(generics, data.0, self.invariant);
self.add_constraints_from_ty(generics, data.1, self.invariant);
}
ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
// Why contravariant on both? Let's consider:
//
// Under what conditions is `(T:'t) <: (U:'u)`,
// meaning that `(T:'t) => (U:'u)`. The answer is
// if `U <: T` or `'u <= 't`. Let's see some examples:
//
// (T: 'big) => (T: 'small)
// where 'small <= 'big
//
// (&'small Foo: 't) => (&'big Foo: 't)
// where 'small <= 'big
// note that &'big Foo <: &'small Foo
let variance_r = self.xform(variance, self.contravariant);
self.add_constraints_from_ty(generics, data.0, variance_r);
self.add_constraints_from_region(generics, data.1, variance_r);
}
ty::Predicate::RegionOutlives(ty::Binder(ref data)) => {
// `'a : 'b` is still true if 'a gets bigger
self.add_constraints_from_region(generics, data.0, variance);
// `'a : 'b` is still true if 'b gets smaller
let variance_r = self.xform(variance, self.contravariant);
self.add_constraints_from_region(generics, data.1, variance_r);
}
ty::Predicate::Projection(ty::Binder(ref data)) => {
self.add_constraints_from_trait_ref(generics,
&*data.projection_ty.trait_ref,
variance);
// as the equality predicate above, a binder is a
// type equality relation, not a subtyping
// relation
self.add_constraints_from_ty(generics, data.ty, self.invariant);
}
}
}
}
/// Adds constraints appropriate for a function with signature
/// `sig` appearing in a context with ambient variance `variance`
fn add_constraints_from_sig(&mut self,

View file

@ -11,9 +11,7 @@
#![crate_type = "rlib"]
#![feature(fundamental)]
use std::marker::MarkerTrait;
pub trait MyCopy : MarkerTrait { }
pub trait MyCopy { }
impl MyCopy for i32 { }
pub struct MyStruct<T>(T);

View file

@ -8,6 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub trait TheTrait<T> : ::std::marker::PhantomFn<T> {
pub trait TheTrait<T> {
fn the_fn(&self);
}

View file

@ -12,12 +12,8 @@
#![no_std]
#![feature(lang_items)]
#[lang="phantom_fn"]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
#[lang="sized"]
pub trait Sized : PhantomFn<Self> {}
pub trait Sized { }
#[lang="panic"]
fn panic(_: &(&'static str, &'static str, usize)) -> ! { loop {} }
@ -29,7 +25,7 @@ fn panic(_: &(&'static str, &'static str, usize)) -> ! { loop {} }
extern fn eh_personality() {}
#[lang="copy"]
pub trait Copy : PhantomFn<Self> {
pub trait Copy {
// Empty.
}

View file

@ -16,12 +16,8 @@
#![feature(no_std)]
#![no_std]
#[lang="phantom_fn"]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
#[lang="sized"]
pub trait Sized : PhantomFn<Self> {
pub trait Sized {
// Empty.
}

View file

@ -18,11 +18,9 @@
extern crate coherence_copy_like_lib as lib;
use std::marker::MarkerTrait;
struct MyType { x: i32 }
trait MyTrait : MarkerTrait { }
trait MyTrait { }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyFundamentalStruct` is declared fundamental, so we can test that

View file

@ -18,11 +18,9 @@
extern crate coherence_copy_like_lib as lib;
use std::marker::MarkerTrait;
struct MyType { x: i32 }
trait MyTrait : MarkerTrait { }
trait MyTrait { }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyFundamentalStruct` is declared fundamental, so we can test that

View file

@ -8,9 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::marker::PhantomFn;
trait FromStructReader<'a> : PhantomFn<(Self,&'a ())> { }
trait FromStructReader<'a> { }
trait ResponseHook {
fn get<'a, T: FromStructReader<'a>>(&'a self);
}

View file

@ -13,12 +13,8 @@
#![feature(lang_items, start, no_std)]
#![no_std]
#[lang="phantom_fn"]
trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
#[lang = "sized"]
trait Sized : PhantomFn<Self> {}
trait Sized { }
#[start]
fn main(_: isize, _: *const *const u8) -> isize {

View file

@ -41,7 +41,7 @@ fn g<T>(val: T) {
fn foo<'a>() {
let t: S<&'a isize> = S(marker::PhantomData);
let a = &t as &Gettable<&'a isize>;
//~^ ERROR cannot infer
//~^ ERROR does not fulfill
}
fn foo2<'a>() {

View file

@ -12,18 +12,15 @@
#![allow(dead_code)]
#![deny(unsafe_code)]
use std::marker::PhantomFn;
struct Bar;
struct Bar2;
struct Bar3;
#[allow(unsafe_code)]
mod allowed_unsafe {
use std::marker::PhantomFn;
fn allowed() { unsafe {} }
unsafe fn also_allowed() {}
unsafe trait AllowedUnsafe : PhantomFn<Self> {}
unsafe trait AllowedUnsafe { }
unsafe impl AllowedUnsafe for super::Bar {}
}
@ -34,7 +31,7 @@ macro_rules! unsafe_in_macro {
}
unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
unsafe trait Foo : PhantomFn<Self> {} //~ ERROR: declaration of an `unsafe` trait
unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait
unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
trait Baz {

View file

@ -13,12 +13,10 @@
#![feature(rustc_attrs)]
#![allow(dead_code)]
use std::marker::PhantomFn;
trait Baz : PhantomFn<Self> {
trait Baz {
}
trait Bar<T> : PhantomFn<(Self, T)> {
trait Bar<T> {
}
fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {

View file

@ -13,11 +13,8 @@
#![allow(unused)]
use std::marker;
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
trait Foo<Bar, Baz, Quux>
: marker::PhantomFn<(Self,Bar,Baz,Quux)>
{}
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
@ -28,19 +25,16 @@ trait MyFromIterator<A> {
#[rustc_on_unimplemented] //~ ERROR this attribute must have a value
trait BadAnnotation1
: marker::MarkerTrait
{}
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
//~^ ERROR there is no type parameter C on trait BadAnnotation2
trait BadAnnotation2<A,B>
: marker::PhantomFn<(Self,A,B)>
{}
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
//~^ only named substitution parameters are allowed
trait BadAnnotation3<A,B>
: marker::PhantomFn<(Self,A,B)>
{}
pub fn main() {

View file

@ -11,11 +11,8 @@
#![feature(on_unimplemented)]
use std::marker;
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
trait Foo<Bar, Baz, Quux>
: marker::PhantomFn<(Self,Bar,Baz,Quux)>
{}
fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {

View file

@ -11,15 +11,11 @@
#![feature(lang_items, start, no_std)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
#[lang="phantom_fn"]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
#[lang="sized"]
pub trait Sized : PhantomFn<Self> {}
pub trait Sized {}
#[lang="copy"]
pub trait Copy : PhantomFn<Self> {}
pub trait Copy {}
mod bar {
// shouldn't bring in too much

View file

@ -11,12 +11,8 @@
#![feature(lang_items, start, no_std)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
#[lang="phantom_fn"]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
#[lang = "sized"] pub trait Sized : PhantomFn<Self> {}
#[lang="copy"] pub trait Copy : PhantomFn<Self> {}
#[lang = "sized"] pub trait Sized {}
#[lang="copy"] pub trait Copy {}
// Test to make sure that private items imported through globs remain private
// when they're used.

View file

@ -15,11 +15,9 @@
#![allow(dead_code)]
use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
pub trait TheTrait: PhantomFn<Self, Self> {
pub trait TheTrait {
type TheAssocType;
}

View file

@ -14,11 +14,9 @@
#![allow(dead_code)]
#![feature(rustc_attrs)]
use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
pub trait TheTrait<'b> : PhantomFn<&'b Self,Self> {
pub trait TheTrait<'b> {
type TheAssocType;
}

View file

@ -15,11 +15,9 @@
#![allow(dead_code)]
use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
pub trait TheTrait: PhantomFn<Self, Self> {
pub trait TheTrait {
type TheAssocType;
}

View file

@ -15,11 +15,9 @@
#![allow(dead_code)]
#![feature(rustc_attrs)]
use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
pub trait TheTrait: PhantomFn<Self, Self> {
pub trait TheTrait {
type TheAssocType;
}

View file

@ -11,12 +11,10 @@
#![feature(box_syntax)]
#![allow(warnings)]
use std::marker::PhantomFn;
trait A<T> : PhantomFn<(Self,T)> { }
trait A<T> { }
struct B<'a, T>(&'a (A<T>+'a));
trait X : ::std::marker::MarkerTrait {}
trait X { }
impl<'a, T> X for B<'a, T> {}

View file

@ -10,12 +10,10 @@
#![feature(box_syntax)]
use std::marker::PhantomFn;
trait A<T> : PhantomFn<(Self,T)> { }
trait A<T> { }
struct B<'a, T>(&'a (A<T>+'a));
trait X : PhantomFn<Self> {}
trait X { }
impl<'a, T> X for B<'a, T> {}
fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {

View file

@ -11,15 +11,13 @@
#![feature(box_syntax)]
#![allow(warnings)]
use std::marker::PhantomFn;
trait A<T> : PhantomFn<(Self,T)> {}
trait A<T> { }
struct B<'a, T>(&'a (A<T>+'a));
trait X : PhantomFn<Self> {}
trait X { }
impl<'a, T> X for B<'a, T> {}
fn h<'a, T, U>(v: Box<A<U>+'static>) -> Box<X+'static> {
fn h<'a, T, U:'static>(v: Box<A<U>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
}

View file

@ -10,12 +10,10 @@
#![feature(box_syntax)]
use std::marker::PhantomFn;
trait A<T> : PhantomFn<(Self,T)> {}
trait A<T> { }
struct B<'a, T>(&'a (A<T>+'a));
trait X : PhantomFn<Self> {}
trait X { }
impl<'a, T> X for B<'a, T> {}
fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {

View file

@ -11,11 +11,7 @@
#![feature(lang_items, no_std)]
#![no_std]
#[lang="phantom_fn"]
pub trait PhantomFn<T:?Sized> { }
impl<T:?Sized, U:?Sized> PhantomFn<T> for U { }
#[lang="sized"] pub trait Sized : PhantomFn<Self> {}
#[lang="sized"] pub trait Sized { }
// error-pattern:requires `start` lang_item

View file

@ -13,8 +13,7 @@
use std::marker;
trait A : marker::PhantomFn<Self> {
}
trait A { }
trait B: A {}

View file

@ -15,7 +15,6 @@ trait Iterator<A> {
}
trait IteratorUtil<A>
: ::std::marker::PhantomFn<(),A>
{
fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
}

View file

@ -16,14 +16,12 @@
#![feature(unboxed_closures)]
#![allow(dead_code)]
use std::marker::PhantomFn;
trait Foo<T> {
type Output;
fn dummy(&self, t: T, u: Self::Output);
}
trait Eq<X: ?Sized> : PhantomFn<(Self,X)> { }
trait Eq<X: ?Sized> { }
impl<X: ?Sized> Eq<X> for X { }
fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }

View file

@ -23,7 +23,7 @@ trait Foo<T> {
fn dummy(&self, t: T);
}
trait Eq<X: ?Sized> : marker::PhantomFn<(Self, X)> { }
trait Eq<X: ?Sized> { }
impl<X: ?Sized> Eq<X> for X { }
fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }

View file

@ -10,6 +10,9 @@
#![allow(dead_code)]
// Test that even when `T` is only used in contravariant position, it
// is treated as invariant.
trait Get<T> : 'static {
fn get(&self, t: T);
}
@ -25,7 +28,8 @@ fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
-> Box<Get<&'max i32>>
where 'max : 'min
{
v
// Previously OK:
v //~ ERROR mismatched types
}
fn main() { }

View file

@ -10,6 +10,9 @@
#![allow(dead_code)]
// Test that even when `T` is only used in contravariant position, it
// is treated as invariant.
trait Get<T> {
fn get(&self, t: T);
}
@ -23,7 +26,9 @@ fn get_min_from_max<'min, 'max, G>()
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : Get<&'min i32>
{
impls_get::<G,&'max i32>()
// Previously OK, but now an error because traits are invariant:
impls_get::<G,&'max i32>() //~ ERROR mismatched types
}
fn impls_get<G,T>() where G : Get<T> { }

View file

@ -10,6 +10,9 @@
#![allow(dead_code)]
// Test that even when `Self` is only used in contravariant position, it
// is treated as invariant.
trait Get {
fn get(&self);
}
@ -23,7 +26,10 @@ fn get_min_from_max<'min, 'max, G>()
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : 'max, &'min G : Get
{
impls_get::<&'max G>();
// Previously OK, but now error because traits are invariant with
// respect to all inputs.
impls_get::<&'max G>(); //~ ERROR mismatched types
}
fn impls_get<G>() where G : Get { }

View file

@ -10,6 +10,9 @@
#![allow(dead_code)]
// Test that even when `T` is only used in covariant position, it
// is treated as invariant.
trait Get<T> : 'static {
fn get(&self) -> T;
}
@ -18,7 +21,8 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
-> Box<Get<&'min i32>>
where 'max : 'min
{
v
// Previously OK, now an error as traits are invariant.
v //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)

View file

@ -10,6 +10,9 @@
#![allow(dead_code)]
// Test that even when `T` is only used in covariant position, it
// is treated as invariant.
trait Get<T> {
fn get(&self) -> T;
}
@ -17,7 +20,8 @@ trait Get<T> {
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : Get<&'max i32>
{
impls_get::<G,&'min i32>()
// Previously OK, now an error as traits are invariant.
impls_get::<G,&'min i32>() //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()

View file

@ -10,6 +10,9 @@
#![allow(dead_code)]
// Test that even when `Self` is only used in covariant position, it
// is treated as invariant.
trait Get {
fn get() -> Self;
}
@ -17,7 +20,8 @@ trait Get {
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : 'max, &'max G : Get
{
impls_get::<&'min G>();
// Previously OK, now an error as traits are invariant.
impls_get::<&'min G>(); //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()

View file

@ -13,11 +13,11 @@
#![feature(rustc_attrs)]
#[rustc_variance]
trait Foo: 'static { //~ ERROR types=[[];[-];[]]
trait Foo: 'static { //~ ERROR types=[[];[o];[]]
}
#[rustc_variance]
trait Bar<T> { //~ ERROR types=[[+];[-];[]]
trait Bar<T> { //~ ERROR types=[[o];[o];[]]
fn do_it(&self)
where T: 'static;
}

View file

@ -18,7 +18,7 @@ struct Struct<'a, 'd> { //~ ERROR parameter `'d` is never used
field: &'a [i32]
}
trait Trait<'a, 'd> { //~ ERROR parameter `'d` is never used
trait Trait<'a, 'd> { // OK on traits
fn method(&'a self);
}

View file

@ -16,12 +16,12 @@
// influence variance.
#[rustc_variance]
trait Getter<T> { //~ ERROR types=[[+];[-];[]]
trait Getter<T> { //~ ERROR types=[[o];[o];[]]
fn get(&self) -> T;
}
#[rustc_variance]
trait Setter<T> { //~ ERROR types=[[-];[-];[]]
trait Setter<T> { //~ ERROR types=[[o];[o];[]]
fn get(&self, T);
}
@ -37,16 +37,16 @@
}
#[rustc_variance]
trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[-, +];[-];[]]
trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[o, o];[o];[]]
fn getter(&self, u: U) -> T;
}
#[rustc_variance]
trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[+];[-];[]]
trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[o];[o];[]]
}
#[rustc_variance]
trait TestTrait3<U> { //~ ERROR types=[[-];[-];[]]
trait TestTrait3<U> { //~ ERROR types=[[o];[o];[]]
fn getter<T:Getter<U>>(&self);
}

View file

@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,22 +8,43 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Issue #5781. Tests that subtyping is handled properly in trait matching.
// pretty-expanded FIXME #23616
trait Make<'a> {
fn make(x: &'a mut isize) -> Self;
#![allow(dead_code)]
// Get<T> is covariant in T
trait Get<T> {
fn get(&self) -> T;
}
impl<'a> Make<'a> for &'a mut isize {
fn make(x: &'a mut isize) -> &'a mut isize {
x
struct Cloner<T:Clone> {
t: T
}
impl<T:Clone> Get<T> for Cloner<T> {
fn get(&self) -> T {
self.t.clone()
}
}
fn f() -> &'static mut isize {
let mut x = 1;
let y: &'static mut isize = Make::make(&mut x); //~ ERROR `x` does not live long enough
y
fn get<'a, G>(get: &G) -> i32
where G : Get<&'a i32>
{
// This fails to type-check because, without variance, we can't
// use `G : Get<&'a i32>` as evidence that `G : Get<&'b i32>`,
// even if `'a : 'b`.
pick(get, &22) //~ ERROR cannot infer
}
fn main() {}
fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
where G : Get<&'b i32>
{
let v = *get.get();
if v % 2 != 0 { v } else { *if_odd }
}
fn main() {
let x = Cloner { t: &23 };
let y = get(&x);
assert_eq!(y, 23);
}

View file

@ -37,12 +37,12 @@
}
#[rustc_variance]
trait Getter<A> { //~ ERROR types=[[+];[-];[]]
trait Getter<A> { //~ ERROR types=[[o];[o];[]]
fn get(&self) -> A;
}
#[rustc_variance]
trait Setter<A> { //~ ERROR types=[[-];[o];[]]
trait Setter<A> { //~ ERROR types=[[o];[o];[]]
fn set(&mut self, a: A);
}
@ -53,7 +53,7 @@
}
#[rustc_variance]
trait GetterInTypeBound<A> { //~ ERROR types=[[-];[-];[]]
trait GetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
// Here, the use of `A` in the method bound *does* affect
// variance. Think of it as if the method requested a dictionary
// for `T:Getter<A>`. Since this dictionary is an input, it is
@ -63,12 +63,12 @@
}
#[rustc_variance]
trait SetterInTypeBound<A> { //~ ERROR types=[[+];[-];[]]
trait SetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
fn do_it<T:Setter<A>>(&self);
}
#[rustc_variance]
struct TestObject<A, R> { //~ ERROR types=[[-, +];[];[]]
struct TestObject<A, R> { //~ ERROR types=[[o, o];[];[]]
n: Box<Setter<A>+Send>,
m: Box<Getter<R>+Send>,
}

View file

@ -12,6 +12,6 @@
struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used
enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used
trait SomeTrait<'a> { fn foo(&self); } //~ ERROR parameter `'a` is never used
trait SomeTrait<'a> { fn foo(&self); } // OK on traits.
fn main() {}

View file

@ -21,10 +21,6 @@ enum SomeEnum<A> { Nothing }
//~^ ERROR parameter `A` is never used
//~| HELP PhantomData
trait SomeTrait<A> { fn foo(&self); }
//~^ ERROR parameter `A` is never used
//~| HELP PhantomFn
// Here T might *appear* used, but in fact it isn't.
enum ListCell<T> {
//~^ ERROR parameter `T` is never used

View file

@ -70,14 +70,10 @@ pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
}
#[lang = "sized"]
pub trait Sized : PhantomFn<Self> {}
pub trait Sized { }
#[lang = "copy"]
pub trait Copy : PhantomFn<Self> {}
#[lang="phantom_fn"]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
pub trait Copy { }
mod core {
pub mod marker {

View file

@ -11,15 +11,11 @@
#![feature(lang_items, no_std)]
#![no_std]
#[lang="phantom_fn"]
trait PhantomFn<A:?Sized,R:?Sized=()> { }
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
#[lang="copy"]
trait Copy : PhantomFn<Self> { }
trait Copy { }
#[lang="sized"]
trait Sized : PhantomFn<Self> { }
trait Sized { }
#[lang="start"]
fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 }

View file

@ -16,7 +16,6 @@ fn foo(&self) { }
}
impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) {
//~^ ERROR E0119
}
impl Contravariant for for<'a> fn(&'a u8, &'a u8) {
@ -29,7 +28,6 @@ fn foo(&self) { }
}
impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) {
//~^ ERROR E0119
}
impl Covariant for for<'a> fn(&'a u8, &'a u8) {
@ -38,7 +36,7 @@ impl Covariant for for<'a> fn(&'a u8, &'a u8) {
///////////////////////////////////////////////////////////////////////////
trait Invariant {
fn foo(&self) -> Self { }
fn foo(&self) { }
}
impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) {

View file

@ -15,11 +15,9 @@
extern crate coherence_copy_like_lib as lib;
use std::marker::MarkerTrait;
struct MyType { x: i32 }
trait MyTrait : MarkerTrait { }
trait MyTrait { }
impl<T: lib::MyCopy> MyTrait for T { }
impl MyTrait for MyType { }
impl<'a> MyTrait for &'a MyType { }

View file

@ -12,9 +12,7 @@
// pretty-expanded FIXME #23616
use std::marker::PhantomFn;
trait Chromosome<X: Chromosome<i32>> : PhantomFn<(Self,X)> {
trait Chromosome<X: Chromosome<i32>> {
}
fn main() { }

View file

@ -10,7 +10,7 @@
// pretty-expanded FIXME #23616
use std::marker::{PhantomData, PhantomFn};
use std::marker::PhantomData;
pub struct Handle<T, I>(T, I);
@ -34,7 +34,7 @@ pub fn get_info(&self) -> &String {
pub type RawBufferHandle<D: Device> = Handle<<D as Device>::Buffer, String>;
pub trait Device: PhantomFn<Self> {
pub trait Device {
type Buffer;
}

View file

@ -27,9 +27,7 @@ pub trait Decoder<'v> {
fn read(&mut self) -> Value<'v>;
}
pub trait Decodable<'v, D: Decoder<'v>>
: marker::PhantomFn<(), &'v isize>
{
pub trait Decodable<'v, D: Decoder<'v>> {
fn decode(d: &mut D) -> Self;
}

View file

@ -17,13 +17,11 @@
#![allow(unknown_features)]
#![feature(box_syntax)]
use std::marker::MarkerTrait;
trait Get {
fn get(&self) -> Self;
}
trait MyCopy : MarkerTrait { fn copy(&self) -> Self; }
trait MyCopy { fn copy(&self) -> Self; }
impl MyCopy for u16 { fn copy(&self) -> Self { *self } }
impl MyCopy for u32 { fn copy(&self) -> Self { *self } }
impl MyCopy for i32 { fn copy(&self) -> Self { *self } }

View file

@ -12,17 +12,17 @@
// pretty-expanded FIXME #23616
use std::marker::{PhantomData, PhantomFn};
use std::marker::PhantomData;
trait T1 : PhantomFn<Self> { }
pub trait T2 : PhantomFn<Self> { }
trait T3<X: T1> : T2 + PhantomFn<X> { }
trait T4<X: ?Sized> : PhantomFn<(Self,X)> {}
trait T5<X: ?Sized, Y> : PhantomFn<(Self,X,Y)> {}
trait T6<Y, X: ?Sized> : PhantomFn<(Self,X,Y)> {}
trait T7<X: ?Sized, Y: ?Sized> : PhantomFn<(Self,X,Y)> {}
trait T8<X: ?Sized+T2> : PhantomFn<(Self,X)> {}
trait T9<X: T2 + ?Sized> : PhantomFn<(Self,X)> {}
trait T1 { }
pub trait T2 { }
trait T3<X: T1> : T2 { }
trait T4<X: ?Sized> { }
trait T5<X: ?Sized, Y> { }
trait T6<Y, X: ?Sized> { }
trait T7<X: ?Sized, Y: ?Sized> { }
trait T8<X: ?Sized+T2> { }
trait T9<X: T2 + ?Sized> { }
struct S1<X: ?Sized>(PhantomData<X>);
enum E<X: ?Sized> { E1(PhantomData<X>) }
impl <X: ?Sized> T1 for S1<X> {}

View file

@ -1,49 +0,0 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// pretty-expanded FIXME #23616
#![allow(dead_code)]
// Get<T> is covariant in T
trait Get<T> {
fn get(&self) -> T;
}
struct Cloner<T:Clone> {
t: T
}
impl<T:Clone> Get<T> for Cloner<T> {
fn get(&self) -> T {
self.t.clone()
}
}
fn get<'a, G>(get: &G) -> i32
where G : Get<&'a i32>
{
// This call only type checks if we can use `G : Get<&'a i32>` as
// evidence that `G : Get<&'b i32>` where `'a : 'b`.
pick(get, &22)
}
fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
where G : Get<&'b i32>
{
let v = *get.get();
if v % 2 != 0 { v } else { *if_odd }
}
fn main() {
let x = Cloner { t: &23 };
let y = get(&x);
assert_eq!(y, 23);
}

View file

@ -13,18 +13,13 @@
// pretty-expanded FIXME #23616
use std::marker::PhantomFn;
static mut COUNT: u32 = 1;
trait Bar<'a>
: PhantomFn<&'a ()>
{
trait Bar<'a> {
fn bar(&self);
}
trait Baz<'a>
: PhantomFn<&'a ()>
{
fn baz(&self);
}