Move Const::{from_anon_const,try_from_lit}
to hir_ty_lowering
These operations are much more about lowering the HIR than about `Const`s themselves. They fit better in hir_ty_lowering with `lower_const_arg` (formerly `Const::from_const_arg`) and the rest. To accomplish this, `const_evaluatable_predicates_of` had to be changed to not use `from_anon_const` anymore. Instead of visiting the HIR and lowering anon consts on the fly, it now visits the `rustc_middle::ty` data structures instead and directly looks for `UnevaluatedConst`s. This approach was proposed in: https://github.com/rust-lang/rust/pull/131081#discussion_r1821189257
This commit is contained in:
parent
3bff51ea91
commit
277e049d91
@ -13,6 +13,7 @@ use rustc_hir::lang_items::LangItem;
|
|||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_macros::LintDiagnostic;
|
use rustc_macros::LintDiagnostic;
|
||||||
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||||
@ -1170,19 +1171,13 @@ fn check_type_defn<'tcx>(
|
|||||||
|
|
||||||
// Explicit `enum` discriminant values must const-evaluate successfully.
|
// Explicit `enum` discriminant values must const-evaluate successfully.
|
||||||
if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
|
if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
|
||||||
let cause = traits::ObligationCause::new(
|
match tcx.const_eval_poly(discr_def_id) {
|
||||||
tcx.def_span(discr_def_id),
|
Ok(_) => {}
|
||||||
wfcx.body_def_id,
|
Err(ErrorHandled::Reported(..)) => {}
|
||||||
ObligationCauseCode::Misc,
|
Err(ErrorHandled::TooGeneric(sp)) => {
|
||||||
);
|
span_bug!(sp, "enum variant discr was too generic to eval")
|
||||||
wfcx.register_obligation(Obligation::new(
|
}
|
||||||
tcx,
|
}
|
||||||
cause,
|
|
||||||
wfcx.param_env,
|
|
||||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
|
|
||||||
ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
|
|
||||||
))),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
||||||
use rustc_hir::intravisit;
|
use rustc_hir::intravisit;
|
||||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
@ -42,7 +42,8 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
|
pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
|
||||||
for did in tcx.hir().body_owners() {
|
for iid in tcx.hir().items() {
|
||||||
|
let did = iid.owner_id.def_id;
|
||||||
if tcx.has_attr(did, sym::rustc_dump_def_parents) {
|
if tcx.has_attr(did, sym::rustc_dump_def_parents) {
|
||||||
struct AnonConstFinder<'tcx> {
|
struct AnonConstFinder<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
@ -50,7 +51,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
|
impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
|
||||||
type NestedFilter = OnlyBodies;
|
type NestedFilter = nested_filter::All;
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> Self::Map {
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
self.tcx.hir()
|
self.tcx.hir()
|
||||||
@ -62,11 +63,11 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for any anon consts inside of this body owner as there is no way to apply
|
// Look for any anon consts inside of this item as there is no way to apply
|
||||||
// the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
|
// the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
|
||||||
// to see what its def parent is.
|
// to see what its def parent is.
|
||||||
let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
|
let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
|
||||||
intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value);
|
intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid));
|
||||||
|
|
||||||
for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
|
for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
|
||||||
let span = tcx.def_span(did);
|
let span = tcx.def_span(did);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
|
|
||||||
use hir::{HirId, Node};
|
use hir::Node;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_middle::ty::{
|
||||||
use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast};
|
self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
|
||||||
|
};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tcx.features().generic_const_exprs() {
|
if tcx.features().generic_const_exprs() {
|
||||||
predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
|
predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut predicates: Vec<_> = predicates.into_iter().collect();
|
let mut predicates: Vec<_> = predicates.into_iter().collect();
|
||||||
@ -369,32 +370,48 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_evaluatable_predicates_of(
|
#[instrument(level = "debug", skip(tcx, predicates), ret)]
|
||||||
tcx: TyCtxt<'_>,
|
fn const_evaluatable_predicates_of<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
) -> FxIndexSet<(ty::Clause<'_>, Span)> {
|
predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
|
||||||
|
) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
|
||||||
struct ConstCollector<'tcx> {
|
struct ConstCollector<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
|
preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
|
fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
|
||||||
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
let hir_id = tcx.local_def_id_to_hir_id(def);
|
||||||
let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
|
let (_, parent_node) = tcx
|
||||||
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
|
.hir()
|
||||||
let span = self.tcx.def_span(c.def_id);
|
.parent_iter(hir_id)
|
||||||
self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span));
|
.skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
|
||||||
}
|
.next()
|
||||||
}
|
.unwrap();
|
||||||
|
matches!(
|
||||||
|
parent_node,
|
||||||
|
Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
|
||||||
// Do not look into const param defaults,
|
fn visit_const(&mut self, c: ty::Const<'tcx>) {
|
||||||
// these get checked when they are actually instantiated.
|
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
|
||||||
//
|
if is_const_param_default(self.tcx, uv.def.expect_local()) {
|
||||||
// We do not want the following to error:
|
// Do not look into const param defaults,
|
||||||
//
|
// these get checked when they are actually instantiated.
|
||||||
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
|
//
|
||||||
// struct Bar<const N: usize>(Foo<N, 3>);
|
// We do not want the following to error:
|
||||||
|
//
|
||||||
|
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
|
||||||
|
// struct Bar<const N: usize>(Foo<N, 3>);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let span = self.tcx.def_span(uv.def);
|
||||||
|
self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,29 +419,32 @@ fn const_evaluatable_predicates_of(
|
|||||||
let node = tcx.hir_node(hir_id);
|
let node = tcx.hir_node(hir_id);
|
||||||
|
|
||||||
let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
|
let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
|
||||||
|
|
||||||
|
for (clause, _sp) in predicates {
|
||||||
|
clause.visit_with(&mut collector);
|
||||||
|
}
|
||||||
|
|
||||||
if let hir::Node::Item(item) = node
|
if let hir::Node::Item(item) = node
|
||||||
&& let hir::ItemKind::Impl(impl_) = item.kind
|
&& let hir::ItemKind::Impl(_) = item.kind
|
||||||
{
|
{
|
||||||
if let Some(of_trait) = &impl_.of_trait {
|
if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
|
||||||
debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
|
debug!("visit impl trait_ref");
|
||||||
collector.visit_trait_ref(of_trait);
|
of_trait.instantiate_identity().visit_with(&mut collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
|
debug!("visit self_ty");
|
||||||
collector.visit_ty(impl_.self_ty);
|
let self_ty = tcx.type_of(def_id);
|
||||||
|
self_ty.instantiate_identity().visit_with(&mut collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(generics) = node.generics() {
|
if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) {
|
||||||
debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
|
debug!("visit fn sig");
|
||||||
collector.visit_generics(generics);
|
let fn_sig = tcx.fn_sig(def_id);
|
||||||
|
let fn_sig = fn_sig.instantiate_identity();
|
||||||
|
debug!(?fn_sig);
|
||||||
|
fn_sig.visit_with(&mut collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
|
|
||||||
debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
|
|
||||||
collector.visit_fn_decl(fn_sig.decl);
|
|
||||||
}
|
|
||||||
debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);
|
|
||||||
|
|
||||||
collector.preds
|
collector.preds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2089,7 +2089,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
qpath.span(),
|
qpath.span(),
|
||||||
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
|
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
|
||||||
),
|
),
|
||||||
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
|
hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id),
|
||||||
hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
|
hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2177,6 +2177,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||||
|
/// becomes `Unevaluated`.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
let body_id = match tcx.hir_node_by_def_id(def) {
|
||||||
|
hir::Node::AnonConst(ac) => ac.body,
|
||||||
|
node => span_bug!(
|
||||||
|
tcx.def_span(def.to_def_id()),
|
||||||
|
"from_anon_const can only process anonymous constants, not {node:?}"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let expr = &tcx.hir().body(body_id).value;
|
||||||
|
debug!(?expr);
|
||||||
|
|
||||||
|
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
||||||
|
|
||||||
|
match self.try_lower_anon_const_lit(ty, expr) {
|
||||||
|
Some(v) => v,
|
||||||
|
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
|
||||||
|
def: def.to_def_id(),
|
||||||
|
args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
fn try_lower_anon_const_lit(
|
||||||
|
&self,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
) -> Option<Const<'tcx>> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
|
||||||
|
block.expr.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
_ => expr,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let hir::ExprKind::Path(hir::QPath::Resolved(
|
||||||
|
_,
|
||||||
|
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
|
||||||
|
)) = expr.kind
|
||||||
|
{
|
||||||
|
span_bug!(
|
||||||
|
expr.span,
|
||||||
|
"try_lower_anon_const_lit: received const param which shouldn't be possible"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
||||||
|
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(lit_input) = lit_input {
|
||||||
|
// If an error occurred, ignore that it's a literal and leave reporting the error up to
|
||||||
|
// mir.
|
||||||
|
match tcx.at(expr.span).lit_to_const(lit_input) {
|
||||||
|
Ok(c) => return Some(c),
|
||||||
|
Err(_) if lit_input.ty.has_aliases() => {
|
||||||
|
// allow the `ty` to be an alias type, though we cannot handle it here
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tcx.dcx().span_delayed_bug(
|
||||||
|
expr.span,
|
||||||
|
format!("try_lower_anon_const_lit: couldn't lit_to_const {e:?}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
|
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
|
||||||
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
|
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
|
||||||
match idx {
|
match idx {
|
||||||
|
@ -2,15 +2,11 @@ use std::borrow::Cow;
|
|||||||
|
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_error_messages::MultiSpan;
|
use rustc_error_messages::MultiSpan;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
|
||||||
use rustc_hir::def_id::LocalDefId;
|
|
||||||
use rustc_hir::{self as hir};
|
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||||
use tracing::{debug, instrument};
|
|
||||||
|
|
||||||
use crate::mir::interpret::{LitToConstInput, Scalar};
|
use crate::mir::interpret::Scalar;
|
||||||
use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
mod int;
|
mod int;
|
||||||
mod kind;
|
mod kind;
|
||||||
@ -181,82 +177,6 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
// FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
|
|
||||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
|
||||||
/// becomes `Unevaluated`.
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
|
||||||
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
|
|
||||||
let body_id = match tcx.hir_node_by_def_id(def) {
|
|
||||||
hir::Node::AnonConst(ac) => ac.body,
|
|
||||||
node => span_bug!(
|
|
||||||
tcx.def_span(def.to_def_id()),
|
|
||||||
"from_anon_const can only process anonymous constants, not {node:?}"
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let expr = &tcx.hir().body(body_id).value;
|
|
||||||
debug!(?expr);
|
|
||||||
|
|
||||||
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
|
||||||
|
|
||||||
match Self::try_from_lit(tcx, ty, expr) {
|
|
||||||
Some(v) => v,
|
|
||||||
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
|
|
||||||
def: def.to_def_id(),
|
|
||||||
args: GenericArgs::identity_for_item(tcx, def.to_def_id()),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
|
||||||
fn try_from_lit(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 {
|
|
||||||
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
|
|
||||||
block.expr.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
_ => expr,
|
|
||||||
};
|
|
||||||
|
|
||||||
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");
|
|
||||||
};
|
|
||||||
|
|
||||||
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 {
|
|
||||||
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(lit_input) = lit_input {
|
|
||||||
// If an error occurred, ignore that it's a literal and leave reporting the error up to
|
|
||||||
// mir.
|
|
||||||
match tcx.at(expr.span).lit_to_const(lit_input) {
|
|
||||||
Ok(c) => return Some(c),
|
|
||||||
Err(_) if lit_input.ty.has_aliases() => {
|
|
||||||
// allow the `ty` to be an alias type, though we cannot handle it here
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
tcx.dcx().span_delayed_bug(
|
|
||||||
expr.span,
|
|
||||||
format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a constant with the given integer value and interns it.
|
/// Creates a constant with the given integer value and interns it.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bits(
|
pub fn from_bits(
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
//@ known-bug: #121429
|
//@ known-bug: #121429
|
||||||
|
|
||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
|
|
||||||
pub trait True {}
|
struct FixedI8<const X: usize>;
|
||||||
|
const FRAC_LHS: usize = 0;
|
||||||
impl<const N: usize = { const { 3 } }> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> where
|
const FRAC_RHS: usize = 1;
|
||||||
If<{}>: True
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#![feature(generic_const_exprs)]
|
|
||||||
|
|
||||||
pub trait True {}
|
pub trait True {}
|
||||||
|
|
||||||
|
@ -3,16 +3,17 @@
|
|||||||
|
|
||||||
fn bar() {
|
fn bar() {
|
||||||
fn foo() {
|
fn foo() {
|
||||||
|
#[rustc_dump_def_parents]
|
||||||
fn baz() {
|
fn baz() {
|
||||||
#[rustc_dump_def_parents]
|
//~^ ERROR: rustc_dump_def_parents: DefId
|
||||||
|| {
|
|| {
|
||||||
//~^ ERROR: rustc_dump_def_parents: DefId
|
|
||||||
qux::<
|
qux::<
|
||||||
{
|
{
|
||||||
//~^ ERROR: rustc_dump_def_parents: DefId
|
//~^ ERROR: rustc_dump_def_parents: DefId
|
||||||
fn inhibits_dump() {
|
fn inhibits_dump() {
|
||||||
qux::<
|
qux::<
|
||||||
{
|
{
|
||||||
|
//~^ ERROR: rustc_dump_def_parents: DefId
|
||||||
"hi";
|
"hi";
|
||||||
1
|
1
|
||||||
},
|
},
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
error: rustc_dump_def_parents: DefId(..)
|
error: rustc_dump_def_parents: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:8:13
|
--> $DIR/dump_def_parents.rs:7:9
|
||||||
|
|
|
||||||
LL | || {
|
|
||||||
| ^^
|
|
||||||
|
|
|
||||||
note: DefId(..)
|
|
||||||
--> $DIR/dump_def_parents.rs:6:9
|
|
||||||
|
|
|
|
||||||
LL | fn baz() {
|
LL | fn baz() {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
note: DefId(..)
|
note: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:5:5
|
--> $DIR/dump_def_parents.rs:5:5
|
||||||
|
|
|
|
||||||
@ -44,12 +39,12 @@ LL | | },
|
|||||||
| |_____________________^
|
| |_____________________^
|
||||||
|
|
|
|
||||||
note: DefId(..)
|
note: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:8:13
|
--> $DIR/dump_def_parents.rs:9:13
|
||||||
|
|
|
|
||||||
LL | || {
|
LL | || {
|
||||||
| ^^
|
| ^^
|
||||||
note: DefId(..)
|
note: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:6:9
|
--> $DIR/dump_def_parents.rs:7:9
|
||||||
|
|
|
|
||||||
LL | fn baz() {
|
LL | fn baz() {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
@ -76,7 +71,65 @@ LL | | fn main() {}
|
|||||||
| |____________^
|
| |____________^
|
||||||
|
|
||||||
error: rustc_dump_def_parents: DefId(..)
|
error: rustc_dump_def_parents: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:22:31
|
--> $DIR/dump_def_parents.rs:15:33
|
||||||
|
|
|
||||||
|
LL | / ... {
|
||||||
|
LL | | ...
|
||||||
|
LL | | ... "hi";
|
||||||
|
LL | | ... 1
|
||||||
|
LL | | ... },
|
||||||
|
| |_______________________^
|
||||||
|
|
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:13:25
|
||||||
|
|
|
||||||
|
LL | fn inhibits_dump() {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:11:21
|
||||||
|
|
|
||||||
|
LL | / {
|
||||||
|
LL | |
|
||||||
|
LL | | fn inhibits_dump() {
|
||||||
|
LL | | qux::<
|
||||||
|
... |
|
||||||
|
LL | | 1
|
||||||
|
LL | | },
|
||||||
|
| |_____________________^
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:9:13
|
||||||
|
|
|
||||||
|
LL | || {
|
||||||
|
| ^^
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:7:9
|
||||||
|
|
|
||||||
|
LL | fn baz() {
|
||||||
|
| ^^^^^^^^
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:5:5
|
||||||
|
|
|
||||||
|
LL | fn foo() {
|
||||||
|
| ^^^^^^^^
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:4:1
|
||||||
|
|
|
||||||
|
LL | fn bar() {
|
||||||
|
| ^^^^^^^^
|
||||||
|
note: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:2:1
|
||||||
|
|
|
||||||
|
LL | / #![feature(rustc_attrs)]
|
||||||
|
LL | |
|
||||||
|
LL | | fn bar() {
|
||||||
|
LL | | fn foo() {
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | fn main() {}
|
||||||
|
| |____________^
|
||||||
|
|
||||||
|
error: rustc_dump_def_parents: DefId(..)
|
||||||
|
--> $DIR/dump_def_parents.rs:23:31
|
||||||
|
|
|
|
||||||
LL | qux::<{ 1 + 1 }>();
|
LL | qux::<{ 1 + 1 }>();
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
@ -93,12 +146,12 @@ LL | | 1
|
|||||||
LL | | },
|
LL | | },
|
||||||
| |_____________________^
|
| |_____________________^
|
||||||
note: DefId(..)
|
note: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:8:13
|
--> $DIR/dump_def_parents.rs:9:13
|
||||||
|
|
|
|
||||||
LL | || {
|
LL | || {
|
||||||
| ^^
|
| ^^
|
||||||
note: DefId(..)
|
note: DefId(..)
|
||||||
--> $DIR/dump_def_parents.rs:6:9
|
--> $DIR/dump_def_parents.rs:7:9
|
||||||
|
|
|
|
||||||
LL | fn baz() {
|
LL | fn baz() {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
@ -124,5 +177,5 @@ LL | |
|
|||||||
LL | | fn main() {}
|
LL | | fn main() {}
|
||||||
| |____________^
|
| |____________^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
//@ known-bug: rust-lang/rust#128176
|
//@ check-pass
|
||||||
|
|
||||||
|
// Regression test for #128176.
|
||||||
|
|
||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
#![feature(dyn_compatible_for_dispatch)]
|
#![feature(dyn_compatible_for_dispatch)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
trait X {
|
trait X {
|
||||||
type Y<const N: i16>;
|
type Y<const N: i16>;
|
||||||
}
|
}
|
@ -10,11 +10,11 @@ note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorD
|
|||||||
LL | trait TensorDimension {
|
LL | trait TensorDimension {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
|
= note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
|
||||||
note: cycle used when computing candidate for `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>`
|
note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:50:1: 50:94>::size` is compatible with trait definition
|
||||||
--> $DIR/issue-83765.rs:4:1
|
--> $DIR/issue-83765.rs:51:5
|
||||||
|
|
|
|
||||||
LL | trait TensorDimension {
|
LL | fn size(&self) -> [usize; DIM] {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= 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
|
= 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[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`
|
error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user