From fbcaa9b0a16cb3eed67cc3dc2429574f28dcac17 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Jan 2025 16:39:30 +0000 Subject: [PATCH] Allow using named consts in pattern types --- compiler/rustc_ast_lowering/src/pat.rs | 27 +++---- .../src/collect/generics_of.rs | 1 + .../pattern_types/assoc_const.default.stderr | 36 ++++++++++ tests/ui/type/pattern_types/assoc_const.rs | 24 +++++++ .../bad_const_generics_args_on_const_param.rs | 11 +-- ..._const_generics_args_on_const_param.stderr | 48 +++---------- tests/ui/type/pattern_types/const_block.rs | 10 +++ .../ui/type/pattern_types/const_block.stderr | 72 +++++++++++++++++++ tests/ui/type/pattern_types/free_const.rs | 13 ++++ 9 files changed, 186 insertions(+), 56 deletions(-) create mode 100644 tests/ui/type/pattern_types/assoc_const.default.stderr create mode 100644 tests/ui/type/pattern_types/assoc_const.rs create mode 100644 tests/ui/type/pattern_types/const_block.rs create mode 100644 tests/ui/type/pattern_types/const_block.stderr create mode 100644 tests/ui/type/pattern_types/free_const.rs diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 57f15f99760a..bb9b2a13185b 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -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)), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 2ac8acbd3a4b..c0902398a54a 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -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, } } diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr new file mode 100644 index 000000000000..abda40e46816 --- /dev/null +++ b/tests/ui/type/pattern_types/assoc_const.default.stderr @@ -0,0 +1,36 @@ +error: constant expression depends on a generic parameter + --> $DIR/assoc_const.rs:17:19 + | +LL | fn foo(_: pattern_type!(u32 is ::START..=::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(_: pattern_type!(u32 is ::START..=::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(_: 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(_: 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 + diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs new file mode 100644 index 000000000000..af0f7e4cbf32 --- /dev/null +++ b/tests/ui/type/pattern_types/assoc_const.rs @@ -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(_: pattern_type!(u32 is ::START..=::END)) {} +//[default]~^ ERROR: constant expression depends on a generic parameter +//[default]~| ERROR: constant expression depends on a generic parameter +fn bar(_: 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() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 05e308de7b1e..0f10bf8ce627 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -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 = 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() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index c4ba89de3f36..fbe80a19863d 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -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 = - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^ -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 = - | ^^^ -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 +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`. diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs new file mode 100644 index 000000000000..49c87f4fa0d6 --- /dev/null +++ b/tests/ui/type/pattern_types/const_block.rs @@ -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() {} diff --git a/tests/ui/type/pattern_types/const_block.stderr b/tests/ui/type/pattern_types/const_block.stderr new file mode 100644 index 000000000000..82b616105afa --- /dev/null +++ b/tests/ui/type/pattern_types/const_block.stderr @@ -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`. diff --git a/tests/ui/type/pattern_types/free_const.rs b/tests/ui/type/pattern_types/free_const.rs new file mode 100644 index 000000000000..2e29fce23797 --- /dev/null +++ b/tests/ui/type/pattern_types/free_const.rs @@ -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() {}