Skip to content

Commit

Permalink
Auto merge of #23938 - nikomatsakis:invariant, r=pnkfelix
Browse files Browse the repository at this point in the history
There are still some remnants we could remove from the compiler (e.g. references to "subtraitrefs"; traits still have variance entries in the variance table), but this removes all user-visible bits I believe.

r? @pnkfelix 

Fixes #22806 (since such traits would no longer exist)
  • Loading branch information
bors committed Apr 3, 2015
2 parents 82dcec7 + c2dba85 commit 2615106
Show file tree
Hide file tree
Showing 61 changed files with 332 additions and 583 deletions.
5 changes: 4 additions & 1 deletion src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
107 changes: 34 additions & 73 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
Expand All @@ -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.
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
}

Expand Down
1 change: 1 addition & 0 deletions src/libcore/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
9 changes: 4 additions & 5 deletions src/librustc/middle/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down
8 changes: 0 additions & 8 deletions src/librustc/middle/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
36 changes: 18 additions & 18 deletions src/librustc/middle/ty_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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)
Expand Down
42 changes: 7 additions & 35 deletions src/librustc_typeck/check/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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<_> =
Expand All @@ -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() {
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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(
Expand Down
Loading

0 comments on commit 2615106

Please sign in to comment.