Skip to content

Commit

Permalink
Rollup merge of rust-lang#97183 - oli-obk:tait_ice_async, r=jackh726
Browse files Browse the repository at this point in the history
wf-check generators

fixes rust-lang#90409

We should not rely on generators being well formed by construction now that they can get used via type alias impl trait (and thus users can choose generic arguments that are invalid). This can cause surprising behaviour if (definitely unsound) transmutes are used, and it's generally saner to just check for well formedness.
  • Loading branch information
Dylan-DPC committed Jul 19, 2022
2 parents 96c2df8 + f403260 commit b9a008a
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 10 deletions.
5 changes: 2 additions & 3 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
/// This is called much less often than `needs_process_obligation`, so we
/// never inline it.
#[inline(never)]
#[instrument(level = "debug", skip(self, pending_obligation))]
fn process_obligation(
&mut self,
pending_obligation: &mut PendingPredicateObligation<'tcx>,
Expand All @@ -303,7 +304,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {

let obligation = &mut pending_obligation.obligation;

debug!(?obligation, "process_obligation pre-resolve");
debug!(?obligation, "pre-resolve");

if obligation.predicate.has_infer_types_or_consts() {
obligation.predicate =
Expand All @@ -312,8 +313,6 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {

let obligation = &pending_obligation.obligation;

debug!(?obligation, ?obligation.cause, "process_obligation");

let infcx = self.selcx.infcx();

if obligation.predicate.has_projections() {
Expand Down
14 changes: 8 additions & 6 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,14 +559,16 @@ impl<'tcx> WfPredicates<'tcx> {
}
}

ty::Generator(..) => {
ty::Generator(did, substs, ..) => {
// Walk ALL the types in the generator: this will
// include the upvar types as well as the yield
// type. Note that this is mildly distinct from
// the closure case, where we have to be careful
// about the signature of the closure. We don't
// have the problem of implied bounds here since
// generators don't take arguments.
let obligations = self.nominal_obligations(did, substs);
self.out.extend(obligations);
}

ty::Closure(did, substs) => {
Expand Down Expand Up @@ -618,11 +620,9 @@ impl<'tcx> WfPredicates<'tcx> {
}

ty::Opaque(did, substs) => {
// all of the requirements on type parameters
// should've been checked by the instantiation
// of whatever returned this exact `impl Trait`.

// for named opaque `impl Trait` types we still need to check them
// All of the requirements on type parameters
// have already been checked for `impl Trait` in
// return position. We do need to check type-alias-impl-trait though.
if ty::is_impl_trait_defn(self.tcx, did).is_none() {
let obligations = self.nominal_obligations(did, substs);
self.out.extend(obligations);
Expand Down Expand Up @@ -684,6 +684,7 @@ impl<'tcx> WfPredicates<'tcx> {
}
}

#[instrument(level = "debug", skip(self))]
fn nominal_obligations(
&mut self,
def_id: DefId,
Expand All @@ -698,6 +699,7 @@ impl<'tcx> WfPredicates<'tcx> {
}

let predicates = predicates.instantiate(self.tcx, substs);
trace!("{:#?}", predicates);
debug_assert_eq!(predicates.predicates.len(), origins.len());

iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/generic-associated-types/issue-88287.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// check-pass
// edition:2018

#![feature(generic_associated_types)]
Expand Down Expand Up @@ -34,6 +33,7 @@ where

fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
async move { todo!() }
//~^ ERROR: the size for values of type `A` cannot be known at compilation time
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/test/ui/generic-associated-types/issue-88287.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/issue-88287.rs:35:9
|
LL | type SearchFutureTy<'f, A, B: 'f>
| - this type parameter needs to be `std::marker::Sized`
...
LL | async move { todo!() }
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required by a bound in `<T as SearchableResourceExt<Criteria>>`
--> $DIR/issue-88287.rs:25:6
|
LL | impl<T, Criteria> SearchableResourceExt<Criteria> for T
| ^ required by this bound in `<T as SearchableResourceExt<Criteria>>`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - A: SearchableResource<B> + ?Sized + 'f,
LL + A: SearchableResource<B> + 'f,
|
help: consider relaxing the implicit `Sized` restriction
|
LL | T: SearchableResource<Criteria> + ?Sized,
| ++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
22 changes: 22 additions & 0 deletions src/test/ui/lifetimes/issue-76168-hr-outlives-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// edition:2018
// check-pass

trait Trait<Input> {
type Output;
}

async fn walk<F>(filter: F)
where
for<'a> F: Trait<&'a u32> + 'a,
for<'a> <F as Trait<&'a u32>>::Output: 'a,
{
}

async fn walk2<F: 'static>(filter: F)
where
for<'a> F: Trait<&'a u32> + 'a,
for<'a> <F as Trait<&'a u32>>::Output: 'a,
{
}

fn main() {}
22 changes: 22 additions & 0 deletions src/test/ui/type-alias-impl-trait/future.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![feature(type_alias_impl_trait)]

// edition:2021
// compile-flags: --crate-type=lib

use std::future::Future;

trait Bar {
fn bar(&self);
}

type FooFuture<B> = impl Future<Output = ()>;

fn foo<B: Bar>(bar: B) -> FooFuture<B> {
async move { bar.bar() }
//~^ ERROR: the trait bound `B: Bar` is not satisfied
}

pub fn mainish(ctx: &mut std::task::Context) {
let boom: FooFuture<u32> = unsafe { core::mem::zeroed() };
Box::pin(boom).as_mut().poll(ctx);
}
19 changes: 19 additions & 0 deletions src/test/ui/type-alias-impl-trait/future.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0277]: the trait bound `B: Bar` is not satisfied
--> $DIR/future.rs:15:5
|
LL | async move { bar.bar() }
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
note: required by a bound in `foo`
--> $DIR/future.rs:14:11
|
LL | fn foo<B: Bar>(bar: B) -> FooFuture<B> {
| ^^^ required by this bound in `foo`
help: consider restricting type parameter `B`
|
LL | type FooFuture<B: Bar> = impl Future<Output = ()>;
| +++++

error: aborting due to previous error

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

0 comments on commit b9a008a

Please sign in to comment.