From a37b0a20d65aae7a175a123c4aaf1e266d363285 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 29 Nov 2020 21:44:32 +0000 Subject: [PATCH] Check projection predicates satisfy bounds This restores the behavior from before #73905. --- .../rustc_trait_selection/src/traits/wf.rs | 22 +++++++++- .../associate-type-bound-wf.rs | 17 ++++++++ .../associate-type-bound-wf.stderr | 41 +++++++++++++++++++ .../collections-project-default.rs | 11 +++-- .../collections-project-default.stderr | 2 +- .../generic-associated-types/collections.rs | 11 +++-- 6 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/associated-types/associate-type-bound-wf.rs create mode 100644 src/test/ui/associated-types/associate-type-bound-wf.stderr diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 5bcb16d21e09c..bc86ac4ca26b9 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -4,7 +4,7 @@ use crate::traits; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_span::Span; @@ -117,6 +117,26 @@ pub fn predicate_obligations<'a, 'tcx>( ty::PredicateAtom::Projection(t) => { wf.compute_projection(t.projection_ty); wf.compute(t.ty.into()); + + // Check item bounds apply. + // + // This is relying on this predicate being used to normalize any + // bounds. For example, for the projection predicate `::Item = U` we will get a bound `::Item: + // Sized`, which then normalizes to `U: Sized`. + let bounds = infcx.tcx.explicit_item_bounds(t.projection_ty.item_def_id); + let bound_obligations: Vec<_> = bounds + .iter() + .map(|&(bound, span)| { + traits::Obligation::new( + wf.cause(traits::BindingObligation(t.projection_ty.item_def_id, span)), + param_env, + bound.subst(infcx.tcx, t.projection_ty.substs), + ) + }) + .filter(|arg| !arg.has_escaping_bound_vars()) + .collect(); + wf.out.extend(bound_obligations); } ty::PredicateAtom::WellFormed(arg) => { wf.compute(arg); diff --git a/src/test/ui/associated-types/associate-type-bound-wf.rs b/src/test/ui/associated-types/associate-type-bound-wf.rs new file mode 100644 index 0000000000000..3b45a6d2dac9f --- /dev/null +++ b/src/test/ui/associated-types/associate-type-bound-wf.rs @@ -0,0 +1,17 @@ +//Regression test for #78893 + +trait TwoAssocTypes { + type X; + type Y; +} + +fn object_iterator>() {} +//~^ ERROR the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + +fn parameter_iterator(_: impl Iterator) {} +//~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time + +fn unsized_object>() {} +//~^ ERROR the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + +fn main() {} diff --git a/src/test/ui/associated-types/associate-type-bound-wf.stderr b/src/test/ui/associated-types/associate-type-bound-wf.stderr new file mode 100644 index 0000000000000..4ead136731d22 --- /dev/null +++ b/src/test/ui/associated-types/associate-type-bound-wf.stderr @@ -0,0 +1,41 @@ +error[E0277]: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + --> $DIR/associate-type-bound-wf.rs:8:32 + | +LL | fn object_iterator>() {} + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | type Item; + | ---------- required by this bound in `std::iter::Iterator::Item` + | + = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` + +error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time + --> $DIR/associate-type-bound-wf.rs:11:40 + | +LL | fn parameter_iterator(_: impl Iterator) {} + | ^^^^^^^----------- + | | | + | | this type parameter needs to be `Sized` + | doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | type Item; + | ---------- required by this bound in `std::iter::Iterator::Item` + +error[E0277]: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + --> $DIR/associate-type-bound-wf.rs:14:44 + | +LL | type Y; + | ------- required by this bound in `TwoAssocTypes::Y` +... +LL | fn unsized_object>() {} + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs index 5fbae02573c62..ac85643d75541 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.rs +++ b/src/test/ui/generic-associated-types/collections-project-default.rs @@ -9,7 +9,9 @@ // check that we don't normalize with trait defaults. trait Collection { - type Iter<'iter>: Iterator where T: 'iter; + type Iter<'iter>: Iterator + where + T: 'iter; type Family: CollectionFamily; // Test associated type defaults with parameters type Sibling: Collection = @@ -22,7 +24,7 @@ trait Collection { fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; } -trait CollectionFamily { +trait CollectionFamily: Sized { type Member: Collection; } @@ -33,7 +35,10 @@ impl CollectionFamily for VecFamily { } impl Collection for Vec { - type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>; + type Iter<'iter> + where + T: 'iter, + = std::slice::Iter<'iter, T>; type Family = VecFamily; fn empty() -> Self { diff --git a/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr index ca02b2603ba64..985bd4e07f496 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.stderr +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/collections-project-default.rs:60:5 + --> $DIR/collections-project-default.rs:65:5 | LL | fn floatify_sibling(ints: &C) -> >::Sibling | ------------------------------------ expected `>::Sibling` because of return type diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs index 1b5b9c181fb61..d5a0c0405be4d 100644 --- a/src/test/ui/generic-associated-types/collections.rs +++ b/src/test/ui/generic-associated-types/collections.rs @@ -9,7 +9,9 @@ // run-pass trait Collection { - type Iter<'iter>: Iterator where T: 'iter; + type Iter<'iter>: Iterator + where + T: 'iter; type Family: CollectionFamily; // Test associated type defaults with parameters type Sibling: Collection = @@ -22,7 +24,7 @@ trait Collection { fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; } -trait CollectionFamily { +trait CollectionFamily: Sized { type Member: Collection; } @@ -33,7 +35,10 @@ impl CollectionFamily for VecFamily { } impl Collection for Vec { - type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>; + type Iter<'iter> + where + T: 'iter, + = std::slice::Iter<'iter, T>; type Family = VecFamily; fn empty() -> Self {