Move impl constness into impl trait header
This commit is contained in:
parent
c0e0d8f874
commit
2ffe3b1e70
8 changed files with 35 additions and 33 deletions
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
|
|
@ -1611,7 +1611,7 @@ 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);
|
||||
|
||||
|
@ -1619,22 +1619,23 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
|||
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();
|
||||
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)]
|
||||
|
@ -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
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue