Use parameter environment associated with field use, not field definition
This commit is contained in:
parent
4386f97a93
commit
fa13cd3489
2 changed files with 9 additions and 4 deletions
|
@ -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, ¶m_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),
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue