Skip to content

Commit 03ecd98

Browse files
committed
Fix the error of selecting obligation by not running the borrow checker.
1 parent f288b87 commit 03ecd98

File tree

6 files changed

+76
-7
lines changed

6 files changed

+76
-7
lines changed

src/librustc/ty/util.rs

+6
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
522522
self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
523523
}
524524

525+
/// True if this def-id refers to the implicit constructor for
526+
/// a tuple struct like `struct Foo(u32)`.
527+
pub fn is_struct_constructor(self, def_id: DefId) -> bool {
528+
self.def_key(def_id).disambiguated_data.data == DefPathData::StructCtor
529+
}
530+
525531
/// Given the `DefId` of a fn or closure, returns the `DefId` of
526532
/// the innermost fn item that the closure is contained within.
527533
/// This is a significant def-id because, when we do

src/librustc_mir/borrow_check/mod.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,37 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC
7676
let input_mir = tcx.mir_validated(def_id);
7777
debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
7878

79-
if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() {
79+
let mut return_early;
80+
81+
// Return early if we are not supposed to use MIR borrow checker for this function.
82+
return_early = !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck();
83+
84+
if tcx.is_struct_constructor(def_id) {
85+
// We are not borrow checking the automatically generated struct constructors
86+
// because we want to accept structs such as this (taken from the `linked-hash-map`
87+
// crate):
88+
// ```rust
89+
// struct Qey<Q: ?Sized>(Q);
90+
// ```
91+
// MIR of this struct constructor looks something like this:
92+
// ```rust
93+
// fn Qey(_1: Q) -> Qey<Q>{
94+
// let mut _0: Qey<Q>; // return place
95+
//
96+
// bb0: {
97+
// (_0.0: Q) = move _1; // bb0[0]: scope 0 at src/main.rs:1:1: 1:26
98+
// return; // bb0[1]: scope 0 at src/main.rs:1:1: 1:26
99+
// }
100+
// }
101+
// ```
102+
// The problem here is that `(_0.0: Q) = move _1;` is valid only if `Q` is
103+
// of statically known size, which is not known to be true because of the
104+
// `Q: ?Sized` constraint. However, it is true because the constructor can be
105+
// called only when `Q` is of statically known size.
106+
return_early = true;
107+
}
108+
109+
if return_early {
80110
return BorrowCheckResult {
81111
closure_requirements: None,
82112
used_mut_upvars: SmallVec::new(),

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,14 @@ impl MirPass for TypeckMir {
17251725
// broken MIR, so try not to report duplicate errors.
17261726
return;
17271727
}
1728+
1729+
if tcx.is_struct_constructor(def_id) {
1730+
// We just assume that the automatically generated struct constructors are
1731+
// correct. See the comment in the `mir_borrowck` implementation for an
1732+
// explanation why we need this.
1733+
return;
1734+
}
1735+
17281736
let param_env = tcx.param_env(def_id);
17291737
tcx.infer_ctxt().enter(|infcx| {
17301738
let _ = type_check_internal(

src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@ LL | | });
2424
= note: where '_#1r: '_#0r
2525

2626
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`
27-
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
27+
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
2828
|
29-
LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
29+
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
30+
| _______________________________________________^
3031
LL | | //~^ ERROR does not outlive free region
3132
LL | |
3233
LL | | // Only works if 'x: 'y:
3334
LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
3435
LL | | });
35-
| |______^
36+
| |_____^
3637

3738
note: No external requirements
3839
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1

src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@ LL | | });
2424
= note: where '_#1r: '_#0r
2525

2626
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`
27-
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
27+
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
2828
|
29-
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
29+
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
30+
| _______________________________________________^
3031
LL | | //~^ ERROR does not outlive free region
3132
LL | | // Only works if 'x: 'y:
3233
LL | | demand_y(x, y, x.get())
3334
LL | | //~^ WARNING not reporting region error due to nll
3435
LL | | });
35-
| |______^
36+
| |_____^
3637

3738
note: No external requirements
3839
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1

src/test/ui/nll/issue-50716-1.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
//
11+
// An additional regression test for the issue #50716 “NLL ignores lifetimes
12+
// bounds derived from `Sized` requirements” that checks that the fixed compiler
13+
// accepts this code fragment with both AST and MIR borrow checkers.
14+
//
15+
// revisions: ast mir
16+
//
17+
// compile-pass
18+
19+
#![cfg_attr(mir, feature(nll))]
20+
21+
struct Qey<Q: ?Sized>(Q);
22+
23+
fn main() {}

0 commit comments

Comments
 (0)