Skip to content

Commit

Permalink
Retroactively feature gate ConstArgKind::Path
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxyUwU committed Aug 18, 2024
1 parent f04f6ca commit 7e42a2a
Show file tree
Hide file tree
Showing 40 changed files with 419 additions and 202 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id();
// HACK(min_generic_const_args): see lower_anon_const
if !expr.is_potential_trivial_const_arg() {
if !self.tcx.features().const_arg_path
|| !expr.is_potential_trivial_const_arg()
{
self.create_def(
parent_def_id,
node_id,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let node_id = self.next_node_id();

// HACK(min_generic_const_args): see lower_anon_const
if !arg.is_potential_trivial_const_arg() {
if !self.tcx.features().const_arg_path || !arg.is_potential_trivial_const_arg() {
// Add a definition for the in-band const def.
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
}
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2358,7 +2358,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span,
) -> &'hir hir::ConstArg<'hir> {
let ct_kind = match res {
Res::Def(DefKind::ConstParam, _) => {
Res::Def(DefKind::ConstParam, _) if self.tcx.features().const_arg_path => {
let qpath = self.lower_qpath(
ty_id,
&None,
Expand Down Expand Up @@ -2433,7 +2433,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
debug!("res={:?}", maybe_res);
// FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
if let Some(res) = maybe_res
if self.tcx.features().const_arg_path
&& let Some(res) = maybe_res
&& let Res::Def(DefKind::ConstParam, _) = res
&& let ExprKind::Path(qself, path) = &expr.kind
{
Expand Down Expand Up @@ -2464,7 +2465,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// See [`hir::ConstArg`] for when to use this function vs
/// [`Self::lower_anon_const_to_const_arg`].
fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
if c.value.is_potential_trivial_const_arg() {
if self.tcx.features().const_arg_path && c.value.is_potential_trivial_const_arg() {
// HACK(min_generic_const_args): see DefCollector::visit_anon_const
// Over there, we guess if this is a bare param and only create a def if
// we think it's not. However we may can guess wrong (see there for example)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ declare_features! (
(unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Gating for a new desugaring of const arguments of usages of const parameters
(internal, const_arg_path, "1.81.0", None),
/// Allows writing custom MIR
(internal, custom_mir, "1.65.0", None),
/// Outputs useful `assert!` messages
Expand Down
32 changes: 22 additions & 10 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl<'tcx> Const<'tcx> {

let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");

match Self::try_from_lit(tcx, ty, expr) {
match Self::try_from_lit_or_param(tcx, ty, expr) {
Some(v) => v,
None => ty::Const::new_unevaluated(
tcx,
Expand Down Expand Up @@ -281,7 +281,11 @@ impl<'tcx> Const<'tcx> {
}

#[instrument(skip(tcx), level = "debug")]
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
fn try_from_lit_or_param(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) -> Option<Self> {
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
Expand All @@ -291,6 +295,22 @@ impl<'tcx> Const<'tcx> {
_ => expr,
};

if let hir::ExprKind::Path(
qpath @ hir::QPath::Resolved(
_,
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
),
) = expr.kind
{
if tcx.features().const_arg_path {
span_bug!(
expr.span,
"try_from_lit: received const param which shouldn't be possible"
);
}
return Some(Const::from_param(tcx, qpath, expr.hir_id));
};

let lit_input = match expr.kind {
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
Expand Down Expand Up @@ -318,14 +338,6 @@ impl<'tcx> Const<'tcx> {
}
}

if let hir::ExprKind::Path(hir::QPath::Resolved(
_,
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
)) = expr.kind
{
span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
}

None
}

Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_resolve/src/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,15 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
}

fn visit_anon_const(&mut self, constant: &'a AnonConst) {
// HACK(min_generic_const_args): don't create defs for anon consts if we think they will
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
// may accidentally identify a construction of a unit struct as a param and not create a
// def. we'll then create a def later in ast lowering in this case. the parent of nested
// items will be messed up, but that's ok because there can't be any if we're just looking
// for bare idents.
if constant.value.is_potential_trivial_const_arg() {
if self.resolver.tcx.features().const_arg_path
&& constant.value.is_potential_trivial_const_arg()
{
// HACK(min_generic_const_args): don't create defs for anon consts if we think they will
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
// may accidentally identify a construction of a unit struct as a param and not create a
// def. we'll then create a def later in ast lowering in this case. the parent of nested
// items will be messed up, but that's ok because there can't be any if we're just looking
// for bare idents.
visit::walk_anon_const(self, constant)
} else {
let def =
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ symbols! {
conservative_impl_trait,
console,
const_allocate,
const_arg_path,
const_async_blocks,
const_closures,
const_compare_raw_pointers,
Expand Down
2 changes: 1 addition & 1 deletion tests/crashes/127972.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@ known-bug: #127962
#![feature(generic_const_exprs)]
#![feature(generic_const_exprs, const_arg_path)]

fn zero_init<const usize: usize>() -> Substs1<{ (N) }> {
Substs1([0; { (usize) }])
Expand Down
10 changes: 0 additions & 10 deletions tests/crashes/128016.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#![feature(with_negative_coherence)]
trait Trait {}
impl<const N: u8> Trait for [(); N] {}
//~^ ERROR: mismatched types
impl<const N: i8> Trait for [(); N] {}
//~^ ERROR: conflicting implementations of trait `Trait`
//~| ERROR: mismatched types

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]`
--> $DIR/generic_const_type_mismatch.rs:8:1
--> $DIR/generic_const_type_mismatch.rs:9:1
|
LL | impl<const N: u8> Trait for [(); N] {}
| ----------------------------------- first implementation here
LL |
LL | impl<const N: i8> Trait for [(); N] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]`

error: aborting due to 1 previous error
error[E0308]: mismatched types
--> $DIR/generic_const_type_mismatch.rs:7:34
|
LL | impl<const N: u8> Trait for [(); N] {}
| ^ expected `usize`, found `u8`

error[E0308]: mismatched types
--> $DIR/generic_const_type_mismatch.rs:9:34
|
LL | impl<const N: i8> Trait for [(); N] {}
| ^ expected `usize`, found `i8`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0119`.
Some errors have detailed explanations: E0119, E0308.
For more information about an error, try `rustc --explain E0119`.
1 change: 1 addition & 0 deletions tests/ui/const-generics/bad-subst-const-kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ trait Q {

impl<const N: u64> Q for [u8; N] {
//~^ ERROR: the constant `N` is not of type `usize`
//~| ERROR: mismatched types
const ASSOC: usize = 1;
}

Expand Down
11 changes: 9 additions & 2 deletions tests/ui/const-generics/bad-subst-const-kind.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | impl<const N: u64> Q for [u8; N] {
| ^^^^^^^ expected `usize`, found `u64`

error: the constant `13` is not of type `u64`
--> $DIR/bad-subst-const-kind.rs:13:24
--> $DIR/bad-subst-const-kind.rs:14:24
|
LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] {
| ^^^^^^^^ expected `u64`, found `usize`
Expand All @@ -18,5 +18,12 @@ LL | impl<const N: u64> Q for [u8; N] {
| |
| unsatisfied trait bound introduced here

error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/bad-subst-const-kind.rs:8:31
|
LL | impl<const N: u64> Q for [u8; N] {
| ^ expected `usize`, found `u64`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
21 changes: 21 additions & 0 deletions tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ check-pass

// This is a regression test for #128016.

macro_rules! len_inner {
() => {
BAR
};
}

macro_rules! len {
() => {
len_inner!()
};
}

const BAR: usize = 0;

fn main() {
let val: [bool; len!()] = [];
}
13 changes: 13 additions & 0 deletions tests/ui/const-generics/early/trivial-const-arg-macro-param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//@ check-pass

macro_rules! len {
($x:ident) => {
$x
};
}

fn bar<const N: usize>() {
let val: [bool; len!(N)] = [true; N];
}

fn main() {}
13 changes: 13 additions & 0 deletions tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This is a regression test for #128016.

macro_rules! len {
() => {
target
//~^ ERROR cannot find value `target`
};
}

fn main() {
let val: [str; len!()] = [];
//~^ ERROR the size for values
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0425]: cannot find value `target` in this scope
--> $DIR/trivial-const-arg-macro-res-error.rs:5:9
|
LL | target
| ^^^^^^ not found in this scope
...
LL | let val: [str; len!()] = [];
| ------ in this macro invocation
|
= note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/trivial-const-arg-macro-res-error.rs:11:14
|
LL | let val: [str; len!()] = [];
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
= note: slice and array elements must have `Sized` type

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
15 changes: 15 additions & 0 deletions tests/ui/const-generics/early/trivial-const-arg-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ check-pass

// This is a regression test for #128016.

macro_rules! len {
() => {
BAR
};
}

const BAR: usize = 0;

fn main() {
let val: [bool; len!()] = [];
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ trait Q {
impl<const N: u64> Q for [u8; N] {}
//~^ ERROR not all trait items implemented
//~| ERROR the constant `N` is not of type `usize`
//~| ERROR mismatched types

pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
//~^ ERROR the constant `13` is not of type `u64`
Expand Down
12 changes: 9 additions & 3 deletions tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LL | impl<const N: u64> Q for [u8; N] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation

error: the constant `13` is not of type `u64`
--> $DIR/type_mismatch.rs:12:26
--> $DIR/type_mismatch.rs:13:26
|
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
| ^^^^^^^^ expected `u64`, found `usize`
Expand All @@ -28,14 +28,20 @@ LL | impl<const N: u64> Q for [u8; N] {}
| unsatisfied trait bound introduced here

error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:12:20
--> $DIR/type_mismatch.rs:13:20
|
LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
| ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression

error: aborting due to 4 previous errors
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:8:31
|
LL | impl<const N: u64> Q for [u8; N] {}
| ^ expected `usize`, found `u64`

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0046, E0308.
For more information about an error, try `rustc --explain E0046`.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ mod v20 {
//~^ ERROR cannot find value `v8` in this scope
//~| ERROR cannot find function `v6` in this scope
pub struct v17<const v10: usize, const v7: v11> {
//~^ WARN type `v17` should have an upper camel case name
//~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
//~^ WARN type `v17` should have an upper camel case name
//~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
_p: (),
}

Expand All @@ -25,10 +25,10 @@ mod v20 {
}

impl<const v10: usize> v17<v10, v2> {
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
pub const fn v21() -> v18 {
//~^ ERROR cannot find type `v18` in this scope
//~^ ERROR cannot find type `v18` in this scope
v18 { _p: () }
//~^ ERROR cannot find struct, variant or union type `v18` in this scope
}
Expand Down
Loading

0 comments on commit 7e42a2a

Please sign in to comment.