diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 767cb1618bb67..ee16d6b3cfbe3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -558,7 +558,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }, ty::PredicateKind::TypeOutlives(pred) => { - if pred.0.is_known_global() { + // A global type with no late-bound regions can only + // contain the "'static" lifetime (any other lifetime + // would either be late-bound or local), so it is guaranteed + // to outlive any other lifetime + if pred.0.is_global(self.infcx.tcx) && !pred.0.has_late_bound_regions() { Ok(EvaluatedToOk) } else { Ok(EvaluatedToOkModuloRegions) diff --git a/src/test/ui/traits/project-modulo-regions.rs b/src/test/ui/traits/project-modulo-regions.rs new file mode 100644 index 0000000000000..f0c0dd3ed9578 --- /dev/null +++ b/src/test/ui/traits/project-modulo-regions.rs @@ -0,0 +1,55 @@ +// revisions: with_clause without_clause +// Tests that `EvaluatedToOkModuloRegions` from a projection sub-obligation +// is correctly propagated + +#![feature(rustc_attrs)] + +trait MyTrait { + type Assoc; +} + +struct MyStruct; + +impl MyTrait for MyStruct { + // Evaluating this projection will result in `EvaluatedToOkModuloRegions` + // (when `with_clause` is enabled) + type Assoc = ::Assoc; +} + +struct Bar; + +// The `where` clause on this impl will cause us to produce `EvaluatedToOkModuloRegions` +// when evaluating a projection involving this impl +#[cfg(with_clause)] +impl MyTrait for Bar where for<'b> &'b (): 'b { + type Assoc = bool; +} + +// This impl tests that the `EvaluatedToOkModuoRegions` result that we get +// is really due to the `where` clause on the `with_clause` impl +#[cfg(without_clause)] +impl MyTrait for Bar { + type Assoc = bool; +} + +// The implementation of `#[rustc_evaluate_where_clauses]` doesn't perform +// normalization, so we need to place the projection predicate behind a normal +// trait predicate +struct Helper {} +trait HelperTrait {} +impl HelperTrait for Helper where ::Assoc: Sized {} + +// Evaluating this 'where' clause will (recursively) end up evaluating +// `for<'b> &'b (): 'b`, which will produce `EvaluatedToOkModuloRegions` +#[rustc_evaluate_where_clauses] +fn test(val: MyStruct) where Helper: HelperTrait { + panic!() +} + +fn foo(val: MyStruct) { + test(val); + //[with_clause]~^ ERROR evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + //[without_clause]~^^ ERROR evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOk) +} + +fn main() {} diff --git a/src/test/ui/traits/project-modulo-regions.with_clause.stderr b/src/test/ui/traits/project-modulo-regions.with_clause.stderr new file mode 100644 index 0000000000000..2434c32c81882 --- /dev/null +++ b/src/test/ui/traits/project-modulo-regions.with_clause.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/project-modulo-regions.rs:50:5 + | +LL | fn test(val: MyStruct) where Helper: HelperTrait { + | ----------- predicate +... +LL | test(val); + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/project-modulo-regions.without_clause.stderr b/src/test/ui/traits/project-modulo-regions.without_clause.stderr new file mode 100644 index 0000000000000..9d35690d5f0fe --- /dev/null +++ b/src/test/ui/traits/project-modulo-regions.without_clause.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/project-modulo-regions.rs:50:5 + | +LL | fn test(val: MyStruct) where Helper: HelperTrait { + | ----------- predicate +... +LL | test(val); + | ^^^^ + +error: aborting due to previous error +