Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 `<T as
// Iterator>::Item = U` we will get a bound `<T as Iterator>::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),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So -- where I got stuck here was that I assumed we would need to normalize after substitution. Does that happen elsewhere?

(I still feel like (not in this PR...) I'd like to explore having the "bounds" predicate return a Binder<Predicate>, with the binder being the "self" type.)

)
})
.filter(|arg| !arg.has_escaping_bound_vars())
.collect();
wf.out.extend(bound_obligations);
}
ty::PredicateAtom::WellFormed(arg) => {
wf.compute(arg);
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/associated-types/associate-type-bound-wf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//Regression test for #78893

trait TwoAssocTypes {
type X;
type Y;
}

fn object_iterator<T: Iterator<Item = dyn Fn()>>() {}
//~^ ERROR the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time

fn parameter_iterator(_: impl Iterator<Item = impl ?Sized>) {}
//~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time

fn unsized_object<T: TwoAssocTypes<X = (), Y = dyn Fn()>>() {}
//~^ ERROR the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time

fn main() {}
41 changes: 41 additions & 0 deletions src/test/ui/associated-types/associate-type-bound-wf.stderr
Original file line number Diff line number Diff line change
@@ -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<T: Iterator<Item = dyn Fn()>>() {}
| ^^^^^^^^^^^^^^^ 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<Item = impl ?Sized>) {}
| ^^^^^^^-----------
| | |
| | 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<T: TwoAssocTypes<X = (), Y = dyn Fn()>>() {}
| ^^^^^^^^^^^^ 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`.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
// check that we don't normalize with trait defaults.

trait Collection<T> {
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
type Iter<'iter>: Iterator<Item = &'iter T>
where
T: 'iter;
type Family: CollectionFamily;
// Test associated type defaults with parameters
type Sibling<U>: Collection<U> =
Expand All @@ -22,7 +24,7 @@ trait Collection<T> {
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
}

trait CollectionFamily {
trait CollectionFamily: Sized {
type Member<T>: Collection<T, Family = Self>;
}

Expand All @@ -33,7 +35,10 @@ impl CollectionFamily for VecFamily {
}

impl<T> Collection<T> for Vec<T> {
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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
| ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
Expand Down
11 changes: 8 additions & 3 deletions src/test/ui/generic-associated-types/collections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
// run-pass

trait Collection<T> {
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
type Iter<'iter>: Iterator<Item = &'iter T>
where
T: 'iter;
type Family: CollectionFamily;
// Test associated type defaults with parameters
type Sibling<U>: Collection<U> =
Expand All @@ -22,7 +24,7 @@ trait Collection<T> {
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
}

trait CollectionFamily {
trait CollectionFamily: Sized {
type Member<T>: Collection<T, Family = Self>;
}

Expand All @@ -33,7 +35,10 @@ impl CollectionFamily for VecFamily {
}

impl<T> Collection<T> for Vec<T> {
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 {
Expand Down