提交 5d4cce6c 编写于 作者: N Nick Cameron

Rebasing

上级 db1b14a1
......@@ -460,7 +460,6 @@ fn deref(&self) -> &T {
}
#[cfg(stage0)] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Rc<T> {
/// Drops the `Rc<T>`.
......@@ -512,7 +511,6 @@ fn drop(&mut self) {
}
#[cfg(not(stage0))] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Rc<T> {
/// Drops the `Rc<T>`.
......@@ -933,7 +931,6 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
}
#[cfg(stage0)] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.
......@@ -979,7 +976,6 @@ fn drop(&mut self) {
}
#[cfg(not(stage0))] // SNAP c64d671
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Weak<T> {
/// Drops the `Weak<T>`.
......
......@@ -707,5 +707,4 @@ pub fn get(&self) -> *mut T {
#![allow(trivial_casts)]
&self.value as *const T as *mut T
}
}
......@@ -1220,24 +1220,33 @@ pub trait CoerceUnsized<T> {
// Empty.
}
// &mut T -> &mut U
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
// &mut T -> &U
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
// &mut T -> *mut U
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
// &mut T -> *const U
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
// &T -> &U
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
// &T -> *const U
#[cfg(not(stage0))] // SNAP c64d671
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
// *mut T -> *mut U
#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
// *mut T -> *const U
#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
// *const T -> *const U
#[cfg(not(stage0))] // SNAP c64d671
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
......@@ -172,14 +172,15 @@ fn unsafe_cell_unsized() {
assert_eq!(unsafe { &mut *cell.get() }, comp);
}
#[test]
fn refcell_unsized() {
let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
{
let b = &mut *cell.borrow_mut();
b[0] = 4;
b[2] = 5;
}
let comp: &mut [i32] = &mut [4, 2, 5];
assert_eq!(&*cell.borrow(), comp);
}
// FIXME(#25351) needs deeply nested coercions of DST structs.
// #[test]
// fn refcell_unsized() {
// let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
// {
// let b = &mut *cell.borrow_mut();
// b[0] = 4;
// b[2] = 5;
// }
// let comp: &mut [i32] = &mut [4, 2, 5];
// assert_eq!(&*cell.borrow(), comp);
// }
......@@ -808,8 +808,6 @@ struct Foo<T: 'static> {
E0019,
E0022,
E0038,
E0079, // enum variant: expected signed integer constant
E0080, // enum variant: constant evaluation error
E0109,
E0110,
E0134,
......
......@@ -1369,7 +1369,8 @@ fn assemble_candidates_from_object_ty(&mut self,
fn assemble_candidates_for_unsizing(&mut self,
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>) {
// TODO is it Ok to skip the binder here?
// It is ok to skip past the higher-ranked binders here because the `match`
// below does not consider regions at all.
let source = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
......@@ -1494,7 +1495,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
&ClosureCandidate(..) |
&FnPointerCandidate(..) |
&BuiltinObjectCandidate(..) |
&&BuiltinUnsizeCandidate(..) |
&BuiltinUnsizeCandidate(..) |
&DefaultImplObjectCandidate(..) |
&BuiltinCandidate(..) => {
// We have a where-clause so don't go around looking
......@@ -2498,7 +2499,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
ty::lookup_field_type_unsubstituted(tcx, def_id, f.id)
}).collect::<Vec<_>>();
// The last field of the structure has to exist and be a
// FIXME(#25351) The last field of the structure has to exist and be a
// type parameter (for now, to avoid tracking edge cases).
let i = if let Some(&ty::ty_param(p)) = fields.last().map(|ty| &ty.sty) {
assert!(p.space == TypeSpace);
......
......@@ -377,7 +377,7 @@ pub fn predicate_for_trait_def<'tcx>(
let trait_ref = ty::TraitRef {
def_id: trait_def_id,
substs: tcx.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
});
};
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
}
......
......@@ -4420,7 +4420,7 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_uniq(ty) => ty,
ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
ty_rptr(_, mt) | ty_ptr(mt) => mt.ty,
_ => ty
}
}
......
......@@ -1058,6 +1058,7 @@ fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationRes
}
}
#[derive(Debug)]
enum MemberOffset {
FixedMemberOffset { bytes: usize },
// For ComputedMemberOffset, the offset is read from the llvm type definition.
......@@ -1066,6 +1067,7 @@ enum MemberOffset {
// Description of a type member, which can either be a regular field (as in
// structs or tuples) or an enum variant.
#[derive(Debug)]
struct MemberDescription {
name: String,
llvm_type: Type,
......@@ -1163,13 +1165,13 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
span: Span)
-> RecursiveTypeDescription<'tcx> {
let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
let struct_llvm_type = type_of::type_of(cx, struct_type);
let struct_llvm_type = type_of::in_memory_type_of(cx, struct_type);
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
let struct_metadata_stub = create_struct_stub(cx,
struct_llvm_type,
&struct_name[..],
&struct_name,
unique_type_id,
containing_scope);
......@@ -1299,7 +1301,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
set_members_of_composite_type(cx,
variant_type_metadata,
variant_llvm_type,
&member_descriptions[..]);
&member_descriptions);
MemberDescription {
name: "".to_string(),
llvm_type: variant_llvm_type,
......
......@@ -487,11 +487,11 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let trait_substs = Substs::erased(VecPerParamSpace::new(vec![target.ty],
vec![source.ty],
Vec::new()));
let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
let trait_ref = ty::Binder(ty::TraitRef {
def_id: langcall(bcx, Some(span), "coercion",
CoerceUnsizedTraitLangItem),
substs: bcx.tcx().mk_substs(trait_substs)
}));
});
let kind = match fulfill_obligation(bcx.ccx(), span, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
......
......@@ -60,28 +60,29 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let e = &cast.expr;
let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
let tcx = fcx.tcx();
// Check for trivial casts.
if !ty::type_has_ty_infer(t_1) {
if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
e.id,
span,
format!("trivial numeric cast: `{}` as `{}`. Cast can be \
replaced by coercion, this might require type \
ascription or a temporary variable",
fcx.infcx().ty_to_string(t_e),
fcx.infcx().ty_to_string(t_1)));
tcx.sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
e.id,
span,
format!("trivial numeric cast: `{}` as `{}`. Cast can be \
replaced by coercion, this might require type \
ascription or a temporary variable",
fcx.infcx().ty_to_string(t_e),
fcx.infcx().ty_to_string(t_1)));
} else {
fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
e.id,
span,
format!("trivial cast: `{}` as `{}`. Cast can be \
replaced by coercion, this might require type \
ascription or a temporary variable",
fcx.infcx().ty_to_string(t_e),
fcx.infcx().ty_to_string(t_1)));
tcx.sess.add_lint(lint::builtin::TRIVIAL_CASTS,
e.id,
span,
format!("trivial cast: `{}` as `{}`. Cast can be \
replaced by coercion, this might require type \
ascription or a temporary variable",
fcx.infcx().ty_to_string(t_e),
fcx.infcx().ty_to_string(t_1)));
}
return;
}
......@@ -91,14 +92,14 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let t_e_is_scalar = ty::type_is_scalar(t_e);
let t_e_is_integral = ty::type_is_integral(t_e);
let t_e_is_float = ty::type_is_floating_point(t_e);
let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e);
let t_e_is_c_enum = ty::type_is_c_like_enum(tcx, t_e);
let t_1_is_scalar = ty::type_is_scalar(t_1);
let t_1_is_integral = ty::type_is_integral(t_1);
let t_1_is_char = ty::type_is_char(t_1);
let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
let t_1_is_float = ty::type_is_floating_point(t_1);
let t_1_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_1);
let t_1_is_c_enum = ty::type_is_c_like_enum(tcx, t_1);
let t1_is_fat_ptr = fcx.type_is_fat_ptr(t_1, span);
// casts to scalars other than `char` and `bare fn` are trivial
......@@ -114,7 +115,7 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}, t_e, None);
}
} else if t_1.sty == ty::ty_bool {
span_err!(fcx.tcx().sess, span, E0054,
span_err!(tcx.sess, span, E0054,
"cannot cast as `bool`, compare with zero instead");
} else if t_e_is_float && (t_1_is_scalar || t_1_is_c_enum) &&
!(t_1_is_integral || t_1_is_float) {
......@@ -174,12 +175,16 @@ fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
} else if t1_is_fat_ptr {
// FIXME This should be allowed where the lefthandside is also a fat
// pointer and is the same kind of fat pointer, i.e., array to array,
// trait object to trait object.
fcx.type_error_message(span, |actual| {
format!("cast to fat pointer: `{}` as `{}`",
actual,
fcx.infcx().ty_to_string(t_1))
}, t_e, None);
// trait object to trait object. That is a bit looser than the current
// rquirement that they are pointers to the same type.
if !(fcx.type_is_fat_ptr(t_e, span) &&
ty::deref(t_1, true).unwrap().ty == ty::deref(t_e, true).unwrap().ty) {
fcx.type_error_message(span, |actual| {
format!("cast to fat pointer: `{}` as `{}`",
actual,
fcx.infcx().ty_to_string(t_1))
}, t_e, None);
}
} else if !(t_e_is_scalar && t_1_is_trivial) {
fcx.type_error_message(span, |actual| {
format!("non-scalar cast: `{}` as `{}`",
......
......@@ -285,14 +285,19 @@ fn coerce_unsized(&self,
// Create an obligation for `Source: CoerceUnsized<Target>`.
let cause = ObligationCause::misc(self.origin.span(), self.fcx.body_id);
queue.push_back(predicate_for_trait_def(self.tcx(), cause, coerce_unsized_did,
0, source, vec![target]));
queue.push_back(predicate_for_trait_def(self.tcx(),
cause,
coerce_unsized_did,
0,
source,
vec![target]));
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
// inference might unify those two inner type variables later.
let traits = [coerce_unsized_did, unsize_did];
while let Some(obligation) = queue.pop_front() {
debug!("coerce_unsized resolve step: {}", obligation.repr(self.tcx()));
let trait_ref = match obligation.predicate {
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
tr.clone()
......@@ -305,6 +310,7 @@ fn coerce_unsized(&self,
match selcx.select(&obligation.with(trait_ref)) {
// Uncertain or unimplemented.
Ok(None) | Err(traits::Unimplemented) => {
debug!("coerce_unsized: early return - can't prove obligation");
return Err(ty::terr_mismatch);
}
......
......@@ -85,6 +85,7 @@
use astconv::AstConv;
use check::dropck;
use check::FnCtxt;
use middle::free_region::FreeRegionMap;
use middle::implicator;
use middle::mem_categorization as mc;
use middle::region::CodeExtent;
......
......@@ -29,6 +29,7 @@
use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
use middle::ty::ty_projection;
use middle::ty;
use middle::free_region::FreeRegionMap;
use CrateCtxt;
use middle::infer::{self, InferCtxt, new_infer_ctxt};
use std::cell::RefCell;
......@@ -439,32 +440,19 @@ fn check_implementations_of_coerce_unsized(&self) {
}
};
let trait_impls = match tcx.trait_impls
.borrow()
.get(&coerce_unsized_trait)
.cloned() {
None => {
debug!("check_implementations_of_coerce_unsized(): no types \
with implementations of `CoerceUnsized` found");
return
}
Some(found_impls) => found_impls
};
let trait_def = ty::lookup_trait_def(tcx, coerce_unsized_trait);
// Clone first to avoid a double borrow error.
let trait_impls = trait_impls.borrow().clone();
for &impl_did in &trait_impls {
trait_def.for_each_impl(tcx, |impl_did| {
debug!("check_implementations_of_coerce_unsized: impl_did={}",
impl_did.repr(tcx));
if impl_did.krate != ast::LOCAL_CRATE {
debug!("check_implementations_of_coerce_unsized(): impl not \
in this crate");
continue
return;
}
let source = self.get_self_type_for_implementation(impl_did).ty;
let source = ty::lookup_item_type(tcx, impl_did).ty;
let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
impl_did.node);
let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
......@@ -507,12 +495,12 @@ fn check_implementations_of_coerce_unsized(&self) {
if def_id_a != def_id_b {
let source_path = ty::item_path_str(tcx, def_id_a);
let target_path = ty::item_path_str(tcx, def_id_b);
span_err!(tcx.sess, span, E0373,
span_err!(tcx.sess, span, E0377,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with the same \
definition; expected {}, found {}",
source_path, target_path);
continue;
return;
}
let origin = infer::Misc(span);
......@@ -532,7 +520,7 @@ fn check_implementations_of_coerce_unsized(&self) {
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with one field \
being coerced, none found");
continue;
return;
} else if diff_fields.len() > 1 {
span_err!(tcx.sess, span, E0375,
"the trait `CoerceUnsized` may only be implemented \
......@@ -549,7 +537,7 @@ fn check_implementations_of_coerce_unsized(&self) {
a.repr(tcx),
b.repr(tcx))
}).collect::<Vec<_>>().connect(", "));
continue;
return;
}
let (i, a, b) = diff_fields[0];
......@@ -561,7 +549,7 @@ fn check_implementations_of_coerce_unsized(&self) {
span_err!(tcx.sess, span, E0376,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures");
continue;
return;
}
};
......@@ -578,14 +566,15 @@ fn check_implementations_of_coerce_unsized(&self) {
traits::report_fulfillment_errors(&infcx, &errors);
}
// Finally, resolve all regions. This catches wily misuses of lifetime
// parameters.
infcx.resolve_regions_and_report_errors(impl_did.node);
// Finally, resolve all regions.
let mut free_regions = FreeRegionMap::new();
free_regions.relate_free_regions_from_predicates(tcx, &param_env.caller_bounds);
infcx.resolve_regions_and_report_errors(&free_regions, impl_did.node);
if let Some(kind) = kind {
tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind);
}
}
});
}
}
......
......@@ -323,7 +323,7 @@ fn check_item(&self, item: &ast::Item) {
return;
}
if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() {
span_err!(self.tcx.sess, item.span, E0323,
span_err!(self.tcx.sess, item.span, E0328,
"explicit impls for the `Unsize` trait are not permitted");
return;
}
......
......@@ -452,13 +452,13 @@ fn foo() -> usize { 12 }
E0369, // binary operation `<op>` cannot be applied to types
E0371, // impl Trait for Trait is illegal
E0372, // impl Trait for Trait where Trait is not object safe
E0373, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with one field being coerced, none found
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with one field being coerced, but multiple
// fields need coercions
E0376 // the trait `CoerceUnsized` may only be implemented for a coercion
E0376, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures
E0377 // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
}
......@@ -531,15 +531,16 @@ fn drop(&mut self) {
assert_eq!(*lock, 2);
}
#[test]
fn test_mutex_unsized() {
let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
{
let b = &mut *mutex.lock().unwrap();
b[0] = 4;
b[2] = 5;
}
let comp: &[i32] = &[4, 2, 5];
assert_eq!(&*mutex.lock().unwrap(), comp);
}
// FIXME(#25351) needs deeply nested coercions of DST structs.
// #[test]
// fn test_mutex_unsized() {
// let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
// {
// let b = &mut *mutex.lock().unwrap();
// b[0] = 4;
// b[2] = 5;
// }
// let comp: &[i32] = &[4, 2, 5];
// assert_eq!(&*mutex.lock().unwrap(), comp);
// }
}
......@@ -573,17 +573,18 @@ fn drop(&mut self) {
assert_eq!(*lock, 2);
}
#[test]
fn test_rwlock_unsized() {
let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
{
let b = &mut *rw.write().unwrap();
b[0] = 4;
b[2] = 5;
}
let comp: &[i32] = &[4, 2, 5];
assert_eq!(&*rw.read().unwrap(), comp);
}
// FIXME(#25351) needs deeply nested coercions of DST structs.
// #[test]
// fn test_rwlock_unsized() {
// let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
// {
// let b = &mut *rw.write().unwrap();
// b[0] = 4;
// b[2] = 5;
// }
// let comp: &[i32] = &[4, 2, 5];
// assert_eq!(&*rw.read().unwrap(), comp);
// }
#[test]
fn test_rwlock_try_write() {
......
......@@ -16,8 +16,8 @@ fn main() {
let a: &[i32] = &[1, 2, 3];
let b: Box<[i32]> = Box::new([1, 2, 3]);
a as usize; //~ ERROR illegal cast
b as usize; //~ ERROR illegal cast
a as usize; //~ ERROR non-scalar cast
b as usize; //~ ERROR non-scalar cast
let a: usize = 42;
a as *const [i32]; //~ ERROR cast to fat pointer: `usize` as `*const [i32]`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册