diff options
| author | bors <bors@rust-lang.org> | 2018-06-27 21:32:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-06-27 21:32:44 +0000 |
| commit | cd494c1f0915da00a63c03454a96d504afe764ff (patch) | |
| tree | c4fb1400dad7cdb89cf479a9e41bfab37f57bf62 /src | |
| parent | 23b55161ab4cb6d4bf868ac575bd174ca2de0ffa (diff) | |
| parent | 03ecd982bf0b3d673dbe759dadfaff9eaaaa95d3 (diff) | |
| download | rust-cd494c1f0915da00a63c03454a96d504afe764ff.tar.gz rust-cd494c1f0915da00a63c03454a96d504afe764ff.zip | |
Auto merge of #51139 - vakaras:issue-50716, r=nikomatsakis
Fix NLL issue 50716 and add a regression test. Fix for NLL issue #50716. r? @nikomatsakis
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/ty/util.rs | 6 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/mod.rs | 32 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/mod.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/nll/issue-50716-1.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/nll/issue-50716.rs | 28 | ||||
| -rw-r--r-- | src/test/ui/nll/issue-50716.stderr | 8 |
8 files changed, 117 insertions, 7 deletions
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 024885420f6..4e281231a41 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -522,6 +522,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr } + /// True if this def-id refers to the implicit constructor for + /// a tuple struct like `struct Foo(u32)`. + pub fn is_struct_constructor(self, def_id: DefId) -> bool { + self.def_key(def_id).disambiguated_data.data == DefPathData::StructCtor + } + /// Given the `DefId` of a fn or closure, returns the `DefId` of /// the innermost fn item that the closure is contained within. /// This is a significant def-id because, when we do diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 6d77364aae0..ca0c259fb67 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -76,7 +76,37 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); - if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() { + let mut return_early; + + // Return early if we are not supposed to use MIR borrow checker for this function. + return_early = !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck(); + + if tcx.is_struct_constructor(def_id) { + // We are not borrow checking the automatically generated struct constructors + // because we want to accept structs such as this (taken from the `linked-hash-map` + // crate): + // ```rust + // struct Qey<Q: ?Sized>(Q); + // ``` + // MIR of this struct constructor looks something like this: + // ```rust + // fn Qey(_1: Q) -> Qey<Q>{ + // let mut _0: Qey<Q>; // return place + // + // bb0: { + // (_0.0: Q) = move _1; // bb0[0]: scope 0 at src/main.rs:1:1: 1:26 + // return; // bb0[1]: scope 0 at src/main.rs:1:1: 1:26 + // } + // } + // ``` + // The problem here is that `(_0.0: Q) = move _1;` is valid only if `Q` is + // of statically known size, which is not known to be true because of the + // `Q: ?Sized` constraint. However, it is true because the constructor can be + // called only when `Q` is of statically known size. + return_early = true; + } + + if return_early { return BorrowCheckResult { closure_requirements: None, used_mut_upvars: SmallVec::new(), 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 d25cec79791..0e5597b036b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -873,6 +873,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } self.check_rvalue(mir, rv, location); + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().sized_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty, &[]), + }; + self.prove_trait_ref(trait_ref, location); } StatementKind::SetDiscriminant { ref place, @@ -1720,6 +1725,14 @@ impl MirPass for TypeckMir { // broken MIR, so try not to report duplicate errors. return; } + + if tcx.is_struct_constructor(def_id) { + // We just assume that the automatically generated struct constructors are + // correct. See the comment in the `mir_borrowck` implementation for an + // explanation why we need this. + return; + } + let param_env = tcx.param_env(def_id); tcx.infer_ctxt().enter(|infcx| { let _ = type_check_internal( diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 93a7c1a0c6c..122e393f97a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -24,15 +24,16 @@ LL | | }); = note: where '_#1r: '_#0r error: free region `ReFree(DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]), BrNamed(crate0:DefIndex(1:16), 'a))` does not outlive free region `ReStatic` - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5 + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47 | -LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | _______________________________________________^ LL | | //~^ ERROR does not outlive free region LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll LL | | }); - | |______^ + | |_____^ note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index c62f62efda3..8cdbc264581 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -24,15 +24,16 @@ LL | | }); = note: where '_#1r: '_#0r error: free region `ReFree(DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]), BrNamed(crate0:DefIndex(1:16), 'a))` does not outlive free region `ReStatic` - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5 + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47 | -LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | _______________________________________________^ LL | | //~^ ERROR does not outlive free region LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | //~^ WARNING not reporting region error due to nll LL | | }); - | |______^ + | |_____^ note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1 diff --git a/src/test/ui/nll/issue-50716-1.rs b/src/test/ui/nll/issue-50716-1.rs new file mode 100644 index 00000000000..ced9b1cde64 --- /dev/null +++ b/src/test/ui/nll/issue-50716-1.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. +// +// An additional regression test for the issue #50716 “NLL ignores lifetimes +// bounds derived from `Sized` requirements” that checks that the fixed compiler +// accepts this code fragment with both AST and MIR borrow checkers. +// +// revisions: ast mir +// +// compile-pass + +#![cfg_attr(mir, feature(nll))] + +struct Qey<Q: ?Sized>(Q); + +fn main() {} diff --git a/src/test/ui/nll/issue-50716.rs b/src/test/ui/nll/issue-50716.rs new file mode 100644 index 00000000000..310600aaf9a --- /dev/null +++ b/src/test/ui/nll/issue-50716.rs @@ -0,0 +1,28 @@ +// 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. +// +// Regression test for the issue #50716: NLL ignores lifetimes bounds +// derived from `Sized` requirements + +#![feature(nll)] + +trait A { + type X: ?Sized; +} + +fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) +where + for<'b> &'b T: A, + <&'static T as A>::X: Sized +{ + let _x = *s; //~ ERROR free region `'a` does not outlive free region `'static` +} + +fn main() {} diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr new file mode 100644 index 00000000000..20b03d648d9 --- /dev/null +++ b/src/test/ui/nll/issue-50716.stderr @@ -0,0 +1,8 @@ +error: free region `'a` does not outlive free region `'static` + --> $DIR/issue-50716.rs:25:14 + | +LL | let _x = *s; //~ ERROR free region `'a` does not outlive free region `'static` + | ^^ + +error: aborting due to previous error + |
