diff options
| author | kennytm <kennytm@gmail.com> | 2018-02-04 23:28:54 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-02-04 23:28:54 +0800 |
| commit | f3dc75602f920e3f99d6e1cf18ce135639908e21 (patch) | |
| tree | f35402d2f65a86744003321b41fd03ce9f261eb3 | |
| parent | 686986375b5c7ba19c936f96670566a05b73251e (diff) | |
| parent | b9f756416a02fe3fd1c145fc081494b68f494f76 (diff) | |
| download | rust-f3dc75602f920e3f99d6e1cf18ce135639908e21.tar.gz rust-f3dc75602f920e3f99d6e1cf18ce135639908e21.zip | |
Rollup merge of #47877 - spastorino:lifetime-bounds-in-copy, r=nikomatsakis
Do not ignore lifetime bounds in Copy impls cc #29149 r? @nikomatsakis
| -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 fb2ab43fbbb..c0c680a4ddc 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); +} |
