Skip to content
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

Don't ICE on return-type notation when promoting trait preds to associated type bounds #111861

Merged
merged 1 commit into from May 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Expand Up @@ -427,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
// supertrait).
if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.substs == trait_identity_substs
// FIXME(return_type_notation): This check should be more robust
&& !tcx.is_impl_trait_in_trait(projection.def_id)
Comment on lines +430 to +431
Copy link
Member

Choose a reason for hiding this comment

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

This seems just incomplete and a not so great hack.

If the return type is not an impl Trait, doesn't it work fine? If so, why?

If everything works as expected, this at least needs a bit more documentation on why this hack exists.

Copy link
Member Author

Choose a reason for hiding this comment

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

We can encounter precisely two types of items for the projection.def_id here:

  1. Associated types/consts
  2. return-position impl trait in trait, when using RTN

If the return type is not an RPITIT, then it's always going to be an associated type or const, and the next line will never ICE. If the return type is an RPITIT, we shouldn't be calling associated_item on it, since that'll ICE.

When I mentioned that it should be more robust, I wasn't saying it was incomplete, I just don't really like that we have to treat associated items and RPITITs differently here (but this is a consequence of how they're currently implemented, and most code doesn't care about this distinction anyways).

&& tcx.associated_item(projection.def_id).container_id(tcx)
== def_id.to_def_id()
} else {
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/async-await/return-type-notation/supertrait-bound.rs
@@ -0,0 +1,11 @@
// check-pass

#![feature(return_position_impl_trait_in_trait, return_type_notation)]
//~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use

trait IntFactory {
fn stream(&self) -> impl Iterator<Item = i32>;
}
trait SendIntFactory: IntFactory<stream(): Send> + Send {}

fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/async-await/return-type-notation/supertrait-bound.stderr
@@ -0,0 +1,11 @@
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/supertrait-bound.rs:3:49
|
LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
= note: `#[warn(incomplete_features)]` on by default

warning: 1 warning emitted