Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1760,11 +1760,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let tcx = self.tcx();
let maybe_uneval = match constant.const_ {
Const::Ty(_, ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => Some(UnevaluatedConst {
def: uv.kind.def_id(),
args: uv.args,
promoted: None,
}),
ty::ConstKind::Unevaluated(uv) => match uv.kind {
ty::UnevaluatedConstKind::Projection { def_id }
| ty::UnevaluatedConstKind::Inherent { def_id }
| ty::UnevaluatedConstKind::Free { def_id }
| ty::UnevaluatedConstKind::Anon { def_id } => {
Some(UnevaluatedConst { def: def_id, args: uv.args, promoted: None })
}
},
_ => None,
},
Const::Unevaluated(uv, _) => Some(uv),
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
if has_default {
// need to store default and type of default
let ct = tcx.const_param_default(param.def_id).skip_binder();
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
tcx.ensure_ok().type_of(uv.kind.def_id());
if let ty::ConstKind::Unevaluated(uv) = ct.kind()
&& let Some(def_id) = uv.kind.opt_def_id()
{
tcx.ensure_ok().type_of(def_id);
}
}
}
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1535,11 +1535,7 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id:
| ty::ConstKind::Bound(_, _) => unreachable!(),
ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,
ty::ConstKind::Value(cv) => cv.ty,
ty::ConstKind::Unevaluated(uv) => infcx
.tcx
.type_of(uv.kind.def_id())
.instantiate(infcx.tcx, uv.args)
.skip_norm_wip(),
ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(),
ty::ConstKind::Param(param_ct) => {
param_ct.find_const_ty_from_env(wfcx.param_env)
}
Expand Down
20 changes: 13 additions & 7 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,16 @@ fn const_evaluatable_predicates_of<'tcx>(
preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
}

fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
let hir_id = tcx.local_def_id_to_hir_id(def);
fn is_const_param_default(tcx: TyCtxt<'_>, kind: ty::UnevaluatedConstKind<'_>) -> bool {
let def_id = match kind {
ty::UnevaluatedConstKind::Projection { def_id } => def_id,
ty::UnevaluatedConstKind::Inherent { def_id } => def_id,
ty::UnevaluatedConstKind::Free { def_id } => def_id,
ty::UnevaluatedConstKind::Anon { def_id } => def_id,
};
let Some(local) = def_id.as_local() else { return false };

let hir_id = tcx.local_def_id_to_hir_id(local);
let (_, parent_node) = tcx
.hir_parent_iter(hir_id)
.skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
Expand All @@ -435,9 +443,7 @@ fn const_evaluatable_predicates_of<'tcx>(
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
fn visit_const(&mut self, c: ty::Const<'tcx>) {
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
if let Some(local) = uv.kind.def_id().as_local()
&& is_const_param_default(self.tcx, local)
{
if is_const_param_default(self.tcx, uv.kind) {
// Do not look into const param defaults,
// these get checked when they are actually instantiated.
//
Expand All @@ -449,11 +455,11 @@ fn const_evaluatable_predicates_of<'tcx>(
}

// Skip type consts as mGCA doesn't support evaluatable clauses.
if self.tcx.is_type_const(uv.kind.def_id()) {
if uv.kind.is_type_const(self.tcx) {
return;
}

let span = self.tcx.def_span(uv.kind.def_id());
let span = uv.kind.def_span(self.tcx);
self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
}
}
Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_middle/src/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,14 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}

let cid = match ty::Instance::try_resolve(self, typing_env, ct.kind.def_id(), ct.args) {
let def_id = match ct.kind {
ty::UnevaluatedConstKind::Projection { def_id }
| ty::UnevaluatedConstKind::Inherent { def_id }
| ty::UnevaluatedConstKind::Free { def_id }
| ty::UnevaluatedConstKind::Anon { def_id } => def_id,
};

let cid = match ty::Instance::try_resolve(self, typing_env, def_id, ct.args) {
Ok(Some(instance)) => GlobalId { instance, promoted: None },
// For errors during resolution, we deliberately do not point at the usage site of the constant,
// since for these errors the place the constant is used shouldn't matter.
Expand Down Expand Up @@ -136,12 +143,14 @@ impl<'tcx> TyCtxt<'tcx> {
&& !self.is_trivial_const(cid.instance.def_id())
{
let mir_body = self.mir_for_ctfe(cid.instance.def_id());
if mir_body.is_polymorphic {
let Some(local_def_id) = ct.kind.def_id().as_local() else { return };
if mir_body.is_polymorphic
&& let Some(def_id) = ct.kind.opt_def_id()
&& let Some(local_def_id) = def_id.as_local()
{
self.emit_node_span_lint(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
self.local_def_id_to_hir_id(local_def_id),
self.def_span(ct.kind.def_id()),
self.def_span(def_id),
rustc_errors::DiagDecorator(|lint| {
lint.primary_message(
"cannot use constants which depend on generic parameters in types",
Expand Down
14 changes: 9 additions & 5 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1492,11 +1492,15 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
Const::Ty(_, ct) => match ct.kind() {
ty::ConstKind::Param(p) => format!("ty::Param({p})"),
ty::ConstKind::Unevaluated(uv) => {
format!(
"ty::Unevaluated({}, {:?})",
self.tcx.def_path_str(uv.kind.def_id()),
uv.args,
)
let kind = match uv.kind {
ty::UnevaluatedConstKind::Projection { def_id }
| ty::UnevaluatedConstKind::Inherent { def_id }
| ty::UnevaluatedConstKind::Free { def_id }
| ty::UnevaluatedConstKind::Anon { def_id } => {
self.tcx.def_path_str(def_id)
}
};
format!("ty::Unevaluated({}, {:?})", kind, uv.args)
}
ty::ConstKind::Value(cv) => {
format!("ty::Valtree({})", fmt_valtree(&cv))
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/abstract_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ impl<'tcx> TyCtxt<'tcx> {
}
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
let ct = match c.kind() {
ty::ConstKind::Unevaluated(uv) => {
match self.tcx.thir_abstract_const(uv.kind.def_id()) {
ty::ConstKind::Unevaluated(uv) if let Some(def_id) = uv.kind.opt_def_id() => {
match self.tcx.thir_abstract_const(def_id) {
Err(e) => ty::Const::new_error(self.tcx, e),
Ok(Some(bac)) => {
let args = self.tcx.erase_and_anonymize_regions(uv.args);
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/context/impl_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.anon_const_kind(def_id)
}

fn def_span(self, def_id: DefId) -> Span {
self.def_span(def_id)
}

type AdtDef = ty::AdtDef<'tcx>;
fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef {
self.adt_def(adt_def_id)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl<'tcx> ConstToPat<'tcx> {

// Mark the pattern to indicate that it is the result of lowering a named
// constant. This is used for diagnostics.
thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.kind.def_id());
thir_pat.extra.get_or_insert_default().expanded_const = uv.kind.opt_def_id();
thir_pat
}

Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,7 @@ where
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
.map_err(Into::into);
}
ty::ConstKind::Unevaluated(uv) => {
self.cx().type_of(uv.kind.def_id()).instantiate(self.cx(), uv.args).skip_norm_wip()
}
ty::ConstKind::Unevaluated(uv) => uv.type_of(self.cx()).skip_norm_wip(),
ty::ConstKind::Expr(_) => unimplemented!(
"`feature(generic_const_exprs)` is not supported in the new trait solver"
),
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_public/src/unstable/convert/stable/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,18 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
}
}
ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)),
ty::ConstKind::Unevaluated(uv) => crate::ty::TyConstKind::Unevaluated(
tables.const_def(uv.kind.def_id()),
uv.args.stable(tables, cx),
),
ty::ConstKind::Unevaluated(uv) => {
let Some(def_id) = uv.kind.opt_def_id() else {
// FIXME: implement (both AliasTy and UnevaluatedConst will be needing this soon)
panic!(
"non-defid unevaluated constants are not supported by rustc_public at the moment"
)
};
crate::ty::TyConstKind::Unevaluated(
tables.const_def(def_id),
uv.args.stable(tables, cx),
)
}
ty::ConstKind::Error(_) => unreachable!(),
ty::ConstKind::Infer(_) => unreachable!(),
ty::ConstKind::Bound(_, _) => unimplemented!(),
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,9 +692,14 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {

// We may still encounter unevaluated consts due to the printing
// logic sometimes passing identity-substituted impl headers.
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => {
return self.print_def_path(kind.def_id(), args);
}
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => match kind {
ty::UnevaluatedConstKind::Projection { def_id }
| ty::UnevaluatedConstKind::Inherent { def_id }
| ty::UnevaluatedConstKind::Free { def_id }
| ty::UnevaluatedConstKind::Anon { def_id } => {
return self.print_def_path(def_id, args);
}
},

ty::ConstKind::Expr(_)
| ty::ConstKind::Infer(_)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3745,44 +3745,39 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
ty::ConstKind::Unevaluated(uv) => {
let mut err =
self.dcx().struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(uv.kind.def_id());

let const_ty = self
.tcx
.type_of(uv.kind.def_id())
.instantiate(self.tcx, uv.args)
.skip_norm_wip();
let const_ty = uv.type_of(self.tcx).skip_norm_wip();
let cast = if const_ty != self.tcx.types.usize { " as usize" } else { "" };
let msg = "try adding a `where` bound";
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => {
let code = format!("[(); {snippet}{cast}]:");
let def_id = if let ObligationCauseCode::CompareImplItem {
trait_item_def_id,
..
} = obligation.cause.code()
{
trait_item_def_id.as_local()
} else {
Some(obligation.cause.body_id)
};
if let Some(def_id) = def_id
&& let Some(generics) = self.tcx.hir_get_generics(def_id)
{
err.span_suggestion_verbose(
generics.tail_span_for_predicate_suggestion(),
msg,
format!("{} {code}", generics.add_where_or_trailing_comma()),
Applicability::MaybeIncorrect,
);
} else {
err.help(format!("{msg}: where {code}"));
};
}
_ => {
err.help(msg);
}
};
if let Some(def_id) = uv.kind.opt_def_id()
&& let const_span = self.tcx.def_span(def_id)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(const_span)
{
let code = format!("[(); {snippet}{cast}]:");
let suggestion_def_id = if let ObligationCauseCode::CompareImplItem {
trait_item_def_id,
..
} = obligation.cause.code()
{
trait_item_def_id.as_local()
} else {
Some(obligation.cause.body_id)
};
if let Some(suggestion_def_id) = suggestion_def_id
&& let Some(generics) = self.tcx.hir_get_generics(suggestion_def_id)
{
err.span_suggestion_verbose(
generics.tail_span_for_predicate_suggestion(),
msg,
format!("{} {code}", generics.add_where_or_trailing_comma()),
Applicability::MaybeIncorrect,
);
} else {
err.help(format!("{msg}: where {code}"));
};
} else {
err.help(msg);
}
Ok(err)
}
ty::ConstKind::Expr(_) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>(
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => {
let ct_ty = match ct.kind() {
ty::ConstKind::Unevaluated(uv) => infcx
.tcx
.type_of(uv.kind.def_id())
.instantiate(infcx.tcx, uv.args)
.skip_norm_wip(),
ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(),
ty::ConstKind::Param(param_ct) => {
param_ct.find_const_ty_from_env(obligation.param_env)
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,10 +773,10 @@ impl<'tcx> AutoTraitFinder<'tcx> {
super::try_evaluate_const(selcx.infcx, c, obligation.param_env);

if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct {
self.tcx.dcx().emit_err(UnableToConstructConstantValue {
span: self.tcx.def_span(unevaluated.kind.def_id()),
unevaluated,
});
let span = unevaluated.kind.def_span(self.tcx);
self.tcx
.dcx()
.emit_err(UnableToConstructConstantValue { span, unevaluated });
}

ct
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub fn is_const_evaluatable<'tcx>(
tcx.dcx()
.struct_span_fatal(
// Slightly better span than just using `span` alone
if span == DUMMY_SP { tcx.def_span(uv.kind.def_id()) } else { span },
if span == DUMMY_SP { uv.kind.def_span(tcx) } else { span },
"failed to evaluate generic const expression",
)
.with_note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -886,16 +886,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
let ct = self.tcx.expand_abstract_consts(ct);

match ct.kind() {
ty::ConstKind::Unevaluated(
proj @ ty::UnevaluatedConst {
kind: ty::UnevaluatedConstKind::Projection { .. },
..
},
) if self.tcx.features().min_generic_const_args() => {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst {
kind: ty::UnevaluatedConstKind::Projection { def_id },
args,
..
}) if self.tcx.features().min_generic_const_args() => {
match self.allow_self_projections {
AllowSelfProjections::Yes => {
let trait_def_id = self.tcx.parent(proj.kind.def_id());
let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args);
let trait_def_id = self.tcx.parent(def_id);
let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, args);

// Only walk contained consts if the parent trait is not a supertrait.
if self.is_supertrait_of_current_trait(trait_ref) {
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,11 +559,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
return ProcessResult::Changed(PendingPredicateObligations::new());
}
ty::ConstKind::Value(cv) => cv.ty,
ty::ConstKind::Unevaluated(uv) => infcx
.tcx
.type_of(uv.kind.def_id())
.instantiate(infcx.tcx, uv.args)
.skip_norm_wip(),
ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(),
// FIXME(generic_const_exprs): we should construct an alias like
// `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
// `lhs + rhs`.
Expand Down
Loading
Loading