diff options
| author | Santiago Pastorino <spastorino@gmail.com> | 2018-01-30 11:20:57 -0300 |
|---|---|---|
| committer | Santiago Pastorino <spastorino@gmail.com> | 2018-01-30 14:00:27 -0300 |
| commit | b9f756416a02fe3fd1c145fc081494b68f494f76 (patch) | |
| tree | 3b7b010931eb642b083bccefc499a8cfde3bbf9d | |
| parent | fe7e1a45f37f4265434cead827f587e75412f85c (diff) | |
| download | rust-b9f756416a02fe3fd1c145fc081494b68f494f76.tar.gz rust-b9f756416a02fe3fd1c145fc081494b68f494f76.zip | |
Do not ignore lifetime bounds in Copy impls
Closes #29149
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/mod.rs | 21 | ||||
| -rw-r--r-- | src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs | 23 |
2 files changed, 37 insertions, 7 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 015eb8a3b66..cebdd4d2826 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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 } diff --git a/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs new file mode 100644 index 00000000000..2a4295fd90a --- /dev/null +++ b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs @@ -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); +} |
