Allow using named consts in pattern types

This commit is contained in:
Oli Scherer 2025-01-07 16:39:30 +00:00
parent f0308938ba
commit fbcaa9b0a1
9 changed files with 186 additions and 56 deletions

View file

@ -440,17 +440,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node = loop {
match &pattern.kind {
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
// FIXME(pattern_types): remove this closure and call `lower_const_arg` instead.
// That requires first modifying the AST to have const args here.
let mut lower_expr = |e: &Expr| -> &_ {
let kind = if let ExprKind::Path(qself, path) = &e.kind {
hir::ConstArgKind::Path(self.lower_qpath(
e.id,
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
))
if let ExprKind::Path(None, path) = &e.kind
&& let Some(res) = self
.resolver
.get_partial_res(e.id)
.and_then(|partial_res| partial_res.full_res())
{
self.lower_const_path_to_const_arg(path, res, e.id, e.span)
} else {
let node_id = self.next_node_id();
let def_id = self.create_def(
@ -467,9 +466,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
body: self.lower_const_body(pattern.span, Some(e)),
span: self.lower_span(pattern.span),
});
hir::ConstArgKind::Anon(ac)
};
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind })
self.arena.alloc(hir::ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Anon(ac),
})
}
};
break hir::TyPatKind::Range(
e1.as_deref().map(|e| lower_expr(e)),

View file

@ -198,6 +198,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
{
Some(parent_did)
}
Node::TyPat(_) => Some(parent_did),
_ => None,
}
}

View file

@ -0,0 +1,36 @@
error: constant expression depends on a generic parameter
--> $DIR/assoc_const.rs:17:19
|
LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: constant expression depends on a generic parameter
--> $DIR/assoc_const.rs:17:19
|
LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: constant expression depends on a generic parameter
--> $DIR/assoc_const.rs:20:19
|
LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: constant expression depends on a generic parameter
--> $DIR/assoc_const.rs:20:19
|
LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors

View file

@ -0,0 +1,24 @@
#![feature(pattern_types)]
#![feature(pattern_type_macro)]
#![cfg_attr(const_arg, feature(generic_const_exprs))]
#![expect(incomplete_features)]
//@ revisions: default const_arg
//@[const_arg] check-pass
use std::pat::pattern_type;
trait Foo {
const START: u32;
const END: u32;
}
fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
//[default]~^ ERROR: constant expression depends on a generic parameter
//[default]~| ERROR: constant expression depends on a generic parameter
fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
//[default]~^ ERROR: constant expression depends on a generic parameter
//[default]~| ERROR: constant expression depends on a generic parameter
fn main() {}

View file

@ -1,11 +1,14 @@
//@known-bug: #127972
//@ failure-status: 101
//@ normalize-stderr: "note: .*\n\n" -> ""
//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
//@ rustc-env:RUST_BACKTRACE=0
#![feature(pattern_types, pattern_type_macro)]
#![allow(internal_features)]
type Pat<const START: u32, const END: u32> =
std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
//~^ ERROR type and const arguments are not allowed on const parameter `START`
//~| ERROR generic arguments are not allowed on const parameter `END`
//~| ERROR associated item constraints are not allowed here
//~| ERROR `_` is not allowed within types on item signatures for type aliases
fn main() {}

View file

@ -1,44 +1,14 @@
error[E0109]: type and const arguments are not allowed on const parameter `START`
--> $DIR/bad_const_generics_args_on_const_param.rs:5:44
error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible
--> $DIR/bad_const_generics_args_on_const_param.rs:12:36
|
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| ----- ^^ ^^^ ^ type and const arguments not allowed
| |
| not allowed on const parameter `START`
|
note: const parameter `START` defined here
--> $DIR/bad_const_generics_args_on_const_param.rs:4:16
|
LL | type Pat<const START: u32, const END: u32> =
| ^^^^^
| ^^^^^^^^^^^^^^^^^^^
error[E0109]: generic arguments are not allowed on const parameter `END`
--> $DIR/bad_const_generics_args_on_const_param.rs:5:64
|
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| --- ^ generic argument not allowed
| |
| not allowed on const parameter `END`
|
note: const parameter `END` defined here
--> $DIR/bad_const_generics_args_on_const_param.rs:4:34
|
LL | type Pat<const START: u32, const END: u32> =
| ^^^
error[E0229]: associated item constraints are not allowed here
--> $DIR/bad_const_generics_args_on_const_param.rs:5:67
|
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| ^^^^^^^^^^ associated item constraint not allowed here
Box<dyn Any>
query stack during panic:
#0 [type_of] expanding type alias `Pat`
#1 [check_well_formed] checking that `Pat` is well-formed
... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack
error: aborting due to 1 previous error
error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
--> $DIR/bad_const_generics_args_on_const_param.rs:5:64
|
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| ^ not allowed in type signatures
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0109, E0121, E0229.
For more information about an error, try `rustc --explain E0109`.

View file

@ -0,0 +1,10 @@
#![feature(pattern_types)]
#![feature(pattern_type_macro)]
#![feature(inline_const_pat)]
use std::pat::pattern_type;
fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
//~^ ERROR: cycle
fn main() {}

View file

@ -0,0 +1,72 @@
error[E0391]: cycle detected when evaluating type-level constant
--> $DIR/const_block.rs:7:36
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `bar::{constant#2}`...
--> $DIR/const_block.rs:7:36
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^
note: ...which requires caching mir of `bar::{constant#2}` for CTFE...
--> $DIR/const_block.rs:7:36
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^
note: ...which requires elaborating drops for `bar::{constant#2}`...
--> $DIR/const_block.rs:7:36
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^
note: ...which requires borrow-checking `bar::{constant#2}`...
--> $DIR/const_block.rs:7:36
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^
note: ...which requires borrow-checking `bar::{constant#0}`...
--> $DIR/const_block.rs:7:41
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^
note: ...which requires promoting constants in MIR for `bar::{constant#0}`...
--> $DIR/const_block.rs:7:41
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^
note: ...which requires const checking `bar::{constant#0}`...
--> $DIR/const_block.rs:7:41
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^
note: ...which requires building MIR for `bar::{constant#0}`...
--> $DIR/const_block.rs:7:41
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^
note: ...which requires match-checking `bar::{constant#0}`...
--> $DIR/const_block.rs:7:41
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^
note: ...which requires type-checking `bar::{constant#0}`...
--> $DIR/const_block.rs:7:41
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^
note: ...which requires type-checking `bar`...
--> $DIR/const_block.rs:7:1
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires evaluating type-level constant, completing the cycle
note: cycle used when checking that `bar` is well-formed
--> $DIR/const_block.rs:7:1
|
LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0391`.

View file

@ -0,0 +1,13 @@
//@ check-pass
#![feature(pattern_types)]
#![feature(pattern_type_macro)]
use std::pat::pattern_type;
const START: u32 = 0;
const END: u32 = 10;
fn foo(_: pattern_type!(u32 is START..=END)) {}
fn main() {}