Skip to content

Commit dde61f3

Browse files
spastorinonikomatsakis
authored andcommitted
add basic region subtyping inference
1 parent b8615f3 commit dde61f3

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed

src/librustc_mir/transform/nll/constraint_generation.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc::util::common::ErrorReported;
2222
use rustc_data_structures::fx::FxHashSet;
2323
use syntax::codemap::DUMMY_SP;
2424

25+
use super::subtype;
2526
use super::LivenessResults;
2627
use super::ToRegionIndex;
2728
use super::region_infer::RegionInferenceContext;
@@ -239,6 +240,9 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
239240
block: BasicBlock,
240241
statement: &Statement<'tcx>,
241242
location: Location) {
243+
244+
debug!("visit_statement(statement={:?}, location={:?})", statement, location);
245+
242246
// Look for a statement like:
243247
//
244248
// D = & L
@@ -250,6 +254,14 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
250254
self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
251255
self.add_reborrow_constraint(location, region, borrowed_lv);
252256
}
257+
258+
let tcx = self.infcx.tcx;
259+
let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
260+
let rv_ty = rv.ty(self.mir, tcx);
261+
262+
for (a, b) in subtype::outlives_pairs(tcx, rv_ty, destination_ty) {
263+
self.regioncx.add_outlives(a, b, location.successor_within_block());
264+
}
253265
}
254266

255267
self.super_statement(block, statement, location);

src/librustc_mir/transform/nll/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use util as mir_util;
2222
use self::mir_util::PassWhere;
2323

2424
mod constraint_generation;
25+
mod subtype;
2526

2627
mod region_infer;
2728
use self::region_infer::RegionInferenceContext;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2017 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+
use super::RegionIndex;
12+
use transform::nll::ToRegionIndex;
13+
use rustc::ty::{self, Ty, TyCtxt};
14+
use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
15+
16+
pub fn outlives_pairs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
17+
a: Ty<'tcx>,
18+
b: Ty<'tcx>)
19+
-> Vec<(RegionIndex, RegionIndex)>
20+
{
21+
let mut subtype = Subtype::new(tcx);
22+
match subtype.relate(&a, &b) {
23+
Ok(_) => subtype.outlives_pairs,
24+
25+
Err(_) => bug!("Fail to relate a = {:?} and b = {:?}", a, b)
26+
}
27+
}
28+
29+
struct Subtype<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
30+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
31+
outlives_pairs: Vec<(RegionIndex, RegionIndex)>,
32+
ambient_variance: ty::Variance,
33+
}
34+
35+
impl<'a, 'gcx, 'tcx> Subtype<'a, 'gcx, 'tcx> {
36+
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Subtype<'a, 'gcx, 'tcx> {
37+
Subtype {
38+
tcx,
39+
outlives_pairs: vec![],
40+
ambient_variance: ty::Covariant,
41+
}
42+
}
43+
}
44+
45+
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Subtype<'a, 'gcx, 'tcx> {
46+
fn tag(&self) -> &'static str { "Subtype" }
47+
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx }
48+
fn a_is_expected(&self) -> bool { true } // irrelevant
49+
50+
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
51+
variance: ty::Variance,
52+
a: &T,
53+
b: &T)
54+
-> RelateResult<'tcx, T>
55+
{
56+
let old_ambient_variance = self.ambient_variance;
57+
self.ambient_variance = self.ambient_variance.xform(variance);
58+
59+
let result = self.relate(a, b);
60+
self.ambient_variance = old_ambient_variance;
61+
result
62+
}
63+
64+
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
65+
relate::super_relate_tys(self, t, t2)
66+
}
67+
68+
fn regions(&mut self, r_a: ty::Region<'tcx>, r_b: ty::Region<'tcx>)
69+
-> RelateResult<'tcx, ty::Region<'tcx>> {
70+
let a = r_a.to_region_index();
71+
let b = r_b.to_region_index();
72+
73+
match self.ambient_variance {
74+
ty::Covariant => {
75+
self.outlives_pairs.push((b, a));
76+
},
77+
78+
ty::Invariant => {
79+
self.outlives_pairs.push((a, b));
80+
self.outlives_pairs.push((b, a));
81+
},
82+
83+
ty::Contravariant => {
84+
self.outlives_pairs.push((a, b));
85+
},
86+
87+
ty::Bivariant => {},
88+
}
89+
90+
Ok(r_a)
91+
}
92+
93+
fn binders<T>(&mut self, _a: &ty::Binder<T>, _b: &ty::Binder<T>)
94+
-> RelateResult<'tcx, ty::Binder<T>>
95+
where T: Relate<'tcx>
96+
{
97+
unimplemented!();
98+
}
99+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2012-2016 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+
// Basic test for liveness constraints: the region (`R1`) that appears
12+
// in the type of `p` includes the points after `&v[0]` up to (but not
13+
// including) the call to `use_x`. The `else` branch is not included.
14+
15+
// compile-flags:-Znll -Zverbose
16+
// ^^^^^^^^^ force compiler to dump more region information
17+
18+
#![allow(warnings)]
19+
20+
fn use_x(_: usize) -> bool { true }
21+
22+
fn main() {
23+
let mut v = [1, 2, 3];
24+
let p = &v[0];
25+
let q = p;
26+
if true {
27+
use_x(*q);
28+
} else {
29+
use_x(22);
30+
}
31+
}
32+
33+
// END RUST SOURCE
34+
// START rustc.node12.nll.0.mir
35+
// | R0: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
36+
// | R1: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
37+
// | R2: {bb1[5], bb1[6], bb2[0], bb2[1]}
38+
// END rustc.node12.nll.0.mir
39+
// START rustc.node12.nll.0.mir
40+
// let _2: &'_#1r usize;
41+
// ...
42+
// let _6: &'_#2r usize;
43+
// ...
44+
// _2 = &'_#0r _1[_3];
45+
// ...
46+
// _7 = _2;
47+
// ...
48+
// _6 = _7;
49+
// END rustc.node12.nll.0.mir

0 commit comments

Comments
 (0)