--- /dev/null
+// Copyright 2016 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.
+
+use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
+use traits::query::outlives_bounds::OutlivesBound;
+use traits::query::Fallible;
+use ty::{ParamEnvAnd, Ty, TyCtxt};
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct ImpliedOutlivesBounds<'tcx> {
+ pub ty: Ty<'tcx>,
+}
+
+impl<'tcx> ImpliedOutlivesBounds<'tcx> {
+ pub fn new(ty: Ty<'tcx>) -> Self {
+ ImpliedOutlivesBounds { ty }
+ }
+}
+
+impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ImpliedOutlivesBounds<'tcx> {
+ type QueryResult = Vec<OutlivesBound<'tcx>>;
+
+ fn try_fast_path(
+ _tcx: TyCtxt<'_, 'gcx, 'tcx>,
+ _key: &ParamEnvAnd<'tcx, Self>,
+ ) -> Option<Self::QueryResult> {
+ None
+ }
+
+ fn perform_query(
+ tcx: TyCtxt<'_, 'gcx, 'tcx>,
+ canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
+ ) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>> {
+ // FIXME the query should take a `ImpliedOutlivesBounds`
+ let Canonical {
+ variables,
+ value:
+ ParamEnvAnd {
+ param_env,
+ value: ImpliedOutlivesBounds { ty },
+ },
+ } = canonicalized;
+ let canonicalized = Canonical {
+ variables,
+ value: param_env.and(ty),
+ };
+
+ tcx.implied_outlives_bounds(canonicalized)
+ }
+
+ fn shrink_to_tcx_lifetime(
+ v: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
+ ) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>> {
+ v
+ }
+}
+
+BraceStructTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for ImpliedOutlivesBounds<'tcx> {
+ ty,
+ }
+}
+
+BraceStructLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for ImpliedOutlivesBounds<'a> {
+ type Lifted = ImpliedOutlivesBounds<'tcx>;
+ ty,
+ }
+}
+
+impl_stable_hash_for! {
+ struct ImpliedOutlivesBounds<'tcx> { ty }
+}
pub mod custom;
pub mod eq;
+pub mod implied_outlives_bounds;
pub mod normalize;
pub mod outlives;
pub mod prove_predicate;
use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
use borrow_check::nll::universal_regions::UniversalRegions;
use borrow_check::nll::ToRegionVid;
-use rustc::hir::def_id::DefId;
+use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::free_region_map::FreeRegionRelations;
use rustc::infer::region_constraints::GenericKind;
use rustc::infer::InferCtxt;
use rustc::ty::{self, RegionVid, Ty};
use rustc_data_structures::transitive_relation::TransitiveRelation;
use std::rc::Rc;
-use syntax::ast;
#[derive(Debug)]
crate struct UniversalRegionRelations<'tcx> {
crate fn create(
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir_def_id: DefId,
param_env: ty::ParamEnv<'tcx>,
location_table: &LocationTable,
implicit_region_bound: Option<ty::Region<'tcx>>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
all_facts: &mut Option<AllFacts>,
) -> CreateResult<'tcx> {
- let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap();
UniversalRegionRelationsBuilder {
infcx,
- mir_def_id,
- mir_node_id,
param_env,
implicit_region_bound,
constraints,
struct UniversalRegionRelationsBuilder<'this, 'gcx: 'tcx, 'tcx: 'this> {
infcx: &'this InferCtxt<'this, 'gcx, 'tcx>,
- mir_def_id: DefId,
- mir_node_id: ast::NodeId,
param_env: ty::ParamEnv<'tcx>,
location_table: &'this LocationTable,
universal_regions: Rc<UniversalRegions<'tcx>>,
let constraint_sets: Vec<_> = unnormalized_input_output_tys
.flat_map(|ty| {
debug!("build: input_or_output={:?}", ty);
- let (ty, constraints) = self
+ let (ty, constraints1) = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx)
.unwrap_or_else(|_| bug!("failed to normalize {:?}", ty));
- self.add_implied_bounds(ty);
+ let constraints2 = self.add_implied_bounds(ty);
normalized_inputs_and_output.push(ty);
- constraints
+ constraints1
+ .into_iter()
+ .chain(constraints2)
})
.collect();
/// either the return type of the MIR or one of its arguments. At
/// the same time, compute and add any implied bounds that come
/// from this local.
- fn add_implied_bounds(&mut self, ty: Ty<'tcx>) {
+ fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<Vec<QueryRegionConstraint<'tcx>>>> {
debug!("add_implied_bounds(ty={:?})", ty);
- let span = self.infcx.tcx.def_span(self.mir_def_id);
- let bounds = self
- .infcx
- .implied_outlives_bounds(self.param_env, self.mir_node_id, ty, span);
+ let (bounds, constraints) =
+ self.param_env
+ .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
+ .fully_perform(self.infcx)
+ .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
self.add_outlives_bounds(bounds);
+ constraints
}
/// Registers the `OutlivesBound` items from `outlives_bounds` in
normalized_inputs_and_output,
} = free_region_relations::create(
infcx,
- mir_def_id,
param_env,
location_table,
Some(implicit_region_bound),
--- /dev/null
+// Copyright 2018 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 an NLL-related ICE (#52992) -- computing
+// implied bounds was causing outlives relations that were not
+// properly handled.
+//
+// compile-pass
+
+#![feature(nll)]
+
+fn main() {}
+
+fn fail<'a>() -> Struct<'a, Generic<()>> {
+ Struct(&Generic(()))
+}
+
+struct Struct<'a, T>(&'a T) where
+ T: Trait + 'a,
+ T::AT: 'a; // only fails with this bound
+
+struct Generic<T>(T);
+
+trait Trait {
+ type AT;
+}
+
+impl<T> Trait for Generic<T> {
+ type AT = T; // only fails with a generic AT
+}