From f40326027accd96214b65d44cf9c357d23de426c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 27 May 2022 20:09:06 +0000 Subject: [PATCH] Check generators for well formedness --- .../src/traits/fulfill.rs | 5 ++-- .../rustc_trait_selection/src/traits/wf.rs | 14 +++++----- .../generic-associated-types/issue-88287.rs | 2 +- .../issue-88287.stderr | 27 +++++++++++++++++++ .../ui/lifetimes/issue-76168-hr-outlives-2.rs | 22 +++++++++++++++ src/test/ui/type-alias-impl-trait/future.rs | 22 +++++++++++++++ .../ui/type-alias-impl-trait/future.stderr | 19 +++++++++++++ 7 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-88287.stderr create mode 100644 src/test/ui/lifetimes/issue-76168-hr-outlives-2.rs create mode 100644 src/test/ui/type-alias-impl-trait/future.rs create mode 100644 src/test/ui/type-alias-impl-trait/future.stderr diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 81f5dcc45b93e..34b37c4e41028 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -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>, @@ -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 = @@ -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() { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 6e23c84219145..6b758ba63cd0f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -559,7 +559,7 @@ 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 @@ -567,6 +567,8 @@ impl<'tcx> WfPredicates<'tcx> { // 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) => { @@ -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); @@ -684,6 +684,7 @@ impl<'tcx> WfPredicates<'tcx> { } } + #[instrument(level = "debug", skip(self))] fn nominal_obligations( &mut self, def_id: DefId, @@ -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()) diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs index 6b10edf073ff6..4952a082586d0 100644 --- a/src/test/ui/generic-associated-types/issue-88287.rs +++ b/src/test/ui/generic-associated-types/issue-88287.rs @@ -1,4 +1,3 @@ -// check-pass // edition:2018 #![feature(generic_associated_types)] @@ -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 } } diff --git a/src/test/ui/generic-associated-types/issue-88287.stderr b/src/test/ui/generic-associated-types/issue-88287.stderr new file mode 100644 index 0000000000000..5241d85a5f964 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88287.stderr @@ -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 `>` + --> $DIR/issue-88287.rs:25:6 + | +LL | impl SearchableResourceExt for T + | ^ required by this bound in `>` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - A: SearchableResource + ?Sized + 'f, +LL + A: SearchableResource + 'f, + | +help: consider relaxing the implicit `Sized` restriction + | +LL | T: SearchableResource + ?Sized, + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lifetimes/issue-76168-hr-outlives-2.rs b/src/test/ui/lifetimes/issue-76168-hr-outlives-2.rs new file mode 100644 index 0000000000000..348586fa26bcc --- /dev/null +++ b/src/test/ui/lifetimes/issue-76168-hr-outlives-2.rs @@ -0,0 +1,22 @@ +// edition:2018 +// check-pass + +trait Trait { + type Output; +} + +async fn walk(filter: F) +where + for<'a> F: Trait<&'a u32> + 'a, + for<'a> >::Output: 'a, +{ +} + +async fn walk2(filter: F) +where + for<'a> F: Trait<&'a u32> + 'a, + for<'a> >::Output: 'a, +{ +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/future.rs b/src/test/ui/type-alias-impl-trait/future.rs new file mode 100644 index 0000000000000..56323216effa4 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/future.rs @@ -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 = impl Future; + +fn foo(bar: B) -> FooFuture { + async move { bar.bar() } + //~^ ERROR: the trait bound `B: Bar` is not satisfied +} + +pub fn mainish(ctx: &mut std::task::Context) { + let boom: FooFuture = unsafe { core::mem::zeroed() }; + Box::pin(boom).as_mut().poll(ctx); +} diff --git a/src/test/ui/type-alias-impl-trait/future.stderr b/src/test/ui/type-alias-impl-trait/future.stderr new file mode 100644 index 0000000000000..7e76c120a2566 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/future.stderr @@ -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(bar: B) -> FooFuture { + | ^^^ required by this bound in `foo` +help: consider restricting type parameter `B` + | +LL | type FooFuture = impl Future; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.