about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-07-26 23:35:38 +0000
committerbors <bors@rust-lang.org>2015-07-26 23:35:38 +0000
commit6d288192d90ad3f8c2b87def74172ef6b3e0fc17 (patch)
treeeb5a5a0a84f99a6af0c02b40a1b0c70f03692993
parent6d36798c89806fc4eaabb83831be1a4c90919a02 (diff)
parentc46f91324434d46472bd4aa15286240b7ba537d6 (diff)
Auto merge of #27294 - eddyb:deep-unsize-hinting, r=nrc
`Rc::new(RefCell::new(x)): Rc<RefCell<Trait>>` should not mean `RefCell::new(x): RefCell<Trait>`.
The latter is impossible, as an rvalue can't have an unsized type.
We were already handling unsized argument hints, but not when dealing with unsized structures.
-rw-r--r--src/librustc_typeck/check/mod.rs10
-rw-r--r--src/test/run-pass/coerce-expect-unsized.rs5
2 files changed, 10 insertions, 5 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 85df5d67ff6..0c60cdc4ca2 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2490,7 +2490,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 // The special-cased logic below has three functions:
                 // 1. Provide as good of an expected type as possible.
                 let expected = expected_arg_tys.get(i).map(|&ty| {
-                    Expectation::rvalue_hint(ty)
+                    Expectation::rvalue_hint(fcx.tcx(), ty)
                 });
 
                 check_expr_with_unifier(fcx, &**arg,
@@ -3268,7 +3268,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             match unop {
                 ast::UnUniq => match ty.sty {
                     ty::TyBox(ty) => {
-                        Expectation::rvalue_hint(ty)
+                        Expectation::rvalue_hint(tcx, ty)
                     }
                     _ => {
                         NoExpectation
@@ -3345,7 +3345,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                         // the last field of a struct can be unsized.
                         ExpectHasType(mt.ty)
                     } else {
-                        Expectation::rvalue_hint(mt.ty)
+                        Expectation::rvalue_hint(tcx, mt.ty)
                     }
                 }
                 _ => NoExpectation
@@ -3982,8 +3982,8 @@ impl<'tcx> Expectation<'tcx> {
     /// which still is useful, because it informs integer literals and the like.
     /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
     /// for examples of where this comes up,.
-    fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
-        match ty.sty {
+    fn rvalue_hint(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
+        match tcx.struct_tail(ty).sty {
             ty::TySlice(_) | ty::TyTrait(..) => {
                 ExpectRvalueLikeUnsized(ty)
             }
diff --git a/src/test/run-pass/coerce-expect-unsized.rs b/src/test/run-pass/coerce-expect-unsized.rs
index 6926879856c..ee4ec24b7e3 100644
--- a/src/test/run-pass/coerce-expect-unsized.rs
+++ b/src/test/run-pass/coerce-expect-unsized.rs
@@ -13,7 +13,9 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
+use std::cell::RefCell;
 use std::fmt::Debug;
+use std::rc::Rc;
 
 // Check that coercions apply at the pointer level and don't cause
 // rvalue expressions to be unsized. See #20169 for more information.
@@ -45,6 +47,9 @@ pub fn main() {
     let _: Box<[isize]> = Box::new([1, 2, 3]);
     let _: Box<Fn(isize) -> _> = Box::new(|x| (x as u8));
 
+    let _: Rc<RefCell<[isize]>> = Rc::new(RefCell::new([1, 2, 3]));
+    let _: Rc<RefCell<FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| (x as u8)));
+
     let _: Vec<Box<Fn(isize) -> _>> = vec![
         Box::new(|x| (x as u8)),
         Box::new(|x| (x as i16 as u8)),