]> git.lizzy.rs Git - rust.git/commitdiff
Fix write_cvalue type assert for late bound regions in trait objects
authorbjorn3 <bjorn3@users.noreply.github.com>
Sun, 3 Mar 2019 15:33:46 +0000 (16:33 +0100)
committerbjorn3 <bjorn3@users.noreply.github.com>
Wed, 6 Mar 2019 19:57:14 +0000 (20:57 +0100)
src/common.rs

index 6da473bcbefe3541b6e579c886192707126791e8..3e51d1e6904c560799bee6938c8e486494dec9b3 100644 (file)
@@ -320,51 +320,70 @@ pub fn to_addr_maybe_unsized(
     }
 
     pub fn write_cvalue(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>, from: CValue<'tcx>) {
+        use rustc::hir::Mutability::*;
+
         let from_ty = from.layout().ty;
         let to_ty = self.layout().ty;
-        match (&from_ty.sty, &to_ty.sty) {
-            (ty::Ref(_, t, src_mut), ty::Ref(_, u, dest_mut))
-                if (if *dest_mut != crate::rustc::hir::Mutability::MutImmutable
-                    && src_mut != dest_mut
-                {
-                    false
-                } else if t != u {
-                    false
-                } else {
-                    true
-                }) =>
-            {
-                // &mut T -> &T is allowed
-                // &'a T -> &'b T is allowed
-            }
-            (ty::FnPtr(_), ty::FnPtr(_)) => {
-                let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
-                    ParamEnv::reveal_all(),
-                    &from_ty.fn_sig(fx.tcx),
-                );
-                let to_sig = fx.tcx.normalize_erasing_late_bound_regions(
-                    ParamEnv::reveal_all(),
-                    &to_ty.fn_sig(fx.tcx),
-                );
-                assert_eq!(
-                    from_sig, to_sig,
-                    "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
-                    from_sig, to_sig, fx,
-                );
-                // fn(&T) -> for<'l> fn(&'l T) is allowed
-            }
-            _ => {
-                assert_eq!(
-                    from_ty,
-                    to_ty,
-                    "Can't write value with incompatible type {:?} to place with type {:?}\n\n{:#?}",
-                    from_ty.sty,
-                    to_ty.sty,
-                    fx,
-                );
+
+        fn assert_assignable<'a, 'tcx: 'a>(fx: &FunctionCx<'a, 'tcx, impl Backend>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) {
+            match (&from_ty.sty, &to_ty.sty) {
+                (ty::Ref(_, t, MutImmutable), ty::Ref(_, u, MutImmutable))
+                | (ty::Ref(_, t, MutMutable), ty::Ref(_, u, MutImmutable))
+                | (ty::Ref(_, t, MutMutable), ty::Ref(_, u, MutMutable)) => {
+                    assert_assignable(fx, t, u);
+                    // &mut T -> &T is allowed
+                    // &'a T -> &'b T is allowed
+                }
+                (ty::Ref(_, _, MutImmutable), ty::Ref(_, _, MutMutable)) => {
+                    panic!("Cant assign value of type {} to place of type {}", from_ty.sty, to_ty.sty)
+                }
+                (ty::FnPtr(_), ty::FnPtr(_)) => {
+                    let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
+                        ParamEnv::reveal_all(),
+                        &from_ty.fn_sig(fx.tcx),
+                    );
+                    let to_sig = fx.tcx.normalize_erasing_late_bound_regions(
+                        ParamEnv::reveal_all(),
+                        &to_ty.fn_sig(fx.tcx),
+                    );
+                    assert_eq!(
+                        from_sig, to_sig,
+                        "Can't write fn ptr with incompatible sig {:?} to place with sig {:?}\n\n{:#?}",
+                        from_sig, to_sig, fx,
+                    );
+                    // fn(&T) -> for<'l> fn(&'l T) is allowed
+                }
+                (ty::Dynamic(from_traits, _), ty::Dynamic(to_traits, _)) => {
+                    let from_traits = fx.tcx.normalize_erasing_late_bound_regions(
+                        ParamEnv::reveal_all(),
+                        from_traits,
+                    );
+                    let to_traits = fx.tcx.normalize_erasing_late_bound_regions(
+                        ParamEnv::reveal_all(),
+                        to_traits,
+                    );
+                    assert_eq!(
+                        from_traits, to_traits,
+                        "Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
+                        from_traits, to_traits, fx,
+                    );
+                    // dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
+                }
+                _ => {
+                    assert_eq!(
+                        from_ty,
+                        to_ty,
+                        "Can't write value with incompatible type {:?} to place with type {:?}\n\n{:#?}",
+                        from_ty.sty,
+                        to_ty.sty,
+                        fx,
+                    );
+                }
             }
         }
 
+        assert_assignable(fx, from_ty, to_ty);
+
         let (addr, dst_layout) = match self {
             CPlace::Var(var, _) => {
                 let data = from.load_scalar(fx);