1
Fork 0

Use parameter environment associated with field use, not field definition

This commit is contained in:
Vadim Petrochenkov 2017-05-18 14:28:40 +03:00
parent 4386f97a93
commit fa13cd3489
2 changed files with 9 additions and 4 deletions

View 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 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, '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 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
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),
};

View 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
}