diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 7843be0b483eb..3f85af9719778 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 AllTypes for T { } + unsafe fn get_tydesc() -> *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 619f983aee071..352f7d869774c 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 { } -// ~~~~~ <-- 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 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`. -/// -/// # 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 { } -/// ``` -/// -/// 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 { } +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "No longer needed")] +#[cfg(stage0)] +pub trait PhantomFn { +} + +/// `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 { +} + +#[allow(deprecated)] +#[cfg(not(stage0))] +impl PhantomFn for T { } /// `PhantomData` 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 230587b726fd1..3df4d00f60cc4 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 Zeroable for *const T {} diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index a08de58f909d3..89a8625856c2c 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 af6bb4ccccd80..a2ff86cd06590 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 f7e7d071f8ca4..ad7d96c652d9b 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 1205b7d957930..3a55a64314ed9 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>> +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>> 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>> +fn relate_arg_vecs<'a,'tcx:'a,R>(relation: &mut R, + a_args: &[Ty<'tcx>], + b_args: &[Ty<'tcx>]) + -> RelateResult<'tcx, Vec>> 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 /////////////////////////////////////////////////////////////////////////// // Error handling -pub fn expected_found<'a,'tcx,R,T>(relation: &mut R, - a: &T, - b: &T) - -> ty::expected_found +pub fn expected_found<'a,'tcx:'a,R,T>(relation: &mut R, + a: &T, + b: &T) + -> ty::expected_found 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 a86e2b17c93b8..eb06caf7d5a63 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) - { - 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) + 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 b83d8fc6af7fa..da2de731d648a 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` is a subtype of `T` //! (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 { Some(A), None } +//! enum OptionalFn { Some(|B|), None } +//! enum OptionalMap { 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` is `V3 = V1.xform(V2)`. +//! +//! ### Constraints +//! +//! If I have a struct or enum with where clauses: +//! +//! struct Foo { ... } +//! +//! 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` that is upcast to `Foo`, 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` 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::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` -//! and `&Trait` 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` and `&Trait` +//! 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 { Some(A), None } -//! enum OptionalFn { Some(|B|), None } -//! enum OptionalMap { 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` is `V3 = V1.xform(V2)`. -//! -//! ### Constraints -//! -//! If I have a struct or enum with where clauses: -//! -//! struct Foo { ... } -//! -//! 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` that is upcast to `Foo`, 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` 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: //! //! <: //! -//! 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 `` is safe -//! to use where a dictionary for `` is expected. -//! -//! The problem is that when you can -//! project types out from ``, -//! the relationship to types projected out -//! of `` 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 `` is safe to use where +//! a dictionary for `` 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 ``, the relationship to types projected out of `` +//! 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)> { 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 a1e1b48c2c4e9..d3d389c6a8bd5 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); diff --git a/src/test/auxiliary/coherence_orphan_lib.rs b/src/test/auxiliary/coherence_orphan_lib.rs index 93d8fd3da88fb..b22d12300c7d1 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 : ::std::marker::PhantomFn { +pub trait TheTrait { fn the_fn(&self); } diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index 72dfc75f41b96..d195bd7e77bd8 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 { } -impl PhantomFn for U { } - #[lang="sized"] -pub trait Sized : PhantomFn {} +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 { +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 04170779ed2f6..0e083e4723634 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 { } -impl PhantomFn for U { } - #[lang="sized"] -pub trait Sized : PhantomFn { +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 f13175ce8e2a4..fcd6e5c495207 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 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 ae3d242af705e..b5c0a7fb5f564 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 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 dc697e4784f85..ea0d880f4a1cc 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 4435ee0cb225d..a4a8eac682dc3 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 { } -impl PhantomFn for U { } - #[lang = "sized"] -trait Sized : PhantomFn {} +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 71494fd5f38dc..d4ee93e9ca5d6 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(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 8440cf3a88e10..10f245aaaf9d7 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 {} + 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 {} //~ 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 1c95ee43d27af..518c45ac9dff6 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 { +trait Baz { } -trait Bar : PhantomFn<(Self, T)> { +trait Bar { } fn make_bar>(t: &T) -> &Bar { diff --git a/src/test/compile-fail/on-unimplemented-bad-anno.rs b/src/test/compile-fail/on-unimplemented-bad-anno.rs index 7538b1c85e533..8580749084d22 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 - : 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 { #[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 - : 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 - : 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 2447d0864226a..c4eb467c4f961 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 - : marker::PhantomFn<(Self,Bar,Baz,Quux)> {} fn foobar>() -> T { diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 67dccb4c93e1a..f728fdfaf9a80 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 { } -impl PhantomFn for U { } - #[lang="sized"] -pub trait Sized : PhantomFn {} +pub trait Sized {} #[lang="copy"] -pub trait Copy : PhantomFn {} +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 adce93af0794f..bcb46663aa849 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 { } -impl PhantomFn for U { } - -#[lang = "sized"] pub trait Sized : PhantomFn {} -#[lang="copy"] pub trait Copy : PhantomFn {} +#[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 6aa0cc003ce64..9a13541bd0b17 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 { +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 9736910d7b5fe..0d3d2e296bec6 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 da7546ce21c60..2ceaea98d2797 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 { +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 e1e72e6f56e93..e3e57ff17115c 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 { +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 4c831a2b65953..5472e09ba4be4 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 : PhantomFn<(Self,T)> { } +trait A { } struct B<'a, T>(&'a (A+'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 6de49020a6fbb..1ef000852d561 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 : PhantomFn<(Self,T)> { } +trait A { } struct B<'a, T>(&'a (A+'a)); -trait X : PhantomFn {} +trait X { } impl<'a, T> X for B<'a, T> {} fn g<'a, T: 'static>(v: Box+'a>) -> Box { 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 b723efff3c902..b7dc759b2717f 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 : PhantomFn<(Self,T)> {} +trait A { } struct B<'a, T>(&'a (A+'a)); -trait X : PhantomFn {} +trait X { } impl<'a, T> X for B<'a, T> {} -fn h<'a, T, U>(v: Box+'static>) -> Box { +fn h<'a, T, U:'static>(v: Box+'static>) -> Box { box B(&*v) as Box //~ 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 9b311588bb1ea..247578d253ea0 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 : PhantomFn<(Self,T)> {} +trait A { } struct B<'a, T>(&'a (A+'a)); -trait X : PhantomFn {} +trait X { } impl<'a, T> X for B<'a, T> {} fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index 1b749faf1b8b9..bb80c763a8b39 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 { } -impl PhantomFn for U { } - -#[lang="sized"] pub trait Sized : PhantomFn {} +#[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 34e06cc93658a..a2369f8ffb4f2 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 { -} +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 217540415a7dd..beabdcea2bbe9 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 { } trait IteratorUtil - : ::std::marker::PhantomFn<(),A> { fn zip>(self, other: U) -> ZipIterator; } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index 6d315c1b7a996..dc5576aee650a 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 { type Output; fn dummy(&self, t: T, u: Self::Output); } -trait Eq : PhantomFn<(Self,X)> { } +trait Eq { } impl Eq for X { } fn eq>() { } 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 bd3530e6e3026..a6f59b7882344 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 { fn dummy(&self, t: T); } -trait Eq : marker::PhantomFn<(Self, X)> { } +trait Eq { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/variance-contravariant-arg-object.rs b/src/test/compile-fail/variance-contravariant-arg-object.rs index 3330e1d0d51b0..1795ac95358d7 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 : 'static { fn get(&self, t: T); } @@ -25,7 +28,8 @@ fn get_max_from_min<'min, 'max, G>(v: Box>) -> Box> 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 caaad4014adfa..9b6e3c9de3bbd 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 { 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::() + // Previously OK, but now an error because traits are invariant: + + impls_get::() //~ ERROR mismatched types } fn impls_get() where G : Get { } 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 013511ed517a8..6d9d1e61fed61 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() 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 828c987c08212..ad059a467f570 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 : 'static { fn get(&self) -> T; } @@ -18,7 +21,8 @@ fn get_min_from_max<'min, 'max>(v: Box>) -> Box> 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>) 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 17761b9c0b19e..c42a845b3b504 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 { fn get(&self) -> T; } @@ -17,7 +20,8 @@ trait Get { fn get_min_from_max<'min, 'max, G>() where 'max : 'min, G : Get<&'max i32> { - impls_get::() + // Previously OK, now an error as traits are invariant. + impls_get::() //~ 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 4e94a3eeb46e6..25148dfc0208a 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 96ae201f6ae94..dfa5dc1444151 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 { //~ ERROR types=[[+];[-];[]] +trait Bar { //~ 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 396e77652067d..037fff72c8022 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 88b50058b6580..222d8338aa2c4 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 { //~ ERROR types=[[+];[-];[]] +trait Getter { //~ ERROR types=[[o];[o];[]] fn get(&self) -> T; } #[rustc_variance] -trait Setter { //~ ERROR types=[[-];[-];[]] +trait Setter { //~ ERROR types=[[o];[o];[]] fn get(&self, T); } @@ -37,16 +37,16 @@ enum TestEnum> {//~ ERROR types=[[*, +];[];[]] } #[rustc_variance] -trait TestTrait> { //~ ERROR types=[[-, +];[-];[]] +trait TestTrait> { //~ ERROR types=[[o, o];[o];[]] fn getter(&self, u: U) -> T; } #[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR types=[[+];[-];[]] +trait TestTrait2 : Getter { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -trait TestTrait3 { //~ ERROR types=[[-];[-];[]] +trait TestTrait3 { //~ ERROR types=[[o];[o];[]] fn getter>(&self); } diff --git a/src/test/compile-fail/variance-trait-matching.rs b/src/test/compile-fail/variance-trait-matching.rs index ec020f1881893..49dc1e68c221f 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 is covariant in T +trait Get { + fn get(&self) -> T; +} + +struct Cloner { + t: T } -impl<'a> Make<'a> for &'a mut isize { - fn make(x: &'a mut isize) -> &'a mut isize { - x +impl Get for Cloner { + 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 d53e4cd76105b..a02f20656e7b5 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 { //~ ERROR types=[[o, o];[];[]] } #[rustc_variance] -trait Getter { //~ ERROR types=[[+];[-];[]] +trait Getter { //~ ERROR types=[[o];[o];[]] fn get(&self) -> A; } #[rustc_variance] -trait Setter { //~ ERROR types=[[-];[o];[]] +trait Setter { //~ ERROR types=[[o];[o];[]] fn set(&mut self, a: A); } @@ -53,7 +53,7 @@ trait GetterSetter { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -trait GetterInTypeBound { //~ ERROR types=[[-];[-];[]] +trait GetterInTypeBound { //~ 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`. Since this dictionary is an input, it is @@ -63,12 +63,12 @@ trait GetterInTypeBound { //~ ERROR types=[[-];[-];[]] } #[rustc_variance] -trait SetterInTypeBound { //~ ERROR types=[[+];[-];[]] +trait SetterInTypeBound { //~ ERROR types=[[o];[o];[]] fn do_it>(&self); } #[rustc_variance] -struct TestObject { //~ ERROR types=[[-, +];[];[]] +struct TestObject { //~ ERROR types=[[o, o];[];[]] n: Box+Send>, m: Box+Send>, } diff --git a/src/test/compile-fail/variance-unused-region-param.rs b/src/test/compile-fail/variance-unused-region-param.rs index 5f504226370a4..407282e5ce0d4 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 2e867ec3c9384..862d842d62c23 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 { Nothing } //~^ ERROR parameter `A` is never used //~| HELP PhantomData -trait SomeTrait { fn foo(&self); } -//~^ ERROR parameter `A` is never used -//~| HELP PhantomFn - // Here T might *appear* used, but in fact it isn't. enum ListCell { //~^ 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 f418d5d1fb74f..563fe79e53732 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 {} +pub trait Sized { } #[lang = "copy"] -pub trait Copy : PhantomFn {} - -#[lang="phantom_fn"] -pub trait PhantomFn { } -impl PhantomFn 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 b13c41be55971..9dbae19338809 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 { } -impl PhantomFn for U { } - #[lang="copy"] -trait Copy : PhantomFn { } +trait Copy { } #[lang="sized"] -trait Sized : PhantomFn { } +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 similarity index 94% rename from src/test/compile-fail/coherence-subtyping.rs rename to src/test/run-pass/coherence-subtyping.rs index 897cb083f849d..082a39f56312e 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 db9893613ad11..71db5225ecc08 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 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 94e4665bb86ab..86b41284cdf35 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> : PhantomFn<(Self,X)> { +trait Chromosome> { } fn main() { } diff --git a/src/test/run-pass/issue-22356.rs b/src/test/run-pass/issue-22356.rs index a54490386d0e7..51a871d59b361 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); @@ -34,7 +34,7 @@ impl BufferHandle { pub type RawBufferHandle = Handle<::Buffer, String>; -pub trait Device: PhantomFn { +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 9aed915512434..0ffbc432aaeb5 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 0190b7b7b9628..0a6b9da74f218 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 8ff8169ef497c..449d6b37e9f89 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 { } -pub trait T2 : PhantomFn { } -trait T3 : T2 + PhantomFn { } -trait T4 : PhantomFn<(Self,X)> {} -trait T5 : PhantomFn<(Self,X,Y)> {} -trait T6 : PhantomFn<(Self,X,Y)> {} -trait T7 : PhantomFn<(Self,X,Y)> {} -trait T8 : PhantomFn<(Self,X)> {} -trait T9 : PhantomFn<(Self,X)> {} +trait T1 { } +pub trait T2 { } +trait T3 : T2 { } +trait T4 { } +trait T5 { } +trait T6 { } +trait T7 { } +trait T8 { } +trait T9 { } struct S1(PhantomData); enum E { E1(PhantomData) } impl T1 for S1 {} 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 5a179bfc7d47f..0000000000000 --- 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 or the MIT license -// , 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 is covariant in T -trait Get { - fn get(&self) -> T; -} - -struct Cloner { - t: T -} - -impl Get for Cloner { - 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 8535d76d4714c..eb95b13d3fa5b 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); }