Skip to content

Commit c1d2c3b

Browse files
committed
Don't crash on ~const trait bounds involving a non-const trait
1 parent 3ad8e2d commit c1d2c3b

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

compiler/rustc_hir_analysis/src/astconv/generics.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,27 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>(
253253
| GenericParamDefKind::Lifetime,
254254
_,
255255
) => {
256-
// SPECIAL CASE FOR DESUGARED EFFECT PARAMS
257-
// This comes from the following example:
256+
// A host effect arg was passed but the generic param isn't the host effect
257+
// param. There are two situations in which we can reach this case.
258+
//
259+
// 1. The number of arguments is incorrect. In this case, an error will
260+
// already have been emitted, and we can just push an inferred const
261+
// arg which will just end up resolving to `{const error}`.
262+
// 2. The generic param has a default. Since host effect args are always
263+
// placed last, it means that we need to infer the arg corresp. to the
264+
// current param and any following to their default until we reach the
265+
// host effect param.
266+
//
267+
// For (2), consider the following example:
258268
//
259269
// ```
260270
// #[const_trait]
261271
// pub trait PartialEq<Rhs: ?Sized = Self> {}
262272
// impl const PartialEq for () {}
263273
// ```
264274
//
265-
// Since this is a const impl, we need to insert `<false>` at the end of
266-
// `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
267-
// To work around this, we infer all arguments until we reach the host param.
275+
// For the trait ref `<() as PartialEq<host>>`, we need to infer the `Rhs`
276+
// and create the generic args `[/*Self*/ (), /*defaulted*/ (), host]`.
268277
args.push(ctx.inferred_kind(Some(&args), param, infer_args));
269278
params.next();
270279
}
@@ -360,7 +369,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>(
360369

361370
(Some(&arg), None) => {
362371
// We should never be able to reach this point with well-formed input.
363-
// There are three situations in which we can encounter this issue.
372+
// There are four situations in which we can encounter this issue.
364373
//
365374
// 1. The number of arguments is incorrect. In this case, an error
366375
// will already have been emitted, and we can ignore it.
@@ -369,9 +378,22 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>(
369378
// user.
370379
// 3. We've inferred some lifetimes, which have been provided later (i.e.
371380
// after a type or const). We want to throw an error in this case.
381+
// 4. A host effect argument was passed but the generic params don't
382+
// contain a host effect param. This can happen if a `~const` trait
383+
// bound modifier was placed on a non-const trait. Since the lowerer
384+
// has no way of knowing if the trait is const or not, it synthesizes
385+
// host effect args unconditionally. We will emit an error later and
386+
// thus we can ignore it.
372387

373388
if arg_count.correct.is_ok()
374389
&& arg_count.explicit_late_bound == ExplicitLateBound::No
390+
&& !matches!(
391+
arg,
392+
GenericArg::Const(hir::ConstArg {
393+
is_desugared_from_effects: true,
394+
..
395+
})
396+
)
375397
{
376398
let kind = arg.descr();
377399
assert_eq!(kind, "lifetime");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Regression test for issue #117244.
2+
#![feature(const_trait_impl, effects)]
3+
4+
trait NonConst {}
5+
6+
const fn perform<T: ~const NonConst>() {}
7+
//~^ ERROR ~const can only be applied to `#[const_trait]` traits
8+
9+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: ~const can only be applied to `#[const_trait]` traits
2+
--> $DIR/tilde-const-on-non-const-trait.rs:6:28
3+
|
4+
LL | const fn perform<T: ~const NonConst>() {}
5+
| ^^^^^^^^
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)