Skip to content

Commit

Permalink
Imply outlives-bounds on lazy type aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
fmease committed Dec 27, 2023
1 parent 2fe50cd commit 6dd1356
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 0 deletions.
26 changes: 26 additions & 0 deletions compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ pub(super) fn infer_predicates(
}
}

DefKind::TyAlias if tcx.type_alias_is_lazy(item_did) => {
insert_required_predicates_to_be_wf(
tcx,
tcx.type_of(item_did).instantiate_identity(),
tcx.def_span(item_did),
&global_inferred_outlives,
&mut item_required_predicates,
&mut explicit_map,
);
}

_ => {}
};

Expand Down Expand Up @@ -212,6 +223,21 @@ fn insert_required_predicates_to_be_wf<'tcx>(
);
}

ty::Alias(ty::Weak, alias) => {
// This corresponds to a type like `Type<'a, T>`.
// Contrary to a GAT like `<() as Trait>::Type<'a, T>`,
// we do use the own explicit predicates.
debug!("Weak");
check_explicit_predicates(
tcx,
alias.def_id,
alias.args,
required_predicates,
explicit_map,
None,
);
}

// FIXME(inherent_associated_types): Handle this case properly.
ty::Alias(ty::Inherent, _) => {}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/src/outlives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
let crate_map = tcx.inferred_outlives_crate(());
crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
}
DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => {
let crate_map = tcx.inferred_outlives_crate(());
crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
}
DefKind::AnonConst if tcx.features().generic_const_exprs => {
let id = tcx.local_def_id_to_hir_id(item_def_id);
if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Ensure that we don't imply the *implied* outlives-bounds of weak aliases.
// For context, we only imply the explicit bounds.
#![feature(lazy_type_alias)]
#![allow(incomplete_features)]

type Alias<'a, T> = &'a T; // implied bound `T: 'a`

struct Outer0<'a, T>(Alias<'a, T>); //~ ERROR the parameter type `T` may not live long enough

type Outer1<'a, T> = Alias<'a, T>; //~ ERROR the parameter type `T` may not live long enough

fn main() {}
29 changes: 29 additions & 0 deletions tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/dont-imply-implied-outlives-bounds.rs:8:22
|
LL | struct Outer0<'a, T>(Alias<'a, T>);
| -- ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| the parameter type `T` must be valid for the lifetime `'a` as defined here...
|
help: consider adding an explicit lifetime bound
|
LL | struct Outer0<'a, T: 'a>(Alias<'a, T>);
| ++++

error[E0309]: the parameter type `T` may not live long enough
--> $DIR/dont-imply-implied-outlives-bounds.rs:10:22
|
LL | type Outer1<'a, T> = Alias<'a, T>;
| -- ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| the parameter type `T` must be valid for the lifetime `'a` as defined here...
|
help: consider adding an explicit lifetime bound
|
LL | type Outer1<'a, T: 'a> = Alias<'a, T>;
| ++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0309`.
26 changes: 26 additions & 0 deletions tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: lifetime may not live long enough
--> $DIR/implied-outlives-bounds.rs:18:12
|
LL | fn env0<'any>() {
| ---- lifetime `'any` defined here
LL | let _: TypeOutlives<'static, &'any ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static`

error: lifetime may not live long enough
--> $DIR/implied-outlives-bounds.rs:23:12
|
LL | fn env1<'any>() {
| ---- lifetime `'any` defined here
LL | let _: RegionOutlives<'static, 'any>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static`

error: lifetime may not live long enough
--> $DIR/implied-outlives-bounds.rs:28:12
|
LL | fn env2<'any>() {
| ---- lifetime `'any` defined here
LL | let _: Outer0<'static, &'any ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static`

error: aborting due to 3 previous errors

31 changes: 31 additions & 0 deletions tests/ui/lazy-type-alias/implied-outlives-bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Check that we imply outlives-bounds on lazy type aliases.

// revisions: pos neg
//[pos] check-pass

#![feature(lazy_type_alias)]
#![allow(incomplete_features)]

type TypeOutlives<'a, T> = &'a T;
type RegionOutlives<'a, 'b> = &'a &'b ();

// Ensure that we imply `T: 'a` from the explicit predicates of the weak alias `Alias`.
struct Outer0<'a, T>(Alias<'a, T>);
type Alias<'a, T: 'a> = &'a T;

#[cfg(neg)]
fn env0<'any>() {
let _: TypeOutlives<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough
}

#[cfg(neg)]
fn env1<'any>() {
let _: RegionOutlives<'static, 'any>; //[neg]~ ERROR lifetime may not live long enough
}

#[cfg(neg)]
fn env2<'any>() {
let _: Outer0<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough
}

fn main() {}

0 comments on commit 6dd1356

Please sign in to comment.