diff options
61 files changed, 332 insertions, 583 deletions
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 7843be0b483..3f85af97197 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -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 } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 619f983aee0..352f7d86977 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -35,6 +35,7 @@ use hash::Hasher; #[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 @@ macro_rules! impls{ ) } -/// `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 @@ mod impls { /// [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 { } diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 230587b726f..3df4d00f60c 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -14,6 +14,7 @@ use marker::{Sized, MarkerTrait}; 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 {} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index a08de58f909..89a8625856c 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -321,7 +321,6 @@ lets_do_this! { ExchangeHeapLangItem, "exchange_heap", exchange_heap; OwnedBoxLangItem, "owned_box", owned_box; - PhantomFnItem, "phantom_fn", phantom_fn; PhantomDataItem, "phantom_data", phantom_data; // Deprecated: diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index af6bb4ccccd..a2ff86cd065 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -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(..) | diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f7e7d071f8c..ad7d96c652d 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -836,14 +836,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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. diff --git a/src/librustc/middle/ty_relate/mod.rs b/src/librustc/middle/ty_relate/mod.rs index 1205b7d9579..3a55a64314e 100644 --- a/src/librustc/middle/ty_relate/mod.rs +++ b/src/librustc/middle/ty_relate/mod.rs @@ -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 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> { } } -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 @@ impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Box<T> /////////////////////////////////////////////////////////////////////////// // 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) diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index a86e2b17c93..eb06caf7d5a 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -117,15 +117,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { 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 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { 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 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { 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 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { 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 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { 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( diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index b83d8fc6af7..da2de731d64 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -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`). +//! +//! 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 algorithm +//! +//! 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. +//! +//! ### Addendum: Variance on traits //! -//! ### 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. //! -//! 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. +//! Just for historical reference,I am going to preserve some text indicating +//! how one could interpret variance and trait matching. //! -//! #### Trait variance and object types +//! #### Variance and object types //! -//! 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 +//! 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. -//! -//! 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. +//! 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. //! -//! *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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { 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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { 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 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - 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, diff --git a/src/test/auxiliary/coherence_copy_like_lib.rs b/src/test/auxiliary/coherence_copy_like_lib.rs index a1e1b48c2c4..d3d389c6a8b 100644 --- a/src/test/auxiliary/coherence_copy_like_lib.rs +++ b/src/test/auxiliary/coherence_copy_like_lib.rs @@ -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); diff --git a/src/test/auxiliary/coherence_orphan_lib.rs b/src/test/auxiliary/coherence_orphan_lib.rs index 93d8fd3da88..b22d12300c7 100644 --- a/src/test/auxiliary/coherence_orphan_lib.rs +++ b/src/test/auxiliary/coherence_orphan_lib.rs @@ -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); } diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index 72dfc75f41b..d195bd7e77b 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -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 @@ extern fn stack_exhausted() {} extern fn eh_personality() {} #[lang="copy"] -pub trait Copy : PhantomFn<Self> { +pub trait Copy { // Empty. } diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 04170779ed2..0e083e47236 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -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. } diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs index f13175ce8e2..fcd6e5c4952 100644 --- a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs +++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs @@ -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 diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs index ae3d242af70..b5c0a7fb5f5 100644 --- a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs +++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs @@ -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 diff --git a/src/test/compile-fail/issue-13853-2.rs b/src/test/compile-fail/issue-13853-2.rs index dc697e4784f..ea0d880f4a1 100644 --- a/src/test/compile-fail/issue-13853-2.rs +++ b/src/test/compile-fail/issue-13853-2.rs @@ -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); } diff --git a/src/test/compile-fail/issue-19660.rs b/src/test/compile-fail/issue-19660.rs index 4435ee0cb22..a4a8eac682d 100644 --- a/src/test/compile-fail/issue-19660.rs +++ b/src/test/compile-fail/issue-19660.rs @@ -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 { diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs index 71494fd5f38..d4ee93e9ca5 100644 --- a/src/test/compile-fail/kindck-impl-type-params.rs +++ b/src/test/compile-fail/kindck-impl-type-params.rs @@ -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>() { diff --git a/src/test/compile-fail/lint-unsafe-code.rs b/src/test/compile-fail/lint-unsafe-code.rs index 8440cf3a88e..10f245aaaf9 100644 --- a/src/test/compile-fail/lint-unsafe-code.rs +++ b/src/test/compile-fail/lint-unsafe-code.rs @@ -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 { diff --git a/src/test/compile-fail/object-safety-phantom-fn.rs b/src/test/compile-fail/object-safety-phantom-fn.rs index 1c95ee43d27..518c45ac9df 100644 --- a/src/test/compile-fail/object-safety-phantom-fn.rs +++ b/src/test/compile-fail/object-safety-phantom-fn.rs @@ -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> { diff --git a/src/test/compile-fail/on-unimplemented-bad-anno.rs b/src/test/compile-fail/on-unimplemented-bad-anno.rs index 7538b1c85e5..8580749084d 100644 --- a/src/test/compile-fail/on-unimplemented-bad-anno.rs +++ b/src/test/compile-fail/on-unimplemented-bad-anno.rs @@ -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() { diff --git a/src/test/compile-fail/on-unimplemented.rs b/src/test/compile-fail/on-unimplemented.rs index 2447d086422..c4eb467c4f9 100644 --- a/src/test/compile-fail/on-unimplemented.rs +++ b/src/test/compile-fail/on-unimplemented.rs @@ -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 { diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 67dccb4c93e..f728fdfaf9a 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -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 diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index adce93af079..bcb46663aa8 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -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. diff --git a/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs index 6aa0cc003ce..9a13541bd0b 100644 --- a/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs +++ b/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs @@ -15,11 +15,9 @@ #![allow(dead_code)] -use std::marker::PhantomFn; - /////////////////////////////////////////////////////////////////////////// -pub trait TheTrait: PhantomFn<Self, Self> { +pub trait TheTrait { type TheAssocType; } diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs b/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs index 9736910d7b5..0d3d2e296be 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs +++ b/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs @@ -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; } diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs b/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs index da7546ce21c..2ceaea98d27 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs +++ b/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs @@ -15,11 +15,9 @@ #![allow(dead_code)] -use std::marker::PhantomFn; - /////////////////////////////////////////////////////////////////////////// -pub trait TheTrait: PhantomFn<Self, Self> { +pub trait TheTrait { type TheAssocType; } diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container.rs b/src/test/compile-fail/regions-assoc-type-outlives-container.rs index e1e72e6f56e..e3e57ff1711 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container.rs +++ b/src/test/compile-fail/regions-assoc-type-outlives-container.rs @@ -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; } diff --git a/src/test/compile-fail/regions-close-object-into-object-1.rs b/src/test/compile-fail/regions-close-object-into-object-1.rs index 4c831a2b659..5472e09ba4b 100644 --- a/src/test/compile-fail/regions-close-object-into-object-1.rs +++ b/src/test/compile-fail/regions-close-object-into-object-1.rs @@ -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> {} diff --git a/src/test/compile-fail/regions-close-object-into-object-2.rs b/src/test/compile-fail/regions-close-object-into-object-2.rs index 6de49020a6f..1ef000852d5 100644 --- a/src/test/compile-fail/regions-close-object-into-object-2.rs +++ b/src/test/compile-fail/regions-close-object-into-object-2.rs @@ -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> { diff --git a/src/test/compile-fail/regions-close-object-into-object-3.rs b/src/test/compile-fail/regions-close-object-into-object-3.rs index b723efff3c9..b7dc759b271 100644 --- a/src/test/compile-fail/regions-close-object-into-object-3.rs +++ b/src/test/compile-fail/regions-close-object-into-object-3.rs @@ -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 } diff --git a/src/test/compile-fail/regions-close-object-into-object-4.rs b/src/test/compile-fail/regions-close-object-into-object-4.rs index 9b311588bb1..247578d253e 100644 --- a/src/test/compile-fail/regions-close-object-into-object-4.rs +++ b/src/test/compile-fail/regions-close-object-into-object-4.rs @@ -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> { diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index 1b749faf1b8..bb80c763a8b 100644 --- a/src/test/compile-fail/required-lang-item.rs +++ b/src/test/compile-fail/required-lang-item.rs @@ -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 diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs index 34e06cc9365..a2369f8ffb4 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs @@ -13,8 +13,7 @@ use std::marker; -trait A : marker::PhantomFn<Self> { -} +trait A { } trait B: A {} diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs index 217540415a7..beabdcea2bb 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs @@ -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>; } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index 6d315c1b7a9..dc5576aee65 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -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>>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs index bd3530e6e30..a6f59b78823 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -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>>() { } diff --git a/src/test/compile-fail/variance-contravariant-arg-object.rs b/src/test/compile-fail/variance-contravariant-arg-object.rs index 3330e1d0d51..1795ac95358 100644 --- a/src/test/compile-fail/variance-contravariant-arg-object.rs +++ b/src/test/compile-fail/variance-contravariant-arg-object.rs @@ -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() { } diff --git a/src/test/compile-fail/variance-contravariant-arg-trait-match.rs b/src/test/compile-fail/variance-contravariant-arg-trait-match.rs index caaad4014ad..9b6e3c9de3b 100644 --- a/src/test/compile-fail/variance-contravariant-arg-trait-match.rs +++ b/src/test/compile-fail/variance-contravariant-arg-trait-match.rs @@ -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> { } diff --git a/src/test/compile-fail/variance-contravariant-self-trait-match.rs b/src/test/compile-fail/variance-contravariant-self-trait-match.rs index 013511ed517..6d9d1e61fed 100644 --- a/src/test/compile-fail/variance-contravariant-self-trait-match.rs +++ b/src/test/compile-fail/variance-contravariant-self-trait-match.rs @@ -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 { } diff --git a/src/test/compile-fail/variance-covariant-arg-object.rs b/src/test/compile-fail/variance-covariant-arg-object.rs index 828c987c082..ad059a467f5 100644 --- a/src/test/compile-fail/variance-covariant-arg-object.rs +++ b/src/test/compile-fail/variance-covariant-arg-object.rs @@ -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>>) diff --git a/src/test/compile-fail/variance-covariant-arg-trait-match.rs b/src/test/compile-fail/variance-covariant-arg-trait-match.rs index 17761b9c0b1..c42a845b3b5 100644 --- a/src/test/compile-fail/variance-covariant-arg-trait-match.rs +++ b/src/test/compile-fail/variance-covariant-arg-trait-match.rs @@ -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>() diff --git a/src/test/compile-fail/variance-covariant-self-trait-match.rs b/src/test/compile-fail/variance-covariant-self-trait-match.rs index 4e94a3eeb46..25148dfc020 100644 --- a/src/test/compile-fail/variance-covariant-self-trait-match.rs +++ b/src/test/compile-fail/variance-covariant-self-trait-match.rs @@ -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>() diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs index 96ae201f6ae..dfa5dc14441 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -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; } diff --git a/src/test/compile-fail/variance-regions-unused-direct.rs b/src/test/compile-fail/variance-regions-unused-direct.rs index 396e7765206..037fff72c80 100644 --- a/src/test/compile-fail/variance-regions-unused-direct.rs +++ b/src/test/compile-fail/variance-regions-unused-direct.rs @@ -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); } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 88b50058b65..222d8338aa2 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -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 @@ enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[*, +];[];[]] } #[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); } diff --git a/src/test/compile-fail/variance-trait-matching.rs b/src/test/compile-fail/variance-trait-matching.rs index ec020f18818..49dc1e68c22 100644 --- a/src/test/compile-fail/variance-trait-matching.rs +++ b/src/test/compile-fail/variance-trait-matching.rs @@ -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; +} + +struct Cloner<T:Clone> { + t: T } -impl<'a> Make<'a> for &'a mut isize { - fn make(x: &'a mut isize) -> &'a mut isize { - x +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); +} diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index d53e4cd7610..a02f20656e7 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -37,12 +37,12 @@ struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[o, o];[];[]] } #[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 @@ trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]] } #[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 @@ trait GetterInTypeBound<A> { //~ ERROR types=[[-];[-];[]] } #[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>, } diff --git a/src/test/compile-fail/variance-unused-region-param.rs b/src/test/compile-fail/variance-unused-region-param.rs index 5f504226370..407282e5ce0 100644 --- a/src/test/compile-fail/variance-unused-region-param.rs +++ b/src/test/compile-fail/variance-unused-region-param.rs @@ -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() {} diff --git a/src/test/compile-fail/variance-unused-type-param.rs b/src/test/compile-fail/variance-unused-type-param.rs index 2e867ec3c93..862d842d62c 100644 --- a/src/test/compile-fail/variance-unused-type-param.rs +++ b/src/test/compile-fail/variance-unused-type-param.rs @@ -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 diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index f418d5d1fb7..563fe79e537 100644 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -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 { diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index b13c41be559..9dbae193388 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -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 } diff --git a/src/test/compile-fail/coherence-subtyping.rs b/src/test/run-pass/coherence-subtyping.rs index 897cb083f84..082a39f5631 100644 --- a/src/test/compile-fail/coherence-subtyping.rs +++ b/src/test/run-pass/coherence-subtyping.rs @@ -16,7 +16,6 @@ trait Contravariant { } 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 @@ trait Covariant { } 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) { diff --git a/src/test/run-pass/coherence_copy_like.rs b/src/test/run-pass/coherence_copy_like.rs index db9893613ad..71db5225ecc 100644 --- a/src/test/run-pass/coherence_copy_like.rs +++ b/src/test/run-pass/coherence_copy_like.rs @@ -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 { } diff --git a/src/test/run-pass/cycle-generic-bound.rs b/src/test/run-pass/cycle-generic-bound.rs index 94e4665bb86..86b41284cdf 100644 --- a/src/test/run-pass/cycle-generic-bound.rs +++ b/src/test/run-pass/cycle-generic-bound.rs @@ -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() { } diff --git a/src/test/run-pass/issue-22356.rs b/src/test/run-pass/issue-22356.rs index a54490386d0..51a871d59b3 100644 --- a/src/test/run-pass/issue-22356.rs +++ b/src/test/run-pass/issue-22356.rs @@ -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 @@ impl<D: Device, T> BufferHandle<D, T> { pub type RawBufferHandle<D: Device> = Handle<<D as Device>::Buffer, String>; -pub trait Device: PhantomFn<Self> { +pub trait Device { type Buffer; } diff --git a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs index 9aed9155124..0ffbc432aae 100644 --- a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs +++ b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs @@ -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; } diff --git a/src/test/run-pass/traits-conditional-dispatch.rs b/src/test/run-pass/traits-conditional-dispatch.rs index 0190b7b7b96..0a6b9da74f2 100644 --- a/src/test/run-pass/traits-conditional-dispatch.rs +++ b/src/test/run-pass/traits-conditional-dispatch.rs @@ -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 } } diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index 8ff8169ef49..449d6b37e9f 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -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> {} diff --git a/src/test/run-pass/variance-trait-matching.rs b/src/test/run-pass/variance-trait-matching.rs deleted file mode 100644 index 5a179bfc7d4..00000000000 --- a/src/test/run-pass/variance-trait-matching.rs +++ /dev/null @@ -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); -} diff --git a/src/test/run-pass/where-for-self.rs b/src/test/run-pass/where-for-self.rs index 8535d76d471..eb95b13d3fa 100644 --- a/src/test/run-pass/where-for-self.rs +++ b/src/test/run-pass/where-for-self.rs @@ -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); } |
