Skip to content

Commit

Permalink
wf-check hidden types at definition site
Browse files Browse the repository at this point in the history
  • Loading branch information
aliemjay committed Aug 19, 2023
1 parent 6ef7d16 commit aec4a4f
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 7 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ where
.handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
.obligations;
self.delegate.register_obligations(obligations);
self.register_predicates([
ty::ClauseKind::WellFormed(a.into()),
ty::ClauseKind::WellFormed(b.into()),
]);
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
Ok(a)
}
Expand Down Expand Up @@ -687,6 +691,10 @@ where
}

fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([
ty::ClauseKind::WellFormed(a.into()),
ty::ClauseKind::WellFormed(b.into()),
]);
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
a.into(),
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_trait_selection/src/solve/alias_relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
Invert::Yes => (other, fresh),
};
self.sub(param_env, sub, sup)?;
self.add_goal(Goal::new(
self.tcx(),
param_env,
ty::ClauseKind::WellFormed(fresh.into()),
));
fresh
}
};
Expand Down
1 change: 1 addition & 0 deletions tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ where
{
async move { c.connect().await }
//~^ ERROR `C` does not live long enough
//~| ERROR `C` may not live long enough
}

fn main() {}
16 changes: 14 additions & 2 deletions tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ error: `C` does not live long enough
LL | async move { c.connect().await }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error[E0310]: the parameter type `C` may not live long enough
--> $DIR/erase-error-in-mir-drop-tracking.rs:19:5
|
LL | async move { c.connect().await }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | C: Client + Send + Sync + 'static,
| +++++++++

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0261`.
Some errors have detailed explanations: E0261, E0310.
For more information about an error, try `rustc --explain E0261`.
21 changes: 21 additions & 0 deletions tests/ui/impl-trait/wf-check-hidden-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Regression test for #114728.

trait Extend<'a, 'b> {
fn extend(self, _: &'a str) -> &'b str;
}

impl<'a, 'b> Extend<'a, 'b> for Option<&'b &'a ()> {
fn extend(self, s: &'a str) -> &'b str {
s
}
}

fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
None::<&'_ &'_ ()>
//~^ ERROR lifetime may not live long enough
}

fn main() {
let y = boom().extend(&String::from("temporary"));
println!("{}", y);
}
14 changes: 14 additions & 0 deletions tests/ui/impl-trait/wf-check-hidden-type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: lifetime may not live long enough
--> $DIR/wf-check-hidden-type.rs:14:5
|
LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | None::<&'_ &'_ ()>
| ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely
--> $DIR/auto-with-drop_tracking_mir.rs:25:13
--> $DIR/auto-with-drop_tracking_mir.rs:28:13
|
LL | is_send(foo());
| ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely
Expand All @@ -9,7 +9,7 @@ LL | is_send(foo());
= help: the trait `Send` is not implemented for `impl Future<Output = ()>`
= note: consider using `std::sync::Arc<impl Future<Output = ()>>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: required by a bound in `is_send`
--> $DIR/auto-with-drop_tracking_mir.rs:24:24
--> $DIR/auto-with-drop_tracking_mir.rs:27:24
|
LL | fn is_send(_: impl Send) {}
| ^^^^ required by this bound in `is_send`
Expand Down
5 changes: 4 additions & 1 deletion tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// compile-flags: -Ztrait-solver=next -Zdrop-tracking-mir
// edition: 2021
// revisions: pass fail
//[pass] check-pass
//[pass] check-fail
// WARN new-solver BUG.

#![feature(negative_impls)]

struct NotSync;
impl !Sync for NotSync {}

async fn foo() {
//[pass]~^ ERROR type mismatch
#[cfg(pass)]
let x = &();
#[cfg(fail)]
Expand All @@ -19,6 +21,7 @@ async fn foo() {
}

async fn bar() {}
//[pass]~^ ERROR type mismatch

fn main() {
fn is_send(_: impl Send) {}
Expand Down
31 changes: 31 additions & 0 deletions tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! Regression test for #114572.
//! We were inferring an ill-formed type:
//! `Opaque<'a> = Static<&'a str>`, vs
//! `Opaque<'a> = Static<&'static str>`.
// check-pass

#![feature(type_alias_impl_trait)]

struct Static<T: 'static>(T);

type OpaqueRet<'a> = impl Sized + 'a;
fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> {
msg
}

type OpaqueAssign<'a> = impl Sized + 'a;
fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
let _: OpaqueAssign<'a> = msg;
None
}

// `OpaqueRef<'a, T> = Ref<'a, T>`, vs
// `OpaqueRef<'a, T> = Ref<'static, T>`.
trait RefAt<'a>: 'a {}
struct Ref<'a, T: RefAt<'a>>(&'a T);
type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> {
msg
}

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:55:27
--> $DIR/wf-nested.rs:57:27
|
LL | type InnerOpaque<T> = impl Sized;
| ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:46:17
--> $DIR/wf-nested.rs:48:17
|
LL | let _ = outer.get();
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/type-alias-impl-trait/wf-nested.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ mod pass {
use super::*;
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
fn define<T>() -> OuterOpaque<T> {}

fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
}

// Test the soundness of `pass` - We should require `T: 'static` at the use site.
Expand Down

0 comments on commit aec4a4f

Please sign in to comment.