diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2eefe1eb3e922..0cbac5b891d10 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,14 +1,15 @@ use std::assert_matches::assert_matches; use hir::Node; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::find_attr; use rustc_middle::ty::{ - self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, + self, Binder, Clause, GenericArgKind, GenericArgs, GenericPredicates, ImplTraitInTraitData, Ty, + TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable, TypeVisitor, Upcast, UpcastFrom, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; @@ -31,6 +32,11 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic let mut result = tcx.explicit_predicates_of(def_id); debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result); + let implied_item_bounds = elaborate_projection_predicates(tcx, result.predicates.to_vec()); + result.predicates = tcx + .arena + .alloc_from_iter(result.predicates.into_iter().copied().chain(implied_item_bounds)); + let inferred_outlives = tcx.inferred_outlives_of(def_id); if !inferred_outlives.is_empty() { debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,); @@ -77,6 +83,150 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic debug!("predicates_of({:?}) = {:?}", def_id, result); result } +// If the term of projection is a generic param, we try to add implied item bounds to predicates. +// FIXME: nested binders and the case that item bound contains bound vars are not handled. +fn elaborate_projection_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: Vec<(Clause<'tcx>, Span)>, +) -> Vec<(ty::Clause<'tcx>, Span)> { + struct PredicateArgFolder<'tcx> { + tcx: TyCtxt<'tcx>, + ty_mapping: FxHashMap, Ty<'tcx>>, + region_mapping: FxHashMap, ty::Region<'tcx>>, + const_mapping: FxHashMap, ty::Const<'tcx>>, + } + impl<'tcx> PredicateArgFolder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, projection: ty::ProjectionPredicate<'tcx>) -> Self { + let mut ty_mapping = FxHashMap::default(); + let mut region_mapping = FxHashMap::default(); + let mut const_mapping = FxHashMap::default(); + let assoc_ty = Ty::new_alias( + tcx, + ty::AliasTyKind::Projection, + ty::AliasTy::new( + tcx, + projection.projection_term.def_id, + GenericArgs::identity_for_item(tcx, projection.projection_term.def_id), + ), + ); + ty_mapping.insert(assoc_ty, projection.term.expect_type()); + let target_assoc_args = + GenericArgs::identity_for_item(tcx, projection.projection_term.def_id); + for (target_arg, proj_arg) in + target_assoc_args.into_iter().zip(projection.projection_term.args) + { + match (target_arg.kind(), proj_arg.kind()) { + (GenericArgKind::Lifetime(r1), GenericArgKind::Lifetime(r2)) => { + region_mapping.insert(r1, r2); + } + (GenericArgKind::Type(t1), GenericArgKind::Type(t2)) => { + ty_mapping.insert(t1, t2); + } + (GenericArgKind::Const(c1), GenericArgKind::Const(c2)) => { + const_mapping.insert(c1, c2); + } + _ => bug!("mismatched generic arg kinds in projection predicate"), + } + } + debug!( + "elaborate_projection_predicates: ty_mapping = {:?}, region_mapping = {:?}, const_mapping = {:?}", + ty_mapping, region_mapping, const_mapping + ); + Self { tcx, ty_mapping, region_mapping, const_mapping } + } + } + impl<'tcx> ty::TypeFolder> for PredicateArgFolder<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + if let Some(replacement) = self.ty_mapping.get(&t) { + *replacement + } else { + t.super_fold_with(self) + } + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let Some(replacement) = self.region_mapping.get(&r) { *replacement } else { r } + } + + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + if let Some(replacement) = self.const_mapping.get(&c) { *replacement } else { c } + } + } + + let mut new_preds = Vec::new(); + for (pred, _span) in &predicates { + if let ty::ClauseKind::Projection(proj_pred) = pred.kind().skip_binder() + && let Some(proj_ty) = proj_pred.term.as_type() + { + // We should minimize this to allow the where clause check to be useful. + fn should_add_clause(t: Ty<'_>) -> bool { + match t.kind() { + ty::Param(_) => true, + ty::Alias(ty::Projection, alias) => alias.args.types().any(should_add_clause), + _ => false, + } + } + if !should_add_clause(proj_ty) { + continue; + } + debug!("elaborate_projection_predicates: projection predicate = {:?}", pred); + let assoc_bounds = tcx.explicit_item_bounds(proj_pred.projection_term.def_id); + debug!("elaborate_projection_predicates: original assoc_bounds = {:?}", assoc_bounds); + let mut folder = PredicateArgFolder::new(tcx, proj_pred); + // FIXME: optimize allocation later. + let assoc_bounds: Vec<_> = assoc_bounds + .skip_binder() + .iter() + .map(|(c, span)| { + ( + Binder::bind_with_vars( + c.kind().skip_binder().fold_with(&mut folder), + pred.kind().bound_vars(), + ), + *span, + ) + }) + .filter(|(c, _)| { + if let ty::ClauseKind::Projection(p) = c.skip_binder() { + if p.projection_term.to_term(tcx) == p.term { + // No need to add identity projection. + // They cause cycles later. + return false; + } + // We shouldn't add opposite projection of existing ones. + // They will be normalized to identity projection by each other. + // We also filter out projections which have the same lhs with existing + // projections. + // They cause ambiguity in normalization. + if predicates.iter().any(|(existing_c, _)| { + if let ty::ClauseKind::Projection(existing_p) = + existing_c.kind().skip_binder() + { + return p.projection_term == existing_p.projection_term + || (existing_p.projection_term.to_term(tcx) == p.term + && existing_p.term == p.projection_term.to_term(tcx)); + } + false + }) { + return false; + } + } + true + }) + .collect(); + debug!("elaborate_projection_predicates: replaced assoc_bounds = {:?}", assoc_bounds); + let assoc_bounds: Vec<_> = + assoc_bounds.into_iter().map(|(c, s)| (Clause::upcast_from(c, tcx), s)).collect(); + debug!("elaborate_projection_predicates: upcasted assoc_bounds = {:?}", assoc_bounds); + new_preds.extend(assoc_bounds); + } + } + new_preds +} /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index db7bd635f32e6..15a6ad2fca154 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -183,8 +183,7 @@ pub fn clause_obligations<'tcx>( wf.add_wf_preds_for_term(ty.into()); } ty::ClauseKind::Projection(t) => { - wf.add_wf_preds_for_alias_term(t.projection_term); - wf.add_wf_preds_for_term(t.term); + wf.add_wf_preds_for_projection_pred(t); } ty::ClauseKind::ConstArgHasType(ct, ty) => { wf.add_wf_preds_for_term(ct.into()); @@ -455,6 +454,50 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + fn add_wf_preds_for_projection_pred(&mut self, projection_pred: ty::ProjectionPredicate<'tcx>) { + let tcx = self.tcx(); + let cause = self.cause(ObligationCauseCode::WellFormed(None)); + debug!("add_wf_preds_for_projection_pred {:?}", projection_pred); + + fn is_total_generic(t: Ty<'_>) -> bool { + match t.kind() { + ty::Param(_) => true, + ty::Alias(ty::Projection, alias) => alias.args.types().all(is_total_generic), + _ => false, + } + } + // Add item bounds to the predicate term. + // If the term is generic, we can skip these item bounds as they're implied by `AliasBound`. + if let Some(normalizes_to_ty) = projection_pred.term.as_type() + && !is_total_generic(normalizes_to_ty) + { + let bounds = tcx.item_bounds(projection_pred.def_id()); + debug!("add_wf_preds_for_projection_pred item_bounds={:?}", bounds); + let bound_obligations: Vec<_> = bounds + .instantiate(tcx, projection_pred.projection_term.args) + .iter() + .filter_map(|bound| { + if !bound.has_escaping_bound_vars() { + Some(traits::Obligation::with_depth( + tcx, + cause.clone(), + self.recursion_depth, + self.param_env, + bound, + )) + } else { + None + } + }) + .collect(); + debug!("add_wf_preds_for_projection_pred bound_obligations={:?}", bound_obligations); + self.out.extend(bound_obligations); + } + + self.add_wf_preds_for_alias_term(projection_pred.projection_term); + self.add_wf_preds_for_term(projection_pred.term); + } + /// Pushes the obligations required for an alias (except inherent) to be WF /// into `self.out`. fn add_wf_preds_for_alias_term(&mut self, data: ty::AliasTerm<'tcx>) { @@ -480,6 +523,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // `i32: Copy` // ] let obligations = self.nominal_obligations(data.def_id, data.args); + debug!("add_wf_preds_for_alias_term nominal_obligations={:?}", obligations); self.out.extend(obligations); self.add_wf_preds_for_projection_args(data.args); diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs index 41857eca87de6..6e1064eb2fa40 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs +++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs @@ -23,6 +23,6 @@ trait SuperTrait { fn take0(_: impl Trait) {} -fn take1(_: impl Trait) {} +fn take1(_: impl Trait) {} fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.rs b/tests/ui/associated-type-bounds/issue-102335-ty.rs index 86bde6367a4cc..d453037d1f3ae 100644 --- a/tests/ui/associated-type-bounds/issue-102335-ty.rs +++ b/tests/ui/associated-type-bounds/issue-102335-ty.rs @@ -2,12 +2,14 @@ trait T { type A: S = ()>; // Just one erroneous equality constraint //~^ ERROR associated item constraints are not allowed here //~| ERROR associated item constraints are not allowed here + //~| ERROR: the trait bound `(): Q` is not satisfied [E0277] } trait T2 { type A: S = ()>; // More than one erroneous equality constraints //~^ ERROR associated item constraints are not allowed here //~| ERROR associated item constraints are not allowed here + //~| ERROR: the trait bound `(): Q` is not satisfied [E0277] } trait Q {} diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr index 259b0ca00e1b3..136b19dc3b6fa 100644 --- a/tests/ui/associated-type-bounds/issue-102335-ty.stderr +++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr @@ -23,8 +23,20 @@ LL - type A: S = ()>; // Just one erroneous equality constraint LL + type A: S; // Just one erroneous equality constraint | +error[E0277]: the trait bound `(): Q` is not satisfied + --> $DIR/issue-102335-ty.rs:2:15 + | +LL | type A: S = ()>; // Just one erroneous equality constraint + | ^^^^^^^^^^^^^^^^^ the trait `Q` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-102335-ty.rs:15:1 + | +LL | trait Q {} + | ^^^^^^^ + error[E0229]: associated item constraints are not allowed here - --> $DIR/issue-102335-ty.rs:8:17 + --> $DIR/issue-102335-ty.rs:9:17 | LL | type A: S = ()>; // More than one erroneous equality constraints | ^^^^^^^^^ associated item constraint not allowed here @@ -36,7 +48,7 @@ LL + type A: S = ()>; // More than one erroneous equality constra | error[E0229]: associated item constraints are not allowed here - --> $DIR/issue-102335-ty.rs:8:17 + --> $DIR/issue-102335-ty.rs:9:17 | LL | type A: S = ()>; // More than one erroneous equality constraints | ^^^^^^^^^ associated item constraint not allowed here @@ -48,6 +60,19 @@ LL - type A: S = ()>; // More than one erroneous equal LL + type A: S = ()>; // More than one erroneous equality constraints | -error: aborting due to 4 previous errors +error[E0277]: the trait bound `(): Q` is not satisfied + --> $DIR/issue-102335-ty.rs:9:15 + | +LL | type A: S = ()>; // More than one erroneous equality constraints + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Q` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-102335-ty.rs:15:1 + | +LL | trait Q {} + | ^^^^^^^ + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0229`. +Some errors have detailed explanations: E0229, E0277. +For more information about an error, try `rustc --explain E0229`. diff --git a/tests/ui/async-await/async-fn/dyn-in-return-type.fixed b/tests/ui/async-await/async-fn/dyn-in-return-type.fixed index 6a717f628460e..8ac21f0192a3a 100644 --- a/tests/ui/async-await/async-fn/dyn-in-return-type.fixed +++ b/tests/ui/async-await/async-fn/dyn-in-return-type.fixed @@ -12,6 +12,8 @@ trait T { //~^ ERROR return type cannot be a trait object without pointer indirection //~| HELP consider returning an `impl Trait` instead of a `dyn Trait` //~| HELP alternatively, box the return type, and wrap all of the returned values in `Box::new` + //~| ERROR: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time [E0277] + //~| HELP: the trait `Sized` is not implemented for `(dyn Debug + 'static)` Box::new("") } } diff --git a/tests/ui/async-await/async-fn/dyn-in-return-type.rs b/tests/ui/async-await/async-fn/dyn-in-return-type.rs index 47d5e371f55f6..94d886286c816 100644 --- a/tests/ui/async-await/async-fn/dyn-in-return-type.rs +++ b/tests/ui/async-await/async-fn/dyn-in-return-type.rs @@ -12,6 +12,8 @@ trait T { //~^ ERROR return type cannot be a trait object without pointer indirection //~| HELP consider returning an `impl Trait` instead of a `dyn Trait` //~| HELP alternatively, box the return type, and wrap all of the returned values in `Box::new` + //~| ERROR: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time [E0277] + //~| HELP: the trait `Sized` is not implemented for `(dyn Debug + 'static)` Box::new("") } } diff --git a/tests/ui/async-await/async-fn/dyn-in-return-type.stderr b/tests/ui/async-await/async-fn/dyn-in-return-type.stderr index 0d8a92d33cf9a..ebc1e67b5e662 100644 --- a/tests/ui/async-await/async-fn/dyn-in-return-type.stderr +++ b/tests/ui/async-await/async-fn/dyn-in-return-type.stderr @@ -31,7 +31,7 @@ LL | async fn f(&self) -> Box { | ++++ + error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-in-return-type.rs:19:26 + --> $DIR/dyn-in-return-type.rs:21:26 | LL | async fn f(&self) -> dyn core::fmt::Debug { | ^^^^^^^^^^^^^^^^^^^^ @@ -46,6 +46,15 @@ help: alternatively, box the return type, and wrap all of the returned values in LL | async fn f(&self) -> Box { | ++++ + -error: aborting due to 3 previous errors +error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time + --> $DIR/dyn-in-return-type.rs:11:26 + | +LL | async fn f(&self) -> dyn core::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0746`. +Some errors have detailed explanations: E0277, E0746. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/issue-111932.rs b/tests/ui/closures/issue-111932.rs index eb3fe08cbc409..c1a39b5ba5f05 100644 --- a/tests/ui/closures/issue-111932.rs +++ b/tests/ui/closures/issue-111932.rs @@ -1,6 +1,6 @@ trait Foo: std::fmt::Debug {} -fn print_foos(foos: impl Iterator) { +fn print_foos(foos: impl Iterator) { //~ ERROR [E0277] foos.for_each(|foo| { //~ ERROR [E0277] println!("{:?}", foo); //~ ERROR [E0277] }); diff --git a/tests/ui/closures/issue-111932.stderr b/tests/ui/closures/issue-111932.stderr index fc3b7b0c6e662..dbf8c1725a5e0 100644 --- a/tests/ui/closures/issue-111932.stderr +++ b/tests/ui/closures/issue-111932.stderr @@ -1,3 +1,11 @@ +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/issue-111932.rs:3:35 + | +LL | fn print_foos(foos: impl Iterator) { + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time --> $DIR/issue-111932.rs:4:20 | @@ -19,6 +27,6 @@ LL | println!("{:?}", foo); = help: the trait `Sized` is not implemented for `dyn Foo` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs index 3a85b86cb1fdd..544a56712cff6 100644 --- a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs +++ b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs @@ -1,5 +1,6 @@ trait Trait { type Assoc; + //~^ ERROR: `Drop` impl requires `U: Sized` but the struct it is implemented for does not [E0367] } struct Foo(T, U); diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr index dab8c55d0e7f3..3863dfa635a3d 100644 --- a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr +++ b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr @@ -1,15 +1,27 @@ error[E0367]: `Drop` impl requires `::Assoc == U` but the struct it is implemented for does not - --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:7:15 + --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:8:15 | LL | impl, U: ?Sized> Drop for Foo { | ^^^^^^^^^ | note: the implementor must specify the same requirement - --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:5:1 + --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:6:1 | LL | struct Foo(T, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0367]: `Drop` impl requires `U: Sized` but the struct it is implemented for does not + --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:2:5 + | +LL | type Assoc; + | ^^^^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:6:1 + | +LL | struct Foo(T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dropck/dropck-only-error-gat.rs b/tests/ui/dropck/dropck-only-error-gat.rs index dadcf76a43f35..86de04e4cf868 100644 --- a/tests/ui/dropck/dropck-only-error-gat.rs +++ b/tests/ui/dropck/dropck-only-error-gat.rs @@ -1,3 +1,5 @@ +//@ check-pass +// // Test that we don't ICE for a typeck error that only shows up in dropck // Version that uses a generic associated type // Regression test for #91985 @@ -35,7 +37,6 @@ where T2: Trait2, { pub fn new() -> Self { - //~^ ERROR the trait bound `::Associated: Clone` is not satisfied todo!() } } diff --git a/tests/ui/dropck/dropck-only-error-gat.stderr b/tests/ui/dropck/dropck-only-error-gat.stderr deleted file mode 100644 index 53982c0826a74..0000000000000 --- a/tests/ui/dropck/dropck-only-error-gat.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `::Associated: Clone` is not satisfied - --> $DIR/dropck-only-error-gat.rs:37:21 - | -LL | pub fn new() -> Self { - | ^^^^ the trait `Clone` is not implemented for `::Associated` - | -note: required by a bound in `GatTrait::Gat` - --> $DIR/dropck-only-error-gat.rs:14:17 - | -LL | type Gat; - | ^^^^^ required by this bound in `GatTrait::Gat` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs index d3c3963a673d5..49c38d7ddfe0f 100644 --- a/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs +++ b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs @@ -10,11 +10,11 @@ pub trait Service { pub trait A1: Service {} -pub trait A2: Service>> + A1 { +pub trait A2: Service + Unpin>> + A1 { fn foo(&self) {} } -pub trait B1: Service>> {} +pub trait B1: Service + Unpin>> {} pub trait B2: Service + B1 { fn foo(&self) {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.rs b/tests/ui/generic-associated-types/issue-102335-gat.rs index 0be6ee3930f11..c6847e9afa70f 100644 --- a/tests/ui/generic-associated-types/issue-102335-gat.rs +++ b/tests/ui/generic-associated-types/issue-102335-gat.rs @@ -2,6 +2,7 @@ trait T { type A: S = ()>; //~^ ERROR associated item constraints are not allowed here //~| ERROR associated item constraints are not allowed here + //~| ERROR: the trait bound `(): Q` is not satisfied [E0277] } trait Q {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr index bcef76290fcdc..d65f30ba203f6 100644 --- a/tests/ui/generic-associated-types/issue-102335-gat.stderr +++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr @@ -23,6 +23,19 @@ LL - type A: S = ()>; LL + type A: S = ()>; | -error: aborting due to 2 previous errors +error[E0277]: the trait bound `(): Q` is not satisfied + --> $DIR/issue-102335-gat.rs:2:15 + | +LL | type A: S = ()>; + | ^^^^^^^^^^^^^^^^^^^^ the trait `Q` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-102335-gat.rs:8:1 + | +LL | trait Q {} + | ^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0229`. +Some errors have detailed explanations: E0229, E0277. +For more information about an error, try `rustc --explain E0229`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs index f33469796c2f9..4fb58ff8fd28e 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs @@ -12,7 +12,7 @@ use std::{ mod object { use super::*; - pub trait Object<'a> { + pub trait Object<'a>: Sized { type Error; type Future: Future; fn create() -> Self::Future; diff --git a/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.rs b/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.rs index 1582cca5cd258..3504da4a61a01 100644 --- a/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.rs +++ b/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.rs @@ -1,7 +1,7 @@ -//@ check-pass - // Make sure that the `opaque_hidden_inferred_bound` lint doesn't fire on // RPITITs with no hidden type. +// This may be no longer necessary since we check the bounds of projection +// in definitions eagerly now. trait T0 {} @@ -11,6 +11,7 @@ trait T1 { trait T2 { fn foo() -> impl T1; + //~^ ERROR: `impl T0` cannot be sent between threads safely [E0277] } fn main() {} diff --git a/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.stderr b/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.stderr new file mode 100644 index 0000000000000..3c692141eafb1 --- /dev/null +++ b/tests/ui/impl-trait/opaque-hidden-inferred-rpitit.stderr @@ -0,0 +1,12 @@ +error[E0277]: `impl T0` cannot be sent between threads safely + --> $DIR/opaque-hidden-inferred-rpitit.rs:13:25 + | +LL | fn foo() -> impl T1; + | ^^^^^^^^^^^^^^^^^ `impl T0` cannot be sent between threads safely + | + = help: within `((), impl T0)`, the trait `Send` is not implemented for `impl T0` + = note: required because it appears within the type `((), impl T0)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/implied-bounds/item-bounds-from-projection-clause.rs b/tests/ui/implied-bounds/item-bounds-from-projection-clause.rs new file mode 100644 index 0000000000000..01724c35a21b6 --- /dev/null +++ b/tests/ui/implied-bounds/item-bounds-from-projection-clause.rs @@ -0,0 +1,40 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// If the rhs of a projection predicate is generic, then we imply item bounds of the associated +// types on it. + +trait Trait { + type Assoc: Copy; +} + +trait Explicit {} +impl, U: Copy> Explicit for T {} + +fn assert_explicit() {} +fn imply_copy, U>() { + assert_explicit::(); +} + + +trait BoundA {} + +trait HasBoundA { + type AssocA: BoundA; +} + +trait BoundB {} +trait HasBoundB { + type AssocB: BoundB; +} + +fn imply_both() +where + T: HasBoundA + HasBoundB, +{ + assert_both::(); +} + +fn assert_both() {} + +fn main() {} diff --git a/tests/ui/layout/unexpected-unsized-field-issue-135020.rs b/tests/ui/layout/unexpected-unsized-field-issue-135020.rs index c81d037e510f2..64423edfbbfde 100644 --- a/tests/ui/layout/unexpected-unsized-field-issue-135020.rs +++ b/tests/ui/layout/unexpected-unsized-field-issue-135020.rs @@ -1,6 +1,7 @@ -//@ check-pass +// We check item bounds on projection predicate's term now for well-formedness. fn problem_thingy(items: &mut impl Iterator) { + //~^ ERROR: the size for values of type `str` cannot be known at compilation time [E0277] items.peekable(); } diff --git a/tests/ui/layout/unexpected-unsized-field-issue-135020.stderr b/tests/ui/layout/unexpected-unsized-field-issue-135020.stderr new file mode 100644 index 0000000000000..eecfe9baf7a45 --- /dev/null +++ b/tests/ui/layout/unexpected-unsized-field-issue-135020.stderr @@ -0,0 +1,11 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unexpected-unsized-field-issue-135020.rs:3:45 + | +LL | fn problem_thingy(items: &mut impl Iterator) { + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs index da11804c2267d..c31346a137a4e 100644 --- a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs +++ b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs @@ -4,6 +4,8 @@ fn return_str() where str: std::ptr::Pointee, + //~^ ERROR: the trait bound `str: Copy` is not satisfied [E0277] + //~| NOTE: the trait `Copy` is not implemented for `str` { [(); { let _a: Option<&str> = None; 0 }]; //~^ ERROR entering unreachable code diff --git a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr index 888e2574119d6..052d39284bb26 100644 --- a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr +++ b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr @@ -1,9 +1,16 @@ +error[E0277]: the trait bound `str: Copy` is not satisfied + --> $DIR/unknown-when-ptr-metadata-is-DST.rs:6:28 + | +LL | str: std::ptr::Pointee, + | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `str` + error[E0080]: entering unreachable code - --> $DIR/unknown-when-ptr-metadata-is-DST.rs:8:10 + --> $DIR/unknown-when-ptr-metadata-is-DST.rs:10:10 | LL | [(); { let _a: Option<&str> = None; 0 }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `return_str::{constant#0}` failed here -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/nll/issue-78561.rs b/tests/ui/nll/issue-78561.rs index 0c7366643c93c..307e25cd201e0 100644 --- a/tests/ui/nll/issue-78561.rs +++ b/tests/ui/nll/issue-78561.rs @@ -11,7 +11,7 @@ pub trait Tr2<'a, 'b> {} pub struct A(T); pub trait Tr { - type B; + type B: ?Sized; } impl<'a, 'b, T: Tr>> Trait for A { diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed index 69780648ab666..c20c0a2421683 100644 --- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -22,7 +22,7 @@ trait Trait { impl Trait for fn() {} #[allow(dead_code)] -fn test2(f: impl Fn() -> (dyn std::fmt::Debug) + Trait) { +fn test2(f: impl Fn() -> i32 + Trait) { f.method(); //~ ERROR no method named `method` found } diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs index f49512bdd62af..30d5eff429b60 100644 --- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -22,7 +22,7 @@ trait Trait { impl Trait for fn() {} #[allow(dead_code)] -fn test2(f: impl Fn() -> dyn std::fmt::Debug) { +fn test2(f: impl Fn() -> i32) { f.method(); //~ ERROR no method named `method` found } diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr index 0aced78ddacba..7473fc12c1822 100644 --- a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -12,19 +12,19 @@ help: the following trait defines an item `hello`, perhaps you need to restrict LL | fn test(foo: impl Foo + Bar) { | +++++ -error[E0599]: no method named `method` found for type parameter `impl Fn() -> dyn std::fmt::Debug` in the current scope +error[E0599]: no method named `method` found for type parameter `impl Fn() -> i32` in the current scope --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:26:7 | -LL | fn test2(f: impl Fn() -> dyn std::fmt::Debug) { - | -------------------------------- method `method` not found for this type parameter +LL | fn test2(f: impl Fn() -> i32) { + | ---------------- method `method` not found for this type parameter LL | f.method(); - | ^^^^^^ method not found in `impl Fn() -> dyn std::fmt::Debug` + | ^^^^^^ method not found in `impl Fn() -> i32` | = help: items from traits can only be used if the type parameter is bounded by the trait -help: the following trait defines an item `method`, perhaps you need to restrict type parameter `impl Fn() -> dyn std::fmt::Debug` with it: +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `impl Fn() -> i32` with it: | -LL | fn test2(f: impl Fn() -> (dyn std::fmt::Debug) + Trait) { - | + +++++++++ +LL | fn test2(f: impl Fn() -> i32 + Trait) { + | +++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs index 2ee6ad91056c5..556795a4e5d0f 100644 --- a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs +++ b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs @@ -1,8 +1,8 @@ use std::future::Future; pub fn dyn_func( - executor: impl FnOnce(T) -> dyn Future, -) -> Box dyn Future> { + executor: impl FnOnce(T) -> &'static dyn Future, +) -> Box &'static dyn Future> { Box::new(executor) //~ ERROR may not live long enough } @@ -12,7 +12,7 @@ trait Trait { impl Trait for fn() {} -pub fn in_ty_param dyn std::fmt::Debug> (t: T) { +pub fn in_ty_param &'static dyn std::fmt::Debug> (t: T) { t.method(); //~^ ERROR no method named `method` found for type parameter `T` } diff --git a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr index 0c331355407de..4c0f2f98a194a 100644 --- a/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr +++ b/tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.stderr @@ -1,7 +1,7 @@ error[E0599]: no method named `method` found for type parameter `T` in the current scope --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:16:7 | -LL | pub fn in_ty_param dyn std::fmt::Debug> (t: T) { +LL | pub fn in_ty_param &'static dyn std::fmt::Debug> (t: T) { | - method `method` not found for this type parameter LL | t.method(); | ^^^^^^ method not found in `T` @@ -9,8 +9,8 @@ LL | t.method(); = help: items from traits can only be used if the type parameter is bounded by the trait help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: | -LL | pub fn in_ty_param (dyn std::fmt::Debug) + Trait> (t: T) { - | + +++++++++ +LL | pub fn in_ty_param &'static (dyn std::fmt::Debug) + Trait> (t: T) { + | + +++++++++ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:21:21 @@ -35,21 +35,21 @@ help: consider relaxing the implicit `Sized` restriction LL | fn without_sized &'static (dyn std::fmt::Debug) + ?Sized>() {} | + ++++++++++ -error[E0310]: the parameter type `impl FnOnce(T) -> dyn Future` may not live long enough +error[E0310]: the parameter type `impl FnOnce(T) -> &'static dyn Future` may not live long enough --> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:6:5 | -LL | ) -> Box dyn Future> { - | ---------------------------------------- this `dyn Trait` has an implicit `'static` lifetime bound +LL | ) -> Box &'static dyn Future> { + | ------------------------------------------------- this `dyn Trait` has an implicit `'static` lifetime bound LL | Box::new(executor) | ^^^^^^^^^^^^^^^^^^ | | - | the parameter type `impl FnOnce(T) -> dyn Future` must be valid for the static lifetime... - | ...so that the type `impl FnOnce(T) -> dyn Future` will meet its required lifetime bounds + | the parameter type `impl FnOnce(T) -> &'static dyn Future` must be valid for the static lifetime... + | ...so that the type `impl FnOnce(T) -> &'static dyn Future` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | -LL | executor: impl FnOnce(T) -> (dyn Future) + 'static, - | + +++++++++++ +LL | executor: impl FnOnce(T) -> &'static (dyn Future) + 'static, + | + +++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs index 5239474ff44b2..28457cbfd5fbc 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs @@ -23,6 +23,7 @@ impl Bar for T where T: Foo {} fn needs_bar() {} fn foo + Foo>() { + //~^ ERROR: type annotations needed [E0282] needs_bar::(); //~^ ERROR type annotations needed: cannot normalize } diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr index 270ad85171779..e09360f382b22 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr @@ -1,5 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/two-projection-param-candidates-are-ambiguous.rs:25:15 + | +LL | fn foo + Foo>() { + | ^^^^^^^^^^^ cannot infer type for associated type `::Assoc` + error[E0284]: type annotations needed: cannot normalize `::Assoc` - --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 + --> $DIR/two-projection-param-candidates-are-ambiguous.rs:27:17 | LL | needs_bar::(); | ^ cannot normalize `::Assoc` @@ -15,6 +21,7 @@ note: required by a bound in `needs_bar` LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs index b1f7c4a600021..8be823d6dcf12 100644 --- a/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs +++ b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs @@ -25,7 +25,7 @@ type AlsoTraitObject = dyn SomeTrait; // Step 3: Force the compiler to check whether the two names are the same type trait Supertrait { - type Foo; + type Foo: ?Sized; } trait Subtrait: Supertrait {} diff --git a/tests/ui/typeck/issue-103899.current.stderr b/tests/ui/typeck/issue-103899.current.stderr index a3a164907be48..c54d254520e8b 100644 --- a/tests/ui/typeck/issue-103899.current.stderr +++ b/tests/ui/typeck/issue-103899.current.stderr @@ -1,3 +1,15 @@ +error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied + --> $DIR/issue-103899.rs:24:32 + | +LL | fn trigger>() -> DoubleProject { + | ^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-103899.rs:4:1 + | +LL | trait BaseWithAssoc { + | ^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied --> $DIR/issue-103899.rs:24:54 | @@ -10,6 +22,6 @@ help: this trait has no implementations, consider adding one LL | trait BaseWithAssoc { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-103899.next.stderr b/tests/ui/typeck/issue-103899.next.stderr index a3a164907be48..c54d254520e8b 100644 --- a/tests/ui/typeck/issue-103899.next.stderr +++ b/tests/ui/typeck/issue-103899.next.stderr @@ -1,3 +1,15 @@ +error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied + --> $DIR/issue-103899.rs:24:32 + | +LL | fn trigger>() -> DoubleProject { + | ^^^^^^^^^^^^^^ the trait `BaseWithAssoc` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/issue-103899.rs:4:1 + | +LL | trait BaseWithAssoc { + | ^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `(): BaseWithAssoc` is not satisfied --> $DIR/issue-103899.rs:24:54 | @@ -10,6 +22,6 @@ help: this trait has no implementations, consider adding one LL | trait BaseWithAssoc { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs index 92356ecf288b1..684f6e535fed5 100644 --- a/tests/ui/typeck/issue-103899.rs +++ b/tests/ui/typeck/issue-103899.rs @@ -23,6 +23,7 @@ struct DoubleProject { fn trigger>() -> DoubleProject { //~^ ERROR the trait bound `(): BaseWithAssoc` is not satisfied [E0277] + //~| ERROR the trait bound `(): BaseWithAssoc` is not satisfied [E0277] loop {} } diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs index e107069d0dfa9..b1be1400d57d7 100644 --- a/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs +++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs @@ -2,6 +2,8 @@ // Checks that we do not ICE while reporting // lifetime mistmatch error +//~^^^^ ERROR: mismatched types + trait Fun { type Assoc; } diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr index 357e504bd5eb9..550e2c17dd0ed 100644 --- a/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr +++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr @@ -1,11 +1,11 @@ error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types - --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + --> $DIR/ice-wf-missing-span-in-error-130012.rs:11:28 | LL | trait MyTrait: for<'a> Fun {} | ^^^^^^^^^^^^^^ error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types - --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + --> $DIR/ice-wf-missing-span-in-error-130012.rs:11:28 | LL | trait MyTrait: for<'a> Fun {} | ^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | trait MyTrait: for<'a> Fun {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types - --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + --> $DIR/ice-wf-missing-span-in-error-130012.rs:11:28 | LL | trait MyTrait: for<'a> Fun {} | ^^^^^^^^^^^^^^ @@ -21,13 +21,23 @@ LL | trait MyTrait: for<'a> Fun {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0582]: binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types - --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:21 + --> $DIR/ice-wf-missing-span-in-error-130012.rs:16:21 | LL | impl Fun> MyTrait for F {} | ^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:50 + | + = note: expected reference `&()` + found reference `&'a ()` +note: the lifetime requirement is introduced here + --> $DIR/ice-wf-missing-span-in-error-130012.rs:11:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:16:50 | LL | impl Fun> MyTrait for F {} | ^ lifetime mismatch @@ -35,7 +45,7 @@ LL | impl Fun> MyTrait for F {} = note: expected reference `&()` found reference `&'b ()` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0308, E0582. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/wf/wf-item-bounds-on-projection.rs b/tests/ui/wf/wf-item-bounds-on-projection.rs new file mode 100644 index 0000000000000..5c5c2834c864a --- /dev/null +++ b/tests/ui/wf/wf-item-bounds-on-projection.rs @@ -0,0 +1,31 @@ +// Projection predicate's WFedness requires that the rhs term satisfy all item bounds defined on the +// associated type. +// Generic types have those bounds implied. + +trait Required {} + +trait AssocHasBound { + type Assoc: Required; +} + +trait Trait { + type Assoc1: AssocHasBound; + //~^ ERROR: the trait bound `i32: Required` is not satisfied [E0277] + type Assoc2: AssocHasBound; + type Assoc3: AssocHasBound; + type DummyAssoc; +} + +fn some_func() +where + T1: AssocHasBound, + //~^ ERROR: type annotations needed [E0284] + T1: AssocHasBound, +{} + +fn opaque_with_concrete_assoc(_: impl AssocHasBound) {} +//~^ ERROR: the trait bound `i32: Required` is not satisfied [E0277] + +fn opaque_with_generic_assoc(_: impl AssocHasBound) {} + +fn main() {} diff --git a/tests/ui/wf/wf-item-bounds-on-projection.stderr b/tests/ui/wf/wf-item-bounds-on-projection.stderr new file mode 100644 index 0000000000000..06189cf0301b2 --- /dev/null +++ b/tests/ui/wf/wf-item-bounds-on-projection.stderr @@ -0,0 +1,36 @@ +error[E0284]: type annotations needed + --> $DIR/wf-item-bounds-on-projection.rs:21:23 + | +LL | T1: AssocHasBound, + | ^^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy `::Assoc == _` + +error[E0277]: the trait bound `i32: Required` is not satisfied + --> $DIR/wf-item-bounds-on-projection.rs:26:53 + | +LL | fn opaque_with_concrete_assoc(_: impl AssocHasBound) {} + | ^^^^^^^^^^^ the trait `Required` is not implemented for `i32` + | +help: this trait has no implementations, consider adding one + --> $DIR/wf-item-bounds-on-projection.rs:5:1 + | +LL | trait Required {} + | ^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `i32: Required` is not satisfied + --> $DIR/wf-item-bounds-on-projection.rs:12:32 + | +LL | type Assoc1: AssocHasBound; + | ^^^^^^^^^^^ the trait `Required` is not implemented for `i32` + | +help: this trait has no implementations, consider adding one + --> $DIR/wf-item-bounds-on-projection.rs:5:1 + | +LL | trait Required {} + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0284. +For more information about an error, try `rustc --explain E0277`.