Skip to content

Commit

Permalink
Treat weak alias types more like ADTs when computing implied bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
fmease committed Mar 11, 2024
1 parent af69f4c commit c5165ba
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 61 deletions.
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/outlives/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
) {
// If the `'a` region is bound within the field type itself, we
// don't want to propagate this constraint to the header.
if !is_free_region(outlived_region) {
if !is_early_bound_region(outlived_region) {
return;
}

Expand Down Expand Up @@ -132,7 +132,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
}

GenericArgKind::Lifetime(r) => {
if !is_free_region(r) {
if !is_early_bound_region(r) {
return;
}
required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region)).or_insert(span);
Expand All @@ -144,7 +144,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
}
}

fn is_free_region(region: Region<'_>) -> bool {
fn is_early_bound_region(region: Region<'_>) -> bool {
// First, screen for regions that might appear in a type header.
match *region {
// These correspond to `T: 'a` relationships:
Expand Down
33 changes: 17 additions & 16 deletions compiler/rustc_infer/src/infer/outlives/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn compute_components<'tcx>(
// trait-ref. Therefore, if we see any higher-ranked regions,
// we simply fallback to the most restrictive rule, which
// requires that `Pi: 'a` for all `i`.
ty::Alias(_, alias_ty) => {
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, alias_ty) => {
if !alias_ty.has_escaping_bound_vars() {
// best case: no escaping regions, so push the
// projection and skip the subtree (thus generating no
Expand Down Expand Up @@ -171,21 +171,22 @@ fn compute_components<'tcx>(
// the type and then visits the types that are lexically
// contained within. (The comments refer to relevant rules
// from RFC1214.)
ty::Bool | // OutlivesScalar
ty::Char | // OutlivesScalar
ty::Int(..) | // OutlivesScalar
ty::Uint(..) | // OutlivesScalar
ty::Float(..) | // OutlivesScalar
ty::Never | // ...
ty::Adt(..) | // OutlivesNominalType
ty::Foreign(..) | // OutlivesNominalType
ty::Str | // OutlivesScalar (ish)
ty::Slice(..) | // ...
ty::RawPtr(..) | // ...
ty::Ref(..) | // OutlivesReference
ty::Tuple(..) | // ...
ty::FnPtr(_) | // OutlivesFunction (*)
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
ty::Bool | // OutlivesScalar
ty::Char | // OutlivesScalar
ty::Int(..) | // OutlivesScalar
ty::Uint(..) | // OutlivesScalar
ty::Float(..) | // OutlivesScalar
ty::Never | // ...
ty::Adt(..) | // OutlivesNominalType
ty::Alias(ty::Weak, _) | // OutlivesNominalType (ish)
ty::Foreign(..) | // OutlivesNominalType
ty::Str | // OutlivesScalar (ish)
ty::Slice(..) | // ...
ty::RawPtr(..) | // ...
ty::Ref(..) | // OutlivesReference
ty::Tuple(..) | // ...
ty::FnPtr(_) | // OutlivesFunction (*)
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
ty::Bound(..) |
ty::Error(_) => {
// (*) Function pointers and trait objects are both binders.
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/lazy-type-alias/implied-outlives-bounds-1.print.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: rustc_outlives
--> $DIR/implied-outlives-bounds-1.rs:16:1
|
LL | struct Type<'a, K, V>(&'a mut Alias<K, V>);
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: K: 'a
= note: V: 'a

error: aborting due to 1 previous error

20 changes: 20 additions & 0 deletions tests/ui/lazy-type-alias/implied-outlives-bounds-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Check that we infer the outlives-predicates `K: 'a`, `V: 'a` for `Type`
// from the weak alias `Alias`.
// This mirrors the behavior of ADTs instead of other kinds of alias types
// like projections and opaque types.
// If we were to mirror the semantics of the latter, we would infer the
// outlives-predicate `Alias<K, V>: 'a` instead which is not what we want.

//@ revisions: default print
//@[default] check-pass

#![feature(lazy_type_alias)]
#![cfg_attr(print, feature(rustc_attrs))]
#![allow(incomplete_features)]

#[cfg_attr(print, rustc_outlives)]
struct Type<'a, K, V>(&'a mut Alias<K, V>); //[print]~ ERROR rustc_outlives

type Alias<K, V> = (K, V);

fn main() {}
2 changes: 0 additions & 2 deletions tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod test_lifetime_param {
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}

mod test_higher_kinded_lifetime_param {
Expand All @@ -27,7 +26,6 @@ mod test_type_param {
fn defining<A>(s: A) -> Ty<A> { s }
fn assert_static<A: 'static>() {}
fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
//~^ ERROR: parameter type `A` may not live long enough
}

mod test_implied_from_fn_sig {
Expand Down
27 changes: 3 additions & 24 deletions tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
Original file line number Diff line number Diff line change
@@ -1,37 +1,16 @@
error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:7:43
|
LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`

error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:15:46
--> $DIR/implied_lifetime_wf_check3.rs:14:46
|
LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`

error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:21:21
--> $DIR/implied_lifetime_wf_check3.rs:20:21
|
LL | fn test<'a>() { assert_static::<'a>() }
| -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
| |
| lifetime `'a` defined here

error[E0310]: the parameter type `A` may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:29:41
|
LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
| ^^^^^^^^^^^^^^^^^^
| |
| the parameter type `A` must be valid for the static lifetime...
| ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() }
| +++++++++

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0310`.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ mod test_type_param_static {
fn defining<A: 'static>(s: A) -> Ty<A> { s }
fn assert_static<A: 'static>() {}
fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
//~^ ERROR: the parameter type `A` may not live long enough
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,6 @@ help: consider adding an explicit lifetime bound
LL | type Ty<A: 'static> = impl Sized + 'static;
| +++++++++

error[E0310]: the parameter type `A` may not live long enough
--> $DIR/implied_lifetime_wf_check4_static.rs:8:41
|
LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
| ^^^^^^^^^^^^^^^^^^
| |
| the parameter type `A` must be valid for the static lifetime...
| ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() }
| +++++++++

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0310`.

0 comments on commit c5165ba

Please sign in to comment.