]> git.lizzy.rs Git - rust.git/commitdiff
Use parameter environment associated with field use, not field definition
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 18 May 2017 11:28:40 +0000 (14:28 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 25 May 2017 07:46:47 +0000 (10:46 +0300)
src/librustc/middle/effect.rs
src/test/compile-fail/union/union-unsafe.rs

index 94362e69c8dd948ab66fcd8f605d9aa821da2384..2261f296454ef75470a7f648ff1e6c665cc644ab 100644 (file)
@@ -52,6 +52,7 @@ fn type_is_unsafe_function(ty: Ty) -> bool {
 struct EffectCheckVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
+    body_id: hir::BodyId,
 
     /// Whether we're in an unsafe context.
     unsafe_context: UnsafeContext,
@@ -99,10 +100,13 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         let old_tables = self.tables;
+        let old_body_id = self.body_id;
         self.tables = self.tcx.body_tables(body);
+        self.body_id = body;
         let body = self.tcx.hir.body(body);
         self.visit_body(body);
         self.tables = old_tables;
+        self.body_id = old_body_id;
     }
 
     fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl,
@@ -223,8 +227,9 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                     if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty {
                         if adt.is_union() {
                             let field_ty = self.tables.expr_ty_adjusted(lhs);
-                            let param_env = self.tcx.parameter_environment(adt.did);
-                            if field_ty.moves_by_default(self.tcx, &param_env, field.span) {
+                            let owner_def_id = self.tcx.hir.body_owner_def_id(self.body_id);
+                            let param_env = self.tcx.param_env(owner_def_id);
+                            if field_ty.moves_by_default(self.tcx, param_env, field.span) {
                                 self.require_unsafe(field.span,
                                                     "assignment to non-`Copy` union field");
                             }
@@ -261,6 +266,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
         tables: &ty::TypeckTables::empty(),
+        body_id: hir::BodyId { node_id: ast::CRATE_NODE_ID },
         unsafe_context: UnsafeContext::new(SafeContext),
     };
 
index a67603675f1755af41142253970b0b4215680b81..2e018e696a4155b6c53a6b3885cf06782cec8bb6 100644 (file)
@@ -33,8 +33,7 @@ fn generic_noncopy<T: Default>() {
 
 fn generic_copy<T: Copy + Default>() {
     let mut u3 = U3 { a: T::default() };
-    // FIXME: it should be known here that `T: Copy`, need to use correct "parameter environment"
-    u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field requires unsafe
+    u3.a = T::default(); // OK
     let mut u4 = U4 { a: T::default() };
     u4.a = T::default(); // OK
 }