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

Support ~const in associated functions in trait impls #119705

Merged
merged 1 commit into from
Jan 8, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::PredicateOrigin;
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, sym, Ident};
Expand Down Expand Up @@ -572,23 +573,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.

match parent_hir.node().expect_item().kind {
let generics = match parent_hir.node().expect_item().kind {
hir::ItemKind::Impl(impl_) => {
self.is_in_trait_impl = impl_.of_trait.is_some();
&impl_.generics
}
hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => {
self.host_param_id = generics
.params
.iter()
.find(|param| {
matches!(
param.kind,
hir::GenericParamKind::Const { is_host_effect: true, .. }
)
})
.map(|param| param.def_id);
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
kind => {
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
}
_ => {}
};

if self.tcx.features().effects {
self.host_param_id = generics
.params
.iter()
.find(|param| {
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
})
.map(|param| param.def_id);
}

match ctxt {
Expand Down
37 changes: 20 additions & 17 deletions tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
error[E0277]: can't compare `impl PartialEq + Destruct + Copy` with `impl PartialEq + Destruct + Copy`
--> $DIR/const-impl-trait.rs:28:17
error[E0277]: can't compare `()` with `()`
--> $DIR/const-impl-trait.rs:35:17
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `impl PartialEq + Destruct + Copy == impl PartialEq + Destruct + Copy`
LL | assert!(cmp(&()));
| --- ^^^ no implementation for `() == ()`
| |
| required by a bound introduced by this call
|
= help: the trait `~const PartialEq` is not implemented for `impl PartialEq + Destruct + Copy`
note: required by a bound in `Foo::{opaque#0}`
--> $DIR/const-impl-trait.rs:24:22
= help: the trait `const PartialEq` is not implemented for `()`
= help: the trait `PartialEq` is implemented for `()`
note: required by a bound in `cmp`
--> $DIR/const-impl-trait.rs:12:23
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
| ^^^^^^^^^^^^^^^^ required by this bound in `cmp`

error[E0277]: can't drop `impl PartialEq + Destruct + Copy`
--> $DIR/const-impl-trait.rs:28:17
error[E0277]: can't compare `&impl ~const PartialEq` with `&impl ~const PartialEq`
--> $DIR/const-impl-trait.rs:13:7
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `impl PartialEq + Destruct + Copy`
LL | a == a
| ^^ no implementation for `&impl ~const PartialEq == &impl ~const PartialEq`
|
note: required by a bound in `Foo::{opaque#0}`
--> $DIR/const-impl-trait.rs:24:41
= help: the trait `~const PartialEq<&impl ~const PartialEq>` is not implemented for `&impl ~const PartialEq`
help: consider dereferencing both sides of the expression
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
LL | *a == *a
| + +

error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Regression test for issue #119700.
// check-pass

#![feature(const_trait_impl, effects)]

#[const_trait]
trait Main {
fn compute<T: ~const Aux>() -> u32;
}

impl const Main for () {
fn compute<T: ~const Aux>() -> u32 {
T::generate()
Copy link
Member Author

Choose a reason for hiding this comment

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

Wait, the UI test is not a true reproducer for the linked issue, oops!

Well, it would be a reproducer of the ICE if I replaced the body with 0

Suggested change
T::generate()
0

but then the test would become a bit boring since we wouldn't actually use anything from ~const Aux. With T::generate() nightly rustc incorrectly fails with mismatched types // expected `host`, found `true` since the ICE is a delayed bug. Ofc I could add revisions to this test or another file.

Copy link
Member

Choose a reason for hiding this comment

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

It's not that big of a deal. Showing that it doesn't ICE (we can lower the where clause) and that it works correctly seems like a fine test.

}
}

#[const_trait]
trait Aux {
fn generate() -> u32;
}

impl const Aux for () {
fn generate() -> u32 { 1024 }
}

fn main() {
const _: u32 = <()>::compute::<()>();
let _ = <()>::compute::<()>();
}
Loading