diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 62933bce76b..129ddb089bd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1389,38 +1389,45 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return true; } - // FIXME: It should be possible to deal with `ForAll` in a cleaner way. - let bound_error = error.kind(); - let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)), - ) => (cond, bound_error.rebind(error)), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; - - for pred in elaborate(self.tcx, std::iter::once(cond)) { - let bound_predicate = pred.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) = - bound_predicate.skip_binder() - { - let error = error.to_poly_trait_ref(); - let implication = bound_predicate.rebind(implication.trait_ref); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication) { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } + if let Some(error) = error.to_opt_poly_trait_pred() { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_trait_pred()) + .any(|implied| { + if error.polarity() != implied.polarity() { + return false; + } + let error = error.to_poly_trait_ref(); + let implied = implied.to_poly_trait_ref(); + // FIXME: I'm just not taking associated types at all here. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(); + let is_implied = self.can_sub(param_env, error, implied); + if is_implied { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); + } + is_implied + }) + } else if let Some(error) = error.to_opt_poly_projection_pred() { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_projection_pred()) + .any(|implied| { + self.enter_forall(implied, |implied| { + let param_env = ty::ParamEnv::empty(); + let is_implied = + self.can_eq(param_env, error.projection_ty, implied.projection_ty) + && self.can_eq(param_env, error.term, implied.term); + if is_implied { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); + } + is_implied + }) + }) + }) + } else { + false } - - false } #[instrument(skip(self), level = "debug")] diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs index 0ad7cbe8efc..7b5be30834b 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/issues/issue-33941.rs @@ -5,5 +5,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr index e7f4a4fa004..f1b6b6ba17e 100644 --- a/tests/ui/issues/issue-33941.stderr +++ b/tests/ui/issues/issue-33941.stderr @@ -27,16 +27,6 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required for `Cloned>` to implement `Iterator` = note: required for `Cloned>` to implement `IntoIterator` -error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_` - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required for `Cloned>` to implement `Iterator` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs index b701f0b3f88..00a9df35b00 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.rs +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -9,12 +9,10 @@ trait Sub: Super {} trait BoundOnSelf: Sub {} impl BoundOnSelf for () {} //~^ ERROR the trait bound `(): Sub` is not satisfied -//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` trait BoundOnParam {} impl BoundOnParam<()> for () {} //~^ ERROR the trait bound `(): Sub` is not satisfied -//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` trait BoundOnAssoc { type Assoc: Sub; @@ -22,7 +20,6 @@ trait BoundOnAssoc { impl BoundOnAssoc for () { type Assoc = (); //~^ ERROR the trait bound `(): Sub` is not satisfied - //~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` } trait BoundOnGat where Self::Assoc: Sub { @@ -31,11 +28,9 @@ trait BoundOnGat where Self::Assoc: Sub { impl BoundOnGat for u8 { type Assoc = (); //~^ ERROR the trait bound `(): Sub` is not satisfied - //~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` } fn trivial_bound() where (): Sub {} //~^ ERROR the trait bound `(): Sub` is not satisfied -//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr index bf19dd45193..0ce0b66cbf9 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.stderr +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -15,30 +15,8 @@ note: required by a bound in `BoundOnSelf` LL | trait BoundOnSelf: Sub {} | ^^^ required by this bound in `BoundOnSelf` -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:10:22 - | -LL | impl BoundOnSelf for () {} - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `()` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnSelf` - --> $DIR/super-assoc-mismatch.rs:9:20 - | -LL | trait BoundOnSelf: Sub {} - | ^^^ required by this bound in `BoundOnSelf` - error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:15:27 + --> $DIR/super-assoc-mismatch.rs:14:27 | LL | impl BoundOnParam<()> for () {} | ^^ the trait `Sub` is not implemented for `()` @@ -49,35 +27,13 @@ help: this trait has no implementations, consider adding one LL | trait Sub: Super {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `BoundOnParam` - --> $DIR/super-assoc-mismatch.rs:14:23 - | -LL | trait BoundOnParam {} - | ^^^ required by this bound in `BoundOnParam` - -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:15:27 - | -LL | impl BoundOnParam<()> for () {} - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `()` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnParam` - --> $DIR/super-assoc-mismatch.rs:14:23 + --> $DIR/super-assoc-mismatch.rs:13:23 | LL | trait BoundOnParam {} | ^^^ required by this bound in `BoundOnParam` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:23:18 + --> $DIR/super-assoc-mismatch.rs:21:18 | LL | type Assoc = (); | ^^ the trait `Sub` is not implemented for `()` @@ -88,35 +44,13 @@ help: this trait has no implementations, consider adding one LL | trait Sub: Super {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `BoundOnAssoc::Assoc` - --> $DIR/super-assoc-mismatch.rs:20:17 - | -LL | type Assoc: Sub; - | ^^^ required by this bound in `BoundOnAssoc::Assoc` - -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:23:18 - | -LL | type Assoc = (); - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `<() as BoundOnAssoc>::Assoc` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnAssoc::Assoc` - --> $DIR/super-assoc-mismatch.rs:20:17 + --> $DIR/super-assoc-mismatch.rs:18:17 | LL | type Assoc: Sub; | ^^^ required by this bound in `BoundOnAssoc::Assoc` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:32:21 + --> $DIR/super-assoc-mismatch.rs:29:21 | LL | type Assoc = (); | ^^ the trait `Sub` is not implemented for `()`, which is required by `::Assoc: Sub` @@ -127,35 +61,13 @@ help: this trait has no implementations, consider adding one LL | trait Sub: Super {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `BoundOnGat` - --> $DIR/super-assoc-mismatch.rs:28:41 - | -LL | trait BoundOnGat where Self::Assoc: Sub { - | ^^^ required by this bound in `BoundOnGat` - -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:32:21 - | -LL | type Assoc = (); - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `::Assoc` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnGat` - --> $DIR/super-assoc-mismatch.rs:28:41 + --> $DIR/super-assoc-mismatch.rs:25:41 | LL | trait BoundOnGat where Self::Assoc: Sub { | ^^^ required by this bound in `BoundOnGat` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:37:26 + --> $DIR/super-assoc-mismatch.rs:33:26 | LL | fn trivial_bound() where (): Sub {} | ^^^^^^^ the trait `Sub` is not implemented for `()` @@ -168,21 +80,6 @@ LL | trait Sub: Super {} = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:37:26 - | -LL | fn trivial_bound() where (): Sub {} - | ^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u8` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ - = help: see issue #48214 - = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable +error: aborting due to 5 previous errors -error: aborting due to 10 previous errors - -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`.