Skip to content

silence mismatched types errors for implied projections #121863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
suppress fulfillment errors for super projections
  • Loading branch information
Lukas Markeffsky committed Mar 4, 2024
commit aa55f6daa2c83020a271077bb15590755f4119d9
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

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

can you also use self.enter_forall(error, ...) here and manually instantiate implied with infer vars?

Copy link
Member Author

Choose a reason for hiding this comment

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

Isn't that exactly what can_sub already does for PolyTraitRefs?

Copy link
Contributor

@lcnr lcnr Mar 4, 2024

Choose a reason for hiding this comment

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

yes, that's something I dislike though. It's subtle and hard to understand, I've already seem other people accidentally using sub inside of the trait system for non-binders because that's what they've seen used. To prevent bugs when using Ty<'tcx> instead of Binder<Ty<'tcx>>, I prefer manually instantiating binders everywhere.

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| {
Copy link
Contributor

Choose a reason for hiding this comment

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

you should instantiate cond with existentials here, not forall. You want to prove cond -> error (forall<T> cond<T> => forall<U> error<U>). This holds if forall<U> exists<T> cond<T> eq errorU> holds

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")]
Expand Down
1 change: 0 additions & 1 deletion tests/ui/issues/issue-33941.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 `(&_, &_)`
}
12 changes: 1 addition & 11 deletions tests/ui/issues/issue-33941.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ LL | for _ in HashMap::new().iter().cloned() {}
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` 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<std::collections::hash_map::Iter<'_, _, _>>` 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`.
5 changes: 0 additions & 5 deletions tests/ui/trait-bounds/super-assoc-mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,17 @@ trait Sub: Super<Assoc = u16> {}
trait BoundOnSelf: Sub {}
impl BoundOnSelf for () {}
//~^ ERROR the trait bound `(): Sub` is not satisfied
//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16`

trait BoundOnParam<T: Sub> {}
impl BoundOnParam<()> for () {}
//~^ ERROR the trait bound `(): Sub` is not satisfied
//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16`

trait BoundOnAssoc {
type Assoc: Sub;
}
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<u8>: Sub {
Expand All @@ -31,11 +28,9 @@ trait BoundOnGat where Self::Assoc<u8>: Sub {
impl BoundOnGat for u8 {
type Assoc<T> = ();
//~^ 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() {}
121 changes: 9 additions & 112 deletions tests/ui/trait-bounds/super-assoc-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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<Assoc = u16> {}
| ^^^
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 `()`
Expand All @@ -49,35 +27,13 @@ help: this trait has no implementations, consider adding one
LL | trait Sub: Super<Assoc = u16> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `BoundOnParam`
--> $DIR/super-assoc-mismatch.rs:14:23
|
LL | trait BoundOnParam<T: Sub> {}
| ^^^ 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<Assoc = u16> {}
| ^^^
note: required by a bound in `BoundOnParam`
--> $DIR/super-assoc-mismatch.rs:14:23
--> $DIR/super-assoc-mismatch.rs:13:23
|
LL | trait BoundOnParam<T: Sub> {}
| ^^^ 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 `()`
Expand All @@ -88,35 +44,13 @@ help: this trait has no implementations, consider adding one
LL | trait Sub: Super<Assoc = u16> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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<Assoc = u16> {}
| ^^^
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<T> = ();
| ^^ the trait `Sub` is not implemented for `()`, which is required by `<u8 as BoundOnGat>::Assoc<u8>: Sub`
Expand All @@ -127,35 +61,13 @@ help: this trait has no implementations, consider adding one
LL | trait Sub: Super<Assoc = u16> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `BoundOnGat`
--> $DIR/super-assoc-mismatch.rs:28:41
|
LL | trait BoundOnGat where Self::Assoc<u8>: 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<T> = ();
| ^^ 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 `<u8 as BoundOnGat>::Assoc<u8>` to implement `Sub`
--> $DIR/super-assoc-mismatch.rs:7:7
|
LL | trait Sub: Super<Assoc = u16> {}
| ^^^
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<u8>: 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 `()`
Expand All @@ -168,21 +80,6 @@ LL | trait Sub: Super<Assoc = u16> {}
= 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 10 previous errors
error: aborting due to 5 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`.