Skip to content

Commit

Permalink
Move impl constness into impl trait header
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Dec 12, 2024
1 parent c0e0d8f commit 2ffe3b1
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 33 deletions.
21 changes: 12 additions & 9 deletions compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;

fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
fn parent_impl_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
let parent_id = tcx.local_parent(def_id);
matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
&& tcx.constness(parent_id) == hir::Constness::Const
if matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
&& let Some(header) = tcx.impl_trait_header(parent_id)
{
header.constness
} else {
hir::Constness::NotConst
}
}

/// Checks whether an item is considered to be `const`. If it is a constructor, anonymous const,
/// const block, const item or associated const, it is const. If it is a trait impl/function,
/// Checks whether an item is considered to be `const`. If it is a constructor, it is const.
/// If it is an assoc method or function,
/// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic
/// has a `rustc_const_{un,}stable` attribute. Otherwise, return `Constness::NotConst`.
/// has a `rustc_const_{un,}stable` attribute. Otherwise, panic.
fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
let node = tcx.hir_node_by_def_id(def_id);

Expand All @@ -22,7 +27,6 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
hir::Constness::Const
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
hir::Node::ForeignItem(_) => {
// Foreign items cannot be evaluated at compile-time.
hir::Constness::NotConst
Expand All @@ -36,8 +40,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {

// If the function itself is not annotated with `const`, it may still be a `const fn`
// if it resides in a const trait impl.
let is_const = is_parent_const_impl_raw(tcx, def_id);
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
parent_impl_constness(tcx, def_id)
} else {
tcx.dcx().span_bug(
tcx.def_span(def_id),
Expand Down
19 changes: 10 additions & 9 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,30 +1611,31 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id).instantiate_identity();

check_impl_constness(tcx, tcx.is_const_trait_impl(def_id.to_def_id()), ast_trait_ref);
check_impl_constness(tcx, impl_.constness, ast_trait_ref);

let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);

ty::ImplTraitHeader {
trait_ref: ty::EarlyBinder::bind(trait_ref),
safety: impl_.safety,
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
constness: impl_.constness,
}
})
}

fn check_impl_constness(
tcx: TyCtxt<'_>,
is_const: bool,
constness: hir::Constness,
hir_trait_ref: &hir::TraitRef<'_>,
) -> Option<ErrorGuaranteed> {
if !is_const {
return None;
) {
if let hir::Constness::NotConst = constness {
return;
}

let trait_def_id = hir_trait_ref.trait_def_id()?;
let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
if tcx.is_const_trait(trait_def_id) {
return None;
return;
}

let trait_name = tcx.item_name(trait_def_id).to_string();
Expand All @@ -1650,14 +1651,14 @@ fn check_impl_constness(
),
(false, _) | (_, false) => (None, ""),
};
Some(tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
trait_ref_span: hir_trait_ref.path.span,
trait_name,
local_trait_span,
suggestion_pre,
marking: (),
adding: (),
}))
});
}

fn polarity_of_impl(
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1264,11 +1264,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {

fn should_encode_constness(def_kind: DefKind) -> bool {
match def_kind {
DefKind::Fn
| DefKind::AssocFn
| DefKind::Closure
| DefKind::Impl { of_trait: true }
| DefKind::Ctor(_, CtorKind::Fn) => true,
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Ctor(_, CtorKind::Fn) => true,

DefKind::Struct
| DefKind::Union
Expand All @@ -1280,7 +1276,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
| DefKind::Static { .. }
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::Impl { of_trait: false }
| DefKind::Impl { .. }
| DefKind::ForeignTy
| DefKind::ConstParam
| DefKind::InlineConst
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,8 @@ rustc_queries! {
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
}

/// Returns the constness of functions and impls.
/// Returns the constness of function-like things (tuple struct/variant constructors, functions,
/// methods)
///
/// Will ICE if used on things that are always const or never const.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3141,7 +3141,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Whether the trait impl is marked const. This does not consider stability or feature gates.
pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
self.def_kind(def_id) == DefKind::Impl { of_trait: true }
&& self.constness(def_id) == hir::Constness::Const
&& self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const
}

pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> {
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ pub struct ImplTraitHeader<'tcx> {
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
pub polarity: ImplPolarity,
pub safety: hir::Safety,
pub constness: hir::Constness,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
Expand Down Expand Up @@ -2004,11 +2005,9 @@ impl<'tcx> TyCtxt<'tcx> {
let def_id: DefId = def_id.into();
match self.def_kind(def_id) {
DefKind::Impl { of_trait: true } => {
self.constness(def_id) == hir::Constness::Const
&& self.is_const_trait(
self.trait_id_of_impl(def_id)
.expect("expected trait for trait implementation"),
)
let header = self.impl_trait_header(def_id).unwrap();
header.constness == hir::Constness::Const
&& self.is_const_trait(header.trait_ref.skip_binder().def_id)
}
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
self.constness(def_id) == hir::Constness::Const
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
.delay_as_bug();
}

dtor_candidate = Some((*item_id, self.constness(impl_did)));
dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
});

let (did, constness) = dtor_candidate?;
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_trait_selection/src/traits/effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
Err(_) => Err(EvaluationFailure::NoSolution),
Ok(Some(source)) => match source {
ImplSource::UserDefined(impl_) => {
if tcx.constness(impl_.impl_def_id) != hir::Constness::Const {
if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness
!= hir::Constness::Const
{
return Err(EvaluationFailure::NoSolution);
}

Expand Down

0 comments on commit 2ffe3b1

Please sign in to comment.