Skip to content

Commit

Permalink
Allow using named consts in pattern types
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jan 30, 2025
1 parent f5d5d70 commit 62ac839
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 49 deletions.
25 changes: 12 additions & 13 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match &pattern.kind {
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
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(
Expand All @@ -467,9 +464,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)),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down
36 changes: 36 additions & 0 deletions tests/ui/type/pattern_types/assoc_const.default.stderr
Original file line number Diff line number Diff line change
@@ -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

24 changes: 24 additions & 0 deletions tests/ui/type/pattern_types/assoc_const.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -1,10 +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

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,38 +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

error: aborting due to 3 previous errors
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

Some errors have detailed explanations: E0109, E0229.
For more information about an error, try `rustc --explain E0109`.
10 changes: 10 additions & 0 deletions tests/ui/type/pattern_types/const_block.rs
Original file line number Diff line number Diff line change
@@ -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() {}
72 changes: 72 additions & 0 deletions tests/ui/type/pattern_types/const_block.stderr
Original file line number Diff line number Diff line change
@@ -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`.
13 changes: 13 additions & 0 deletions tests/ui/type/pattern_types/free_const.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 62ac839

Please sign in to comment.