diff options
Diffstat (limited to 'src')
6 files changed, 76 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 0c5e4f40531..0e5597b036b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1725,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() {} |
