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::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
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);
|
let parent_id = tcx.local_parent(def_id);
|
||||||
matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
|
if matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
|
||||||
&& tcx.constness(parent_id) == hir::Constness::Const
|
&& 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,
|
/// Checks whether an item is considered to be `const`. If it is a constructor, it is const.
|
||||||
/// const block, const item or associated const, it is const. If it is a trait impl/function,
|
/// If it is an assoc method or function,
|
||||||
/// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic
|
/// 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 {
|
fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
||||||
let node = tcx.hir_node_by_def_id(def_id);
|
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::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
|
||||||
hir::Constness::Const
|
hir::Constness::Const
|
||||||
}
|
}
|
||||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
|
|
||||||
hir::Node::ForeignItem(_) => {
|
hir::Node::ForeignItem(_) => {
|
||||||
// Foreign items cannot be evaluated at compile-time.
|
// Foreign items cannot be evaluated at compile-time.
|
||||||
hir::Constness::NotConst
|
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 the function itself is not annotated with `const`, it may still be a `const fn`
|
||||||
// if it resides in a const trait impl.
|
// if it resides in a const trait impl.
|
||||||
let is_const = is_parent_const_impl_raw(tcx, def_id);
|
parent_impl_constness(tcx, def_id)
|
||||||
if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
|
|
||||||
} else {
|
} else {
|
||||||
tcx.dcx().span_bug(
|
tcx.dcx().span_bug(
|
||||||
tcx.def_span(def_id),
|
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| {
|
impl_.of_trait.as_ref().map(|ast_trait_ref| {
|
||||||
let selfty = tcx.type_of(def_id).instantiate_identity();
|
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);
|
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),
|
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||||
safety: impl_.safety,
|
safety: impl_.safety,
|
||||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
||||||
|
constness: impl_.constness,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_constness(
|
fn check_impl_constness(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
is_const: bool,
|
constness: hir::Constness,
|
||||||
hir_trait_ref: &hir::TraitRef<'_>,
|
hir_trait_ref: &hir::TraitRef<'_>,
|
||||||
) -> Option<ErrorGuaranteed> {
|
) {
|
||||||
if !is_const {
|
if let hir::Constness::NotConst = constness {
|
||||||
return None;
|
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) {
|
if tcx.is_const_trait(trait_def_id) {
|
||||||
return None;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_name = tcx.item_name(trait_def_id).to_string();
|
let trait_name = tcx.item_name(trait_def_id).to_string();
|
||||||
|
@ -1650,14 +1651,14 @@ fn check_impl_constness(
|
||||||
),
|
),
|
||||||
(false, _) | (_, false) => (None, ""),
|
(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_ref_span: hir_trait_ref.path.span,
|
||||||
trait_name,
|
trait_name,
|
||||||
local_trait_span,
|
local_trait_span,
|
||||||
suggestion_pre,
|
suggestion_pre,
|
||||||
marking: (),
|
marking: (),
|
||||||
adding: (),
|
adding: (),
|
||||||
}))
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn polarity_of_impl(
|
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 {
|
fn should_encode_constness(def_kind: DefKind) -> bool {
|
||||||
match def_kind {
|
match def_kind {
|
||||||
DefKind::Fn
|
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Ctor(_, CtorKind::Fn) => true,
|
||||||
| DefKind::AssocFn
|
|
||||||
| DefKind::Closure
|
|
||||||
| DefKind::Impl { of_trait: true }
|
|
||||||
| DefKind::Ctor(_, CtorKind::Fn) => true,
|
|
||||||
|
|
||||||
DefKind::Struct
|
DefKind::Struct
|
||||||
| DefKind::Union
|
| DefKind::Union
|
||||||
|
@ -1280,7 +1276,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Static { .. }
|
| DefKind::Static { .. }
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::OpaqueTy
|
| DefKind::OpaqueTy
|
||||||
| DefKind::Impl { of_trait: false }
|
| DefKind::Impl { .. }
|
||||||
| DefKind::ForeignTy
|
| DefKind::ForeignTy
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::InlineConst
|
| DefKind::InlineConst
|
||||||
|
|
|
@ -746,7 +746,8 @@ rustc_queries! {
|
||||||
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
|
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.
|
/// 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.
|
/// 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 {
|
pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
|
||||||
self.def_kind(def_id) == DefKind::Impl { of_trait: true }
|
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> {
|
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 trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
|
||||||
pub polarity: ImplPolarity,
|
pub polarity: ImplPolarity,
|
||||||
pub safety: hir::Safety,
|
pub safety: hir::Safety,
|
||||||
|
pub constness: hir::Constness,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
|
||||||
|
@ -2004,11 +2005,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
let def_id: DefId = def_id.into();
|
let def_id: DefId = def_id.into();
|
||||||
match self.def_kind(def_id) {
|
match self.def_kind(def_id) {
|
||||||
DefKind::Impl { of_trait: true } => {
|
DefKind::Impl { of_trait: true } => {
|
||||||
self.constness(def_id) == hir::Constness::Const
|
let header = self.impl_trait_header(def_id).unwrap();
|
||||||
&& self.is_const_trait(
|
header.constness == hir::Constness::Const
|
||||||
self.trait_id_of_impl(def_id)
|
&& self.is_const_trait(header.trait_ref.skip_binder().def_id)
|
||||||
.expect("expected trait for trait implementation"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
|
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
|
||||||
self.constness(def_id) == hir::Constness::Const
|
self.constness(def_id) == hir::Constness::Const
|
||||||
|
|
|
@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
.delay_as_bug();
|
.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?;
|
let (did, constness) = dtor_candidate?;
|
||||||
|
|
|
@ -128,7 +128,9 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
|
||||||
Err(_) => Err(EvaluationFailure::NoSolution),
|
Err(_) => Err(EvaluationFailure::NoSolution),
|
||||||
Ok(Some(source)) => match source {
|
Ok(Some(source)) => match source {
|
||||||
ImplSource::UserDefined(impl_) => {
|
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);
|
return Err(EvaluationFailure::NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue