-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Allow projections to be used as const generic #104443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
291bc0d
eed7738
9587fd7
00d9f41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,6 +74,11 @@ impl<'tcx> Const<'tcx> { | |
|
||
let ty = tcx.type_of(def.def_id_for_type_of()); | ||
|
||
let param_env = tcx.param_env(def.did); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This normalization is causing a lot of cycle error. If I nest it into a Do you have any idea what's going on here? Why would normalization would create cycle errors? (in code like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah yeah ofc that causes issues 😅 having a const parameter in the where clauses now relies on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any idea how to fix it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not really 😅 even changing the type of type level constants to not inherit their parents generics won't work because normalization depends on impl headers which can also contain If we were to delay normalization of the type of consts to a later point this may mostly work. tbh that makes me think that we shouldn't land this change and should keep forbidding projections in the type of type system constants. Sorry for not noticing this issue earlier 😅 especially as we've had to deal with pretty much the same issue for |
||
// We check that the `ty` is well formed in `wfcheck::check_param_wf` so | ||
// this should always succeed. | ||
let ty = tcx.normalize_erasing_regions(param_env, ty); | ||
|
||
match Self::try_eval_lit_or_param(tcx, ty, expr) { | ||
Some(v) => v, | ||
None => tcx.mk_const( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId; | |
use rustc_index::vec::IndexVec; | ||
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; | ||
use rustc_middle::ty::abstract_const::{CastKind, Node, NodeId}; | ||
use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; | ||
use rustc_middle::ty::{self, ParamEnv, TyCtxt, TypeVisitable}; | ||
use rustc_middle::{mir, thir}; | ||
use rustc_span::Span; | ||
use rustc_target::abi::VariantIdx; | ||
|
@@ -222,6 +222,9 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | |
fn recurse_build(&mut self, node: thir::ExprId) -> Result<NodeId, ErrorGuaranteed> { | ||
use thir::ExprKind; | ||
let node = &self.body.exprs[node]; | ||
let param_env = ParamEnv::reveal_all().with_reveal_all_normalized(self.tcx); | ||
let node_ty = self.tcx.try_normalize_erasing_regions(param_env, node.ty).unwrap_or(node.ty); | ||
Comment on lines
+225
to
+226
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both The fact that an unnormalized type ends up in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I marked this as resolved mistakenly. Should still check where the node gets its type and normalize there |
||
|
||
Ok(match &node.kind { | ||
// I dont know if handling of these 3 is correct | ||
&ExprKind::Scope { value, .. } => self.recurse_build(value)?, | ||
|
@@ -231,12 +234,12 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | |
let sp = node.span; | ||
let constant = match self.tcx.at(sp).lit_to_const(LitToConstInput { | ||
lit: &lit.node, | ||
ty: node.ty, | ||
ty: node_ty, | ||
neg, | ||
}) { | ||
Ok(c) => c, | ||
Err(LitToConstError::Reported(guar)) => { | ||
self.tcx.const_error_with_guaranteed(node.ty, guar) | ||
self.tcx.const_error_with_guaranteed(node_ty, guar) | ||
} | ||
Err(LitToConstError::TypeError) => { | ||
bug!("encountered type error in lit_to_const") | ||
|
@@ -247,23 +250,23 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | |
} | ||
&ExprKind::NonHirLiteral { lit, user_ty: _ } => { | ||
let val = ty::ValTree::from_scalar_int(lit); | ||
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty))) | ||
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node_ty))) | ||
} | ||
&ExprKind::ZstLiteral { user_ty: _ } => { | ||
let val = ty::ValTree::zst(); | ||
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty))) | ||
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node_ty))) | ||
} | ||
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => { | ||
let uneval = | ||
ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs); | ||
|
||
let constant = self.tcx.mk_const(ty::ConstKind::Unevaluated(uneval), node.ty); | ||
let constant = self.tcx.mk_const(ty::ConstKind::Unevaluated(uneval), node_ty); | ||
|
||
self.nodes.push(Node::Leaf(constant)) | ||
} | ||
|
||
ExprKind::ConstParam { param, .. } => { | ||
let const_param = self.tcx.mk_const(ty::ConstKind::Param(*param), node.ty); | ||
let const_param = self.tcx.mk_const(ty::ConstKind::Param(*param), node_ty); | ||
self.nodes.push(Node::Leaf(const_param)) | ||
} | ||
|
||
|
@@ -308,11 +311,11 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { | |
// This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) | ||
&ExprKind::Use { source } => { | ||
let arg = self.recurse_build(source)?; | ||
self.nodes.push(Node::Cast(CastKind::Use, arg, node.ty)) | ||
self.nodes.push(Node::Cast(CastKind::Use, arg, node_ty)) | ||
} | ||
&ExprKind::Cast { source } => { | ||
let arg = self.recurse_build(source)?; | ||
self.nodes.push(Node::Cast(CastKind::As, arg, node.ty)) | ||
self.nodes.push(Node::Cast(CastKind::As, arg, node_ty)) | ||
} | ||
ExprKind::Borrow { arg, .. } => { | ||
let arg_node = &self.body.exprs[*arg]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// run-pass | ||
|
||
pub trait Identity { | ||
type Identity; | ||
} | ||
|
||
impl<T> Identity for T { | ||
type Identity = Self; | ||
} | ||
|
||
pub fn foo<const X: <i32 as Identity>::Identity>() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tbh I am not sure whether i want to insta stabilize projections in const params or keep them as part of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As you prefer! If a FCP is needed, I'll let someone from your team handle this part. |
||
assert!(X == 12); | ||
} | ||
|
||
fn main() { | ||
foo::<12>(); | ||
} |
Uh oh!
There was an error while loading. Please reload this page.