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 Dec 7, 2024
1 parent 5a0a5e6 commit 0e7952c
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 50 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ fn check_explicit_predicates<'tcx>(
}
}

/// Check the inferred predicates declared on the type.
/// Check the inferred predicates of the type.
///
/// ### Example
///
Expand Down
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
3 changes: 2 additions & 1 deletion compiler/rustc_type_ir/src/outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
// 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::Opaque | ty::Inherent, 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 @@ -195,6 +195,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
}

ty::Adt(_, _)
| ty::Alias(ty::Weak, _)
| ty::Foreign(_)
| ty::Array(_, _)
| ty::Pat(_, _)
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 @@ -12,7 +12,6 @@ where
test_lifetime_param::Ty<'a>: 'static,
{
test_lifetime_param::assert_static::<'a>()
//~^ ERROR: lifetime may not live long enough
}

mod test_higher_kinded_lifetime_param {
Expand Down Expand Up @@ -50,7 +49,6 @@ where
test_type_param::Ty<A>: 'static,
{
test_type_param::assert_static::<A>()
//~^ ERROR: parameter type `A` may not live long enough
}

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

error: lifetime may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:29:5
--> $DIR/implied_lifetime_wf_check3.rs:28:5
|
LL | fn test_higher_kinded_lifetime_param_test<'a>()
| -- lifetime `'a` defined here
Expand All @@ -17,27 +8,12 @@ LL | test_higher_kinded_lifetime_param::assert_static::<'a>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`

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

error[E0310]: the parameter type `A` may not live long enough
--> $DIR/implied_lifetime_wf_check3.rs:52:5
|
LL | test_type_param::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_type_param_test<A: 'static>()
| +++++++++

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 @@ -15,7 +15,6 @@ 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 @@ -17,20 +17,6 @@ help: consider adding an explicit lifetime bound
LL | pub 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:17:5
|
LL | 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>()
| +++++++++

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 0e7952c

Please sign in to comment.