Skip to content

Commit

Permalink
Do not ignore lifetime bounds in Copy impls
Browse files Browse the repository at this point in the history
Closes #29149
  • Loading branch information
spastorino committed Jan 30, 2018
1 parent fe7e1a4 commit b9f7564
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,13 +374,20 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
}
};
if let PlaceContext::Copy = context {
let ty = place_ty.to_ty(self.tcx());
if self.cx
.infcx
.type_moves_by_default(self.cx.param_env, ty, DUMMY_SP)
{
span_mirbug!(self, place, "attempted copy of non-Copy type ({:?})", ty);
}
let tcx = self.tcx();
let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().copy_trait().unwrap(),
substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
};

// In order to have a Copy operand, the type T of the value must be Copy. Note that we
// prove that T: Copy, rather than using the type_moves_by_default test. This is
// important because type_moves_by_default ignores the resulting region obligations and
// assumes they pass. This can result in bounds from Copy impls being unsoundly ignored
// (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds
// fully apply: in effect, the rule is that if a value of some type could implement
// Copy, then it must.
self.cx.prove_trait_ref(trait_ref, location);
}
place_ty
}
Expand Down
23 changes: 23 additions & 0 deletions src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that the 'static bound from the Copy impl is respected. Regression test for #29149.

#![feature(nll)]

#[derive(Clone)] struct Foo<'a>(&'a u32);
impl Copy for Foo<'static> {}

fn main() {
let s = 2;
let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597]
drop(a);
drop(a);
}

0 comments on commit b9f7564

Please sign in to comment.