Skip to content

Commit a59584a

Browse files
committed
use TypeOp machinery for outlives_bounds
Fixes rust-lang#52992
1 parent 89574a6 commit a59584a

File tree

5 files changed

+131
-17
lines changed

5 files changed

+131
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 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+
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
12+
use traits::query::outlives_bounds::OutlivesBound;
13+
use traits::query::Fallible;
14+
use ty::{ParamEnvAnd, Ty, TyCtxt};
15+
16+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
17+
pub struct ImpliedOutlivesBounds<'tcx> {
18+
pub ty: Ty<'tcx>,
19+
}
20+
21+
impl<'tcx> ImpliedOutlivesBounds<'tcx> {
22+
pub fn new(ty: Ty<'tcx>) -> Self {
23+
ImpliedOutlivesBounds { ty }
24+
}
25+
}
26+
27+
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ImpliedOutlivesBounds<'tcx> {
28+
type QueryResult = Vec<OutlivesBound<'tcx>>;
29+
30+
fn try_fast_path(
31+
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
32+
_key: &ParamEnvAnd<'tcx, Self>,
33+
) -> Option<Self::QueryResult> {
34+
None
35+
}
36+
37+
fn perform_query(
38+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
39+
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
40+
) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>> {
41+
// FIXME the query should take a `ImpliedOutlivesBounds`
42+
let Canonical {
43+
variables,
44+
value:
45+
ParamEnvAnd {
46+
param_env,
47+
value: ImpliedOutlivesBounds { ty },
48+
},
49+
} = canonicalized;
50+
let canonicalized = Canonical {
51+
variables,
52+
value: param_env.and(ty),
53+
};
54+
55+
tcx.implied_outlives_bounds(canonicalized)
56+
}
57+
58+
fn shrink_to_tcx_lifetime(
59+
v: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
60+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>> {
61+
v
62+
}
63+
}
64+
65+
BraceStructTypeFoldableImpl! {
66+
impl<'tcx> TypeFoldable<'tcx> for ImpliedOutlivesBounds<'tcx> {
67+
ty,
68+
}
69+
}
70+
71+
BraceStructLiftImpl! {
72+
impl<'a, 'tcx> Lift<'tcx> for ImpliedOutlivesBounds<'a> {
73+
type Lifted = ImpliedOutlivesBounds<'tcx>;
74+
ty,
75+
}
76+
}
77+
78+
impl_stable_hash_for! {
79+
struct ImpliedOutlivesBounds<'tcx> { ty }
80+
}

src/librustc/traits/query/type_op/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use ty::{Lift, ParamEnvAnd, TyCtxt};
2121

2222
pub mod custom;
2323
pub mod eq;
24+
pub mod implied_outlives_bounds;
2425
pub mod normalize;
2526
pub mod outlives;
2627
pub mod prove_predicate;

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

+13-16
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use borrow_check::nll::type_check::constraint_conversion;
1414
use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
1515
use borrow_check::nll::universal_regions::UniversalRegions;
1616
use borrow_check::nll::ToRegionVid;
17-
use rustc::hir::def_id::DefId;
17+
use rustc::infer::canonical::QueryRegionConstraint;
1818
use rustc::infer::outlives::free_region_map::FreeRegionRelations;
1919
use rustc::infer::region_constraints::GenericKind;
2020
use rustc::infer::InferCtxt;
@@ -23,7 +23,6 @@ use rustc::traits::query::type_op::{self, TypeOp};
2323
use rustc::ty::{self, RegionVid, Ty};
2424
use rustc_data_structures::transitive_relation::TransitiveRelation;
2525
use std::rc::Rc;
26-
use syntax::ast;
2726

2827
#[derive(Debug)]
2928
crate struct UniversalRegionRelations<'tcx> {
@@ -67,19 +66,15 @@ crate struct CreateResult<'tcx> {
6766

6867
crate fn create(
6968
infcx: &InferCtxt<'_, '_, 'tcx>,
70-
mir_def_id: DefId,
7169
param_env: ty::ParamEnv<'tcx>,
7270
location_table: &LocationTable,
7371
implicit_region_bound: Option<ty::Region<'tcx>>,
7472
universal_regions: &Rc<UniversalRegions<'tcx>>,
7573
constraints: &mut MirTypeckRegionConstraints<'tcx>,
7674
all_facts: &mut Option<AllFacts>,
7775
) -> CreateResult<'tcx> {
78-
let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap();
7976
UniversalRegionRelationsBuilder {
8077
infcx,
81-
mir_def_id,
82-
mir_node_id,
8378
param_env,
8479
implicit_region_bound,
8580
constraints,
@@ -212,8 +207,6 @@ impl UniversalRegionRelations<'tcx> {
212207

213208
struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> {
214209
infcx: &'this InferCtxt<'this, 'gcx, 'tcx>,
215-
mir_def_id: DefId,
216-
mir_node_id: ast::NodeId,
217210
param_env: ty::ParamEnv<'tcx>,
218211
location_table: &'this LocationTable,
219212
universal_regions: Rc<UniversalRegions<'tcx>>,
@@ -248,14 +241,16 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
248241
let constraint_sets: Vec<_> = unnormalized_input_output_tys
249242
.flat_map(|ty| {
250243
debug!("build: input_or_output={:?}", ty);
251-
let (ty, constraints) = self
244+
let (ty, constraints1) = self
252245
.param_env
253246
.and(type_op::normalize::Normalize::new(ty))
254247
.fully_perform(self.infcx)
255248
.unwrap_or_else(|_| bug!("failed to normalize {:?}", ty));
256-
self.add_implied_bounds(ty);
249+
let constraints2 = self.add_implied_bounds(ty);
257250
normalized_inputs_and_output.push(ty);
258-
constraints
251+
constraints1
252+
.into_iter()
253+
.chain(constraints2)
259254
})
260255
.collect();
261256

@@ -306,13 +301,15 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
306301
/// either the return type of the MIR or one of its arguments. At
307302
/// the same time, compute and add any implied bounds that come
308303
/// from this local.
309-
fn add_implied_bounds(&mut self, ty: Ty<'tcx>) {
304+
fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<Vec<QueryRegionConstraint<'tcx>>>> {
310305
debug!("add_implied_bounds(ty={:?})", ty);
311-
let span = self.infcx.tcx.def_span(self.mir_def_id);
312-
let bounds = self
313-
.infcx
314-
.implied_outlives_bounds(self.param_env, self.mir_node_id, ty, span);
306+
let (bounds, constraints) =
307+
self.param_env
308+
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
309+
.fully_perform(self.infcx)
310+
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
315311
self.add_outlives_bounds(bounds);
312+
constraints
316313
}
317314

318315
/// Registers the `OutlivesBound` items from `outlives_bounds` in

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

-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ pub(crate) fn type_check<'gcx, 'tcx>(
135135
normalized_inputs_and_output,
136136
} = free_region_relations::create(
137137
infcx,
138-
mir_def_id,
139138
param_env,
140139
location_table,
141140
Some(implicit_region_bound),

src/test/ui/issue-52992.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2018 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+
// Regression test for an NLL-related ICE (#52992) -- computing
12+
// implied bounds was causing outlives relations that were not
13+
// properly handled.
14+
//
15+
// compile-pass
16+
17+
#![feature(nll)]
18+
19+
fn main() {}
20+
21+
fn fail<'a>() -> Struct<'a, Generic<()>> {
22+
Struct(&Generic(()))
23+
}
24+
25+
struct Struct<'a, T>(&'a T) where
26+
T: Trait + 'a,
27+
T::AT: 'a; // only fails with this bound
28+
29+
struct Generic<T>(T);
30+
31+
trait Trait {
32+
type AT;
33+
}
34+
35+
impl<T> Trait for Generic<T> {
36+
type AT = T; // only fails with a generic AT
37+
}

0 commit comments

Comments
 (0)