Auto merge of #39075 - est31:remove_reflect, r=nikomatsakis
Remove Reflect PR for removing the `Reflect` trait. Opened so that a crater run can be done for testing the impact: https://github.com/rust-lang/rust/issues/27749#issuecomment-272665163 Fixes #27749
This commit is contained in:
commit
5158501367
@ -82,7 +82,6 @@
|
||||
#![feature(no_core)]
|
||||
#![feature(on_unimplemented)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(reflect)]
|
||||
#![feature(unwind_attributes)]
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
@ -553,59 +553,3 @@ mod impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
||||
}
|
||||
|
||||
/// Types that can be reflected over.
|
||||
///
|
||||
/// By "reflection" we mean use of the [`Any`][any] trait, or related
|
||||
/// machinery such as [`TypeId`][typeid].
|
||||
///
|
||||
/// `Reflect` is implemented for all types. Its purpose is to ensure
|
||||
/// that when you write a generic function that will employ reflection,
|
||||
/// that must be reflected (no pun intended) in the generic bounds of
|
||||
/// that function.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(reflect_marker)]
|
||||
/// use std::marker::Reflect;
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
/// fn foo<T: Reflect + 'static>(x: &T) {
|
||||
/// let any: &Any = x;
|
||||
/// if any.is::<u32>() { println!("u32"); }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Without the bound `T: Reflect`, `foo` would not typecheck. (As
|
||||
/// a matter of style, it would be preferable to write `T: Any`,
|
||||
/// because `T: Any` implies `T: Reflect` and `T: 'static`, but we
|
||||
/// use `Reflect` here for illustrative purposes.)
|
||||
///
|
||||
/// The `Reflect` bound serves to alert `foo`'s caller to the
|
||||
/// fact that `foo` may behave differently depending on whether
|
||||
/// `T` is `u32` or not. The ability for a caller to reason about what
|
||||
/// a function may do based solely on what generic bounds are declared
|
||||
/// is often called the "[parametricity property][param]". Despite the
|
||||
/// use of `Reflect`, Rust lacks true parametricity because a generic
|
||||
/// function can, at the very least, call [`mem::size_of`][size_of]
|
||||
/// without employing any trait bounds whatsoever.
|
||||
///
|
||||
/// [any]: ../any/trait.Any.html
|
||||
/// [typeid]: ../any/struct.TypeId.html
|
||||
/// [param]: http://en.wikipedia.org/wiki/Parametricity
|
||||
/// [size_of]: ../mem/fn.size_of.html
|
||||
#[rustc_reflect_like]
|
||||
#[unstable(feature = "reflect_marker",
|
||||
reason = "requires RFC and more experience",
|
||||
issue = "27749")]
|
||||
#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")]
|
||||
#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
|
||||
ensure all type parameters are bounded by `Any`"]
|
||||
pub trait Reflect {}
|
||||
|
||||
#[unstable(feature = "reflect_marker",
|
||||
reason = "requires RFC and more experience",
|
||||
issue = "27749")]
|
||||
#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")]
|
||||
#[allow(deprecated)]
|
||||
impl Reflect for .. { }
|
||||
|
@ -204,7 +204,6 @@ enum SelectionCandidate<'tcx> {
|
||||
ParamCandidate(ty::PolyTraitRef<'tcx>),
|
||||
ImplCandidate(DefId),
|
||||
DefaultImplCandidate(DefId),
|
||||
DefaultImplObjectCandidate(DefId),
|
||||
|
||||
/// This is a trait matching with a projected type as `Self`, and
|
||||
/// we found an applicable bound in the trait definition.
|
||||
@ -237,9 +236,6 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
|
||||
}
|
||||
ImplCandidate(def_id) => ImplCandidate(def_id),
|
||||
DefaultImplCandidate(def_id) => DefaultImplCandidate(def_id),
|
||||
DefaultImplObjectCandidate(def_id) => {
|
||||
DefaultImplObjectCandidate(def_id)
|
||||
}
|
||||
ProjectionCandidate => ProjectionCandidate,
|
||||
FnPointerCandidate => FnPointerCandidate,
|
||||
ObjectCandidate => ObjectCandidate,
|
||||
@ -1431,17 +1427,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
match self_ty.sty {
|
||||
ty::TyDynamic(..) => {
|
||||
// For object types, we don't know what the closed
|
||||
// over types are. For most traits, this means we
|
||||
// conservatively say nothing; a candidate may be
|
||||
// added by `assemble_candidates_from_object_ty`.
|
||||
// However, for the kind of magic reflect trait,
|
||||
// we consider it to be implemented even for
|
||||
// object types, because it just lets you reflect
|
||||
// onto the object type, not into the object's
|
||||
// interior.
|
||||
if self.tcx().has_attr(def_id, "rustc_reflect_like") {
|
||||
candidates.vec.push(DefaultImplObjectCandidate(def_id));
|
||||
}
|
||||
// over types are. This means we conservatively
|
||||
// say nothing; a candidate may be added by
|
||||
// `assemble_candidates_from_object_ty`.
|
||||
}
|
||||
ty::TyParam(..) |
|
||||
ty::TyProjection(..) |
|
||||
@ -1671,7 +1659,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
FnPointerCandidate |
|
||||
BuiltinObjectCandidate |
|
||||
BuiltinUnsizeCandidate |
|
||||
DefaultImplObjectCandidate(..) |
|
||||
BuiltinCandidate { .. } => {
|
||||
// We have a where-clause so don't go around looking
|
||||
// for impls.
|
||||
@ -1998,11 +1985,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
Ok(VtableDefaultImpl(data))
|
||||
}
|
||||
|
||||
DefaultImplObjectCandidate(trait_def_id) => {
|
||||
let data = self.confirm_default_impl_object_candidate(obligation, trait_def_id);
|
||||
Ok(VtableDefaultImpl(data))
|
||||
}
|
||||
|
||||
ImplCandidate(impl_def_id) => {
|
||||
Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
|
||||
}
|
||||
@ -2138,42 +2120,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types))
|
||||
}
|
||||
|
||||
fn confirm_default_impl_object_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
trait_def_id: DefId)
|
||||
-> VtableDefaultImplData<PredicateObligation<'tcx>>
|
||||
{
|
||||
debug!("confirm_default_impl_object_candidate({:?}, {:?})",
|
||||
obligation,
|
||||
trait_def_id);
|
||||
|
||||
assert!(self.tcx().has_attr(trait_def_id, "rustc_reflect_like"));
|
||||
|
||||
// OK to skip binder, it is reintroduced below
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
|
||||
match self_ty.sty {
|
||||
ty::TyDynamic(ref data, ..) => {
|
||||
// OK to skip the binder, it is reintroduced below
|
||||
let principal = data.principal().unwrap();
|
||||
let input_types = principal.input_types();
|
||||
let assoc_types = data.projection_bounds()
|
||||
.map(|pb| pb.skip_binder().ty);
|
||||
let all_types: Vec<_> = input_types.chain(assoc_types)
|
||||
.collect();
|
||||
|
||||
// reintroduce the two binding levels we skipped, then flatten into one
|
||||
let all_types = ty::Binder(ty::Binder(all_types));
|
||||
let all_types = self.tcx().flatten_late_bound_regions(&all_types);
|
||||
|
||||
self.vtable_default_impl(obligation, trait_def_id, all_types)
|
||||
}
|
||||
_ => {
|
||||
bug!("asked to confirm default object implementation for non-object type: {:?}",
|
||||
self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See `confirm_default_impl_candidate`
|
||||
fn vtable_default_impl(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
|
@ -124,7 +124,6 @@ declare_features! (
|
||||
(active, advanced_slice_patterns, "1.0.0", Some(23121)),
|
||||
(active, box_syntax, "1.0.0", Some(27779)),
|
||||
(active, placement_in_syntax, "1.0.0", Some(27779)),
|
||||
(active, reflect, "1.0.0", Some(27749)),
|
||||
(active, unboxed_closures, "1.0.0", Some(29625)),
|
||||
|
||||
(active, allocator, "1.0.0", Some(27389)),
|
||||
@ -337,6 +336,7 @@ declare_features! (
|
||||
(removed, managed_boxes, "1.0.0", None),
|
||||
// Allows use of unary negate on unsigned integers, e.g. -e for e: u8
|
||||
(removed, negate_unsigned, "1.0.0", Some(29645)),
|
||||
(removed, reflect, "1.0.0", Some(27749)),
|
||||
// A way to temporarily opt out of opt in copy. This will *never* be accepted.
|
||||
(removed, opt_out_copy, "1.0.0", None),
|
||||
(removed, quad_precision_float, "1.0.0", None),
|
||||
@ -734,10 +734,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
||||
"unboxed_closures",
|
||||
"unboxed_closures are still evolving",
|
||||
cfg_fn!(unboxed_closures))),
|
||||
("rustc_reflect_like", Whitelisted, Gated(Stability::Unstable,
|
||||
"reflect",
|
||||
"defining reflective traits is still evolving",
|
||||
cfg_fn!(reflect))),
|
||||
|
||||
("windows_subsystem", Whitelisted, Gated(Stability::Unstable,
|
||||
"windows_subsystem",
|
||||
|
@ -1,37 +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.
|
||||
|
||||
#![feature(reflect_marker)]
|
||||
|
||||
// Test that types that appear in assoc bindings in an object
|
||||
// type are subject to the reflect check.
|
||||
|
||||
use std::marker::Reflect;
|
||||
use std::io::Write;
|
||||
|
||||
trait Get {
|
||||
type Output;
|
||||
fn get(self) -> Self::Output;
|
||||
}
|
||||
|
||||
struct Struct<T>(T);
|
||||
|
||||
fn is_reflect<T:Reflect>() { }
|
||||
|
||||
fn a<T>() {
|
||||
is_reflect::<Box<Get<Output=T>>>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn ok_a<T: Reflect>() {
|
||||
is_reflect::<Box<Get<Output=T>>>(); // OK
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -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.
|
||||
|
||||
#![feature(reflect_marker)]
|
||||
|
||||
// Test that types that appear in input types in an object type are
|
||||
// subject to the reflect check.
|
||||
|
||||
use std::marker::Reflect;
|
||||
use std::io::Write;
|
||||
|
||||
trait Get<T> {
|
||||
fn get(self) -> T;
|
||||
}
|
||||
|
||||
struct Struct<T>(T);
|
||||
|
||||
fn is_reflect<T:Reflect>() { }
|
||||
|
||||
fn a<T>() {
|
||||
is_reflect::<T>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn ok_a<T: Reflect>() {
|
||||
is_reflect::<T>(); // OK
|
||||
}
|
||||
|
||||
fn b<T>() {
|
||||
is_reflect::<Box<Get<T>>>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn ok_b<T: Reflect>() {
|
||||
is_reflect::<Box<Get<T>>>(); // OK
|
||||
}
|
||||
|
||||
fn c<T>() {
|
||||
is_reflect::<Box<Get<Struct<T>>>>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn main() {
|
||||
is_reflect::<Box<Get<Struct<()>>>>(); // OK
|
||||
}
|
@ -1,41 +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.
|
||||
|
||||
#![feature(reflect_marker)]
|
||||
|
||||
// Test that there is no way to get a generic type `T` to be
|
||||
// considered as `Reflect` (or accessible via something that is
|
||||
// considered `Reflect`) without a reflect bound, but that any
|
||||
// concrete type works fine. Note that object types are tested
|
||||
// separately.
|
||||
|
||||
use std::marker::Reflect;
|
||||
use std::io::Write;
|
||||
|
||||
struct Struct<T>(T);
|
||||
|
||||
fn is_reflect<T:Reflect>() { }
|
||||
|
||||
fn c<T>() {
|
||||
is_reflect::<Struct<T>>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn ok_c<T: Reflect>() {
|
||||
is_reflect::<Struct<T>>(); // OK
|
||||
}
|
||||
|
||||
fn d<T>() {
|
||||
is_reflect::<(i32, T)>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn main() {
|
||||
is_reflect::<&i32>(); // OK
|
||||
is_reflect::<Box<Write>>(); // OK
|
||||
}
|
@ -167,7 +167,7 @@ pub fn check(path: &Path, bad: &mut bool) {
|
||||
// FIXME get this whitelist empty.
|
||||
let whitelist = vec![
|
||||
"abi_ptx", "simd", "macro_reexport",
|
||||
"static_recursion", "reflect", "quote",
|
||||
"static_recursion", "quote",
|
||||
"cfg_target_has_atomic", "staged_api", "const_indexing",
|
||||
"unboxed_closures", "stmt_expr_attributes",
|
||||
"cfg_target_thread_local", "unwind_attributes",
|
||||
|
Loading…
x
Reference in New Issue
Block a user