mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 07:44:10 +00:00
Introduce min_generic_const_args
and directly represent paths
Co-authored-by: Boxy UwU <rust@boxyuwu.dev> Co-authored-by: León Orell Valerian Liehr <me@fmease.dev>
This commit is contained in:
parent
b71fb5edc0
commit
59e339f766
@ -2052,6 +2052,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used when lowering a type argument that turned out to actually be a const argument.
|
||||||
|
///
|
||||||
|
/// Only use for that purpose since otherwise it will create a duplicate def.
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn lower_const_path_to_const_arg(
|
fn lower_const_path_to_const_arg(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -2060,51 +2063,58 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
ty_id: NodeId,
|
ty_id: NodeId,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> &'hir hir::ConstArg<'hir> {
|
) -> &'hir hir::ConstArg<'hir> {
|
||||||
let ct_kind = match res {
|
let tcx = self.tcx;
|
||||||
Res::Def(DefKind::ConstParam, _) => {
|
|
||||||
let qpath = self.lower_qpath(
|
|
||||||
ty_id,
|
|
||||||
&None,
|
|
||||||
path,
|
|
||||||
ParamMode::Optional,
|
|
||||||
AllowReturnTypeNotation::No,
|
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
hir::ConstArgKind::Path(qpath)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
|
||||||
|
|
||||||
let parent_def_id = self.current_def_id_parent;
|
// FIXME(min_generic_const_args): we only allow one-segment const paths for now
|
||||||
let node_id = self.next_node_id();
|
let ct_kind = if path.is_potential_trivial_const_arg()
|
||||||
let span = self.lower_span(span);
|
&& (tcx.features().min_generic_const_args()
|
||||||
|
|| matches!(res, Res::Def(DefKind::ConstParam, _)))
|
||||||
|
{
|
||||||
|
let qpath = self.lower_qpath(
|
||||||
|
ty_id,
|
||||||
|
&None,
|
||||||
|
path,
|
||||||
|
ParamMode::Optional,
|
||||||
|
AllowReturnTypeNotation::No,
|
||||||
|
// FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
|
||||||
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
hir::ConstArgKind::Path(qpath)
|
||||||
|
} else {
|
||||||
|
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||||
|
|
||||||
// Add a definition for the in-band const def.
|
let parent_def_id = self.current_def_id_parent;
|
||||||
let def_id =
|
let node_id = self.next_node_id();
|
||||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
let span = self.lower_span(span);
|
||||||
let hir_id = self.lower_node_id(node_id);
|
|
||||||
|
|
||||||
let path_expr = Expr {
|
// Add a definition for the in-band const def.
|
||||||
id: ty_id,
|
// We're lowering a const argument that was originally thought to be a type argument,
|
||||||
kind: ExprKind::Path(None, path.clone()),
|
// so the def collector didn't create the def ahead of time. That's why we have to do
|
||||||
|
// it here.
|
||||||
|
let def_id =
|
||||||
|
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
||||||
|
let hir_id = self.lower_node_id(node_id);
|
||||||
|
|
||||||
|
let path_expr = Expr {
|
||||||
|
id: ty_id,
|
||||||
|
kind: ExprKind::Path(None, path.clone()),
|
||||||
|
span,
|
||||||
|
attrs: AttrVec::new(),
|
||||||
|
tokens: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ct = self.with_new_scopes(span, |this| {
|
||||||
|
self.arena.alloc(hir::AnonConst {
|
||||||
|
def_id,
|
||||||
|
hir_id,
|
||||||
|
body: this.with_def_id_parent(def_id, |this| {
|
||||||
|
this.lower_const_body(path_expr.span, Some(&path_expr))
|
||||||
|
}),
|
||||||
span,
|
span,
|
||||||
attrs: AttrVec::new(),
|
})
|
||||||
tokens: None,
|
});
|
||||||
};
|
hir::ConstArgKind::Anon(ct)
|
||||||
|
|
||||||
let ct = self.with_new_scopes(span, |this| {
|
|
||||||
self.arena.alloc(hir::AnonConst {
|
|
||||||
def_id,
|
|
||||||
hir_id,
|
|
||||||
body: this.with_def_id_parent(def_id, |this| {
|
|
||||||
this.lower_const_body(path_expr.span, Some(&path_expr))
|
|
||||||
}),
|
|
||||||
span,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
hir::ConstArgKind::Anon(ct)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.arena.alloc(hir::ConstArg {
|
self.arena.alloc(hir::ConstArg {
|
||||||
@ -2122,6 +2132,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
|
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
|
||||||
|
let tcx = self.tcx;
|
||||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
// 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.
|
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||||
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
|
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
|
||||||
@ -2135,18 +2146,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
};
|
};
|
||||||
let maybe_res =
|
let maybe_res =
|
||||||
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
|
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
|
||||||
debug!("res={:?}", maybe_res);
|
// FIXME(min_generic_const_args): we only allow one-segment const paths for now
|
||||||
// FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
|
if let ExprKind::Path(None, path) = &expr.kind
|
||||||
if let Some(res) = maybe_res
|
&& path.is_potential_trivial_const_arg()
|
||||||
&& let Res::Def(DefKind::ConstParam, _) = res
|
&& (tcx.features().min_generic_const_args()
|
||||||
&& let ExprKind::Path(qself, path) = &expr.kind
|
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
|
||||||
{
|
{
|
||||||
let qpath = self.lower_qpath(
|
let qpath = self.lower_qpath(
|
||||||
expr.id,
|
expr.id,
|
||||||
qself,
|
&None,
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
AllowReturnTypeNotation::No,
|
AllowReturnTypeNotation::No,
|
||||||
|
// FIXME(min_generic_const_args): update for `fn foo() -> Bar<FOO<impl Trait>>` support
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -529,6 +529,8 @@ declare_features! (
|
|||||||
(unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
|
(unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
|
||||||
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
||||||
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
|
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
|
||||||
|
/// Enables the generic const args MVP (only bare paths, not arbitrary computation).
|
||||||
|
(incomplete, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980)),
|
||||||
/// A minimal, sound subset of specialization intended to be used by the
|
/// A minimal, sound subset of specialization intended to be used by the
|
||||||
/// standard library until the soundness issues with specialization
|
/// standard library until the soundness issues with specialization
|
||||||
/// are fixed.
|
/// are fixed.
|
||||||
|
@ -46,7 +46,7 @@ use tracing::{debug, instrument};
|
|||||||
|
|
||||||
use crate::check::intrinsic::intrinsic_operation_unsafety;
|
use crate::check::intrinsic::intrinsic_operation_unsafety;
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
|
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
|
||||||
|
|
||||||
pub(crate) mod dump;
|
pub(crate) mod dump;
|
||||||
mod generics_of;
|
mod generics_of;
|
||||||
@ -88,6 +88,7 @@ pub fn provide(providers: &mut Providers) {
|
|||||||
coroutine_for_closure,
|
coroutine_for_closure,
|
||||||
opaque_ty_origin,
|
opaque_ty_origin,
|
||||||
rendered_precise_capturing_args,
|
rendered_precise_capturing_args,
|
||||||
|
const_param_default,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1790,3 +1791,23 @@ fn rendered_precise_capturing_args<'tcx>(
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn const_param_default<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||||
|
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||||
|
hir::Node::GenericParam(hir::GenericParam {
|
||||||
|
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||||
|
..
|
||||||
|
}) => ct,
|
||||||
|
_ => span_bug!(
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
"`const_param_default` expected a generic parameter with a constant"
|
||||||
|
),
|
||||||
|
};
|
||||||
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
|
// FIXME(const_generics): investigate which places do and don't need const ty feeding
|
||||||
|
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
|
||||||
|
ty::EarlyBinder::bind(ct)
|
||||||
|
}
|
||||||
|
@ -223,11 +223,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
trace!(?predicates);
|
trace!(?predicates);
|
||||||
}
|
}
|
||||||
hir::GenericParamKind::Const { .. } => {
|
hir::GenericParamKind::Const { .. } => {
|
||||||
|
let param_def_id = param.def_id.to_def_id();
|
||||||
let ct_ty = tcx
|
let ct_ty = tcx
|
||||||
.type_of(param.def_id.to_def_id())
|
.type_of(param_def_id)
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameters cannot be generic");
|
.expect("const parameters cannot be generic");
|
||||||
let ct = icx.lowerer().lower_const_param(param.hir_id);
|
let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
|
||||||
predicates
|
predicates
|
||||||
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ use tracing::{debug, instrument};
|
|||||||
use super::errors::GenericsArgsErrExtend;
|
use super::errors::GenericsArgsErrExtend;
|
||||||
use crate::bounds::Bounds;
|
use crate::bounds::Bounds;
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer, PredicateFilter, RegionInferReason};
|
use crate::hir_ty_lowering::{
|
||||||
|
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
|
||||||
|
};
|
||||||
|
|
||||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
/// Add a `Sized` bound to the `bounds` if appropriate.
|
/// Add a `Sized` bound to the `bounds` if appropriate.
|
||||||
@ -346,9 +348,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
hir::AssocItemConstraintKind::Equality { term } => {
|
hir::AssocItemConstraintKind::Equality { term } => {
|
||||||
let term = match term {
|
let term = match term {
|
||||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||||
hir::Term::Const(ct) => {
|
hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
|
||||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find any late-bound regions declared in `ty` that are not
|
// Find any late-bound regions declared in `ty` that are not
|
||||||
|
@ -115,17 +115,22 @@ fn generic_arg_mismatch_err(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
|
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
|
||||||
// FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
|
if let hir::ConstArgKind::Path(qpath) = cnst.kind
|
||||||
// this should match against that instead of ::Anon
|
&& let rustc_hir::QPath::Resolved(_, path) = qpath
|
||||||
if let hir::ConstArgKind::Anon(anon) = cnst.kind
|
&& let Res::Def(DefKind::Fn { .. }, id) = path.res
|
||||||
|
{
|
||||||
|
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
||||||
|
err.help("function item types cannot be named directly");
|
||||||
|
} else if let hir::ConstArgKind::Anon(anon) = cnst.kind
|
||||||
&& let body = tcx.hir().body(anon.body)
|
&& let body = tcx.hir().body(anon.body)
|
||||||
&& let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
|
&& let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
|
||||||
body.value.kind
|
body.value.kind
|
||||||
|
&& let Res::Def(DefKind::Fn { .. }, id) = path.res
|
||||||
{
|
{
|
||||||
if let Res::Def(DefKind::Fn { .. }, id) = path.res {
|
// FIXME(min_generic_const_args): this branch is dead once new const path lowering
|
||||||
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
// (for single-segment paths) is no longer gated
|
||||||
err.help("function item types cannot be named directly");
|
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
||||||
}
|
err.help("function item types cannot be named directly");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -30,7 +30,7 @@ use rustc_errors::{
|
|||||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
|
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::{GenericArg, GenericArgs, HirId};
|
use rustc_hir::{GenericArg, GenericArgs, HirId};
|
||||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
@ -217,6 +217,23 @@ impl AssocItemQSelf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
||||||
|
/// through const generics need to have their type "fed" to them
|
||||||
|
/// using the query system.
|
||||||
|
///
|
||||||
|
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
|
||||||
|
/// desired behavior.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum FeedConstTy {
|
||||||
|
/// Feed the type.
|
||||||
|
///
|
||||||
|
/// The `DefId` belongs to the const param that we are supplying
|
||||||
|
/// this (anon) const arg to.
|
||||||
|
Param(DefId),
|
||||||
|
/// Don't feed the type.
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
/// New-typed boolean indicating whether explicit late-bound lifetimes
|
/// New-typed boolean indicating whether explicit late-bound lifetimes
|
||||||
/// are present in a set of generic arguments.
|
/// are present in a set of generic arguments.
|
||||||
///
|
///
|
||||||
@ -500,8 +517,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
handle_ty_args(has_default, &inf.to_ty())
|
handle_ty_args(has_default, &inf.to_ty())
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
|
self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||||
self.lowerer.ct_infer(Some(param), inf.span).into()
|
self.lowerer.ct_infer(Some(param), inf.span).into()
|
||||||
@ -979,8 +995,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
let term: ty::Term<'_> = match term {
|
let term: ty::Term<'_> = match term {
|
||||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||||
hir::Term::Const(ct) => {
|
hir::Term::Const(ct) => {
|
||||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
|
self.lower_const_arg(ct, FeedConstTy::No).into()
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// FIXME(#97583): This isn't syntactically well-formed!
|
// FIXME(#97583): This isn't syntactically well-formed!
|
||||||
@ -2025,23 +2040,138 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
///
|
///
|
||||||
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
|
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
|
||||||
/// and late-bound ones to [`ty::ConstKind::Bound`].
|
/// and late-bound ones to [`ty::ConstKind::Bound`].
|
||||||
pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'tcx> {
|
pub(crate) fn lower_const_param(&self, param_def_id: DefId, path_hir_id: HirId) -> Const<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
match tcx.named_bound_var(hir_id) {
|
|
||||||
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
match tcx.named_bound_var(path_hir_id) {
|
||||||
|
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||||
// Find the name and index of the const parameter by indexing the generics of
|
// Find the name and index of the const parameter by indexing the generics of
|
||||||
// the parent item and construct a `ParamConst`.
|
// the parent item and construct a `ParamConst`.
|
||||||
let item_def_id = tcx.local_parent(def_id);
|
let item_def_id = tcx.parent(param_def_id);
|
||||||
let generics = tcx.generics_of(item_def_id);
|
let generics = tcx.generics_of(item_def_id);
|
||||||
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
|
let index = generics.param_def_id_to_index[¶m_def_id];
|
||||||
let name = tcx.item_name(def_id.to_def_id());
|
let name = tcx.item_name(param_def_id);
|
||||||
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
||||||
}
|
}
|
||||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||||
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
||||||
}
|
}
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Const).
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
pub fn lower_const_arg(
|
||||||
|
&self,
|
||||||
|
const_arg: &hir::ConstArg<'tcx>,
|
||||||
|
feed: FeedConstTy,
|
||||||
|
) -> Const<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
if let FeedConstTy::Param(param_def_id) = feed
|
||||||
|
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||||
|
{
|
||||||
|
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
let hir_id = const_arg.hir_id;
|
||||||
|
match const_arg.kind {
|
||||||
|
hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
|
||||||
|
debug!(?maybe_qself, ?path);
|
||||||
|
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
||||||
|
self.lower_const_path_resolved(opt_self_ty, path, hir_id)
|
||||||
|
}
|
||||||
|
hir::ConstArgKind::Path(qpath) => ty::Const::new_error_with_message(
|
||||||
|
tcx,
|
||||||
|
qpath.span(),
|
||||||
|
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
|
||||||
|
),
|
||||||
|
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_const_path_resolved(
|
||||||
|
&self,
|
||||||
|
opt_self_ty: Option<Ty<'tcx>>,
|
||||||
|
path: &hir::Path<'tcx>,
|
||||||
|
hir_id: HirId,
|
||||||
|
) -> Const<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
let span = path.span;
|
||||||
|
match path.res {
|
||||||
|
Res::Def(DefKind::ConstParam, def_id) => {
|
||||||
|
assert_eq!(opt_self_ty, None);
|
||||||
|
let _ = self.prohibit_generic_args(
|
||||||
|
path.segments.iter(),
|
||||||
|
GenericsArgsErrExtend::Param(def_id),
|
||||||
|
);
|
||||||
|
self.lower_const_param(def_id, hir_id)
|
||||||
|
}
|
||||||
|
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
|
||||||
|
assert_eq!(opt_self_ty, None);
|
||||||
|
let _ = self.prohibit_generic_args(
|
||||||
|
path.segments.split_last().unwrap().1.iter(),
|
||||||
|
GenericsArgsErrExtend::None,
|
||||||
|
);
|
||||||
|
let args = self.lower_generic_args_of_path_segment(
|
||||||
|
span,
|
||||||
|
did,
|
||||||
|
path.segments.last().unwrap(),
|
||||||
|
);
|
||||||
|
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
|
||||||
|
}
|
||||||
|
Res::Def(DefKind::Static { .. }, _) => {
|
||||||
|
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
|
||||||
|
}
|
||||||
|
// FIXME(const_generics): create real const to allow fn items as const paths
|
||||||
|
Res::Def(DefKind::Fn | DefKind::AssocFn, _) => ty::Const::new_error_with_message(
|
||||||
|
tcx,
|
||||||
|
span,
|
||||||
|
"fn items cannot be used as const args",
|
||||||
|
),
|
||||||
|
|
||||||
|
// Exhaustive match to be clear about what exactly we're considering to be
|
||||||
|
// an invalid Res for a const path.
|
||||||
|
Res::Def(
|
||||||
|
DefKind::Mod
|
||||||
|
| DefKind::Enum
|
||||||
|
| DefKind::Variant
|
||||||
|
| DefKind::Ctor(CtorOf::Variant, CtorKind::Fn)
|
||||||
|
| DefKind::Struct
|
||||||
|
| DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
|
||||||
|
| DefKind::OpaqueTy
|
||||||
|
| DefKind::TyAlias
|
||||||
|
| DefKind::TraitAlias
|
||||||
|
| DefKind::AssocTy
|
||||||
|
| DefKind::Union
|
||||||
|
| DefKind::Trait
|
||||||
|
| DefKind::ForeignTy
|
||||||
|
| DefKind::AssocConst
|
||||||
|
| DefKind::TyParam
|
||||||
|
| DefKind::Macro(_)
|
||||||
|
| DefKind::LifetimeParam
|
||||||
|
| DefKind::Use
|
||||||
|
| DefKind::ForeignMod
|
||||||
|
| DefKind::AnonConst
|
||||||
|
| DefKind::InlineConst
|
||||||
|
| DefKind::Field
|
||||||
|
| DefKind::Impl { .. }
|
||||||
|
| DefKind::Closure
|
||||||
|
| DefKind::ExternCrate
|
||||||
|
| DefKind::GlobalAsm
|
||||||
|
| DefKind::SyntheticCoroutineBody,
|
||||||
|
_,
|
||||||
|
)
|
||||||
|
| Res::PrimTy(_)
|
||||||
|
| Res::SelfTyParam { .. }
|
||||||
|
| Res::SelfTyAlias { .. }
|
||||||
|
| Res::SelfCtor(_)
|
||||||
|
| Res::Local(_)
|
||||||
|
| Res::ToolMod
|
||||||
|
| Res::NonMacroAttr(_)
|
||||||
|
| Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2053,14 +2183,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lower a type from the HIR to our internal notion of a type given some extra data for diagnostics.
|
/// Lower a type from the HIR to our internal notion of a type.
|
||||||
///
|
|
||||||
/// Extra diagnostic data:
|
|
||||||
///
|
|
||||||
/// 1. `borrowed`: Whether trait object types are borrowed like in `&dyn Trait`.
|
|
||||||
/// Used to avoid emitting redundant errors.
|
|
||||||
/// 2. `in_path`: Whether the type appears inside of a path.
|
|
||||||
/// Used to provide correct diagnostics for bare trait object types.
|
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
@ -2189,7 +2312,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
let length = match length {
|
let length = match length {
|
||||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||||
hir::ArrayLen::Body(constant) => {
|
hir::ArrayLen::Body(constant) => {
|
||||||
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
|
self.lower_const_arg(constant, FeedConstTy::No)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2247,7 +2370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
.type_of(def_id)
|
.type_of(def_id)
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameter types cannot be generic");
|
.expect("const parameter types cannot be generic");
|
||||||
let ct = self.lower_const_param(expr.hir_id);
|
let ct = self.lower_const_param(def_id, expr.hir_id);
|
||||||
(ct, ty)
|
(ct, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,12 +97,14 @@ use rustc_hir::def::DefKind;
|
|||||||
use rustc_middle::middle;
|
use rustc_middle::middle;
|
||||||
use rustc_middle::mir::interpret::GlobalId;
|
use rustc_middle::mir::interpret::GlobalId;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
||||||
|
use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
|
||||||
|
|
||||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
fn require_c_abi_if_c_variadic(
|
fn require_c_abi_if_c_variadic(
|
||||||
@ -226,3 +228,14 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
|||||||
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
|
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
|
||||||
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
|
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is for rustdoc.
|
||||||
|
// FIXME(const_generics): having special methods for rustdoc in `rustc_hir_analysis` is cursed
|
||||||
|
pub fn lower_const_arg_for_rustdoc<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
hir_ct: &hir::ConstArg<'tcx>,
|
||||||
|
feed: FeedConstTy,
|
||||||
|
) -> Const<'tcx> {
|
||||||
|
let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id);
|
||||||
|
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
|
||||||
|
}
|
||||||
|
@ -14,8 +14,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
|
|||||||
check_generic_arg_count_for_call, lower_generic_args,
|
check_generic_arg_count_for_call, lower_generic_args,
|
||||||
};
|
};
|
||||||
use rustc_hir_analysis::hir_ty_lowering::{
|
use rustc_hir_analysis::hir_ty_lowering::{
|
||||||
ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer,
|
ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult,
|
||||||
GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
|
GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
|
||||||
};
|
};
|
||||||
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
|
||||||
@ -491,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||||
hir::ArrayLen::Body(const_arg) => {
|
hir::ArrayLen::Body(const_arg) => {
|
||||||
let span = const_arg.span();
|
let span = const_arg.span();
|
||||||
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
|
let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
|
||||||
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
||||||
self.normalize(span, c)
|
self.normalize(span, c)
|
||||||
}
|
}
|
||||||
@ -503,8 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||||
param_def_id: DefId,
|
param_def_id: DefId,
|
||||||
) -> ty::Const<'tcx> {
|
) -> ty::Const<'tcx> {
|
||||||
let ct =
|
let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
|
||||||
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
|
|
||||||
self.register_wf_obligation(
|
self.register_wf_obligation(
|
||||||
ct.into(),
|
ct.into(),
|
||||||
self.tcx.hir().span(const_arg.hir_id),
|
self.tcx.hir().span(const_arg.hir_id),
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
|
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::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::{self as hir, HirId};
|
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 tracing::{debug, instrument};
|
||||||
|
|
||||||
use crate::middle::resolve_bound_vars as rbv;
|
|
||||||
use crate::mir::interpret::{LitToConstInput, Scalar};
|
use crate::mir::interpret::{LitToConstInput, Scalar};
|
||||||
use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
|
use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
span: S,
|
span: S,
|
||||||
msg: &'static str,
|
msg: impl Into<Cow<'static, str>>,
|
||||||
) -> Const<'tcx> {
|
) -> Const<'tcx> {
|
||||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||||
Const::new_error(tcx, reported)
|
Const::new_error(tcx, reported)
|
||||||
@ -183,46 +184,8 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
|
||||||
/// through const generics need to have their type "fed" to them
|
|
||||||
/// using the query system.
|
|
||||||
///
|
|
||||||
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
|
|
||||||
/// desired behavior.
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum FeedConstTy {
|
|
||||||
/// Feed the type.
|
|
||||||
///
|
|
||||||
/// The `DefId` belongs to the const param that we are supplying
|
|
||||||
/// this (anon) const arg to.
|
|
||||||
Param(DefId),
|
|
||||||
/// Don't feed the type.
|
|
||||||
No,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
|
// FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
|
||||||
pub fn from_const_arg(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
|
||||||
feed: FeedConstTy,
|
|
||||||
) -> Self {
|
|
||||||
if let FeedConstTy::Param(param_def_id) = feed
|
|
||||||
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
|
||||||
{
|
|
||||||
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
match const_arg.kind {
|
|
||||||
hir::ConstArgKind::Path(qpath) => {
|
|
||||||
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
|
|
||||||
Self::from_param(tcx, qpath, const_arg.hir_id)
|
|
||||||
}
|
|
||||||
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||||
/// becomes `Unevaluated`.
|
/// becomes `Unevaluated`.
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
@ -240,7 +203,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
|
|
||||||
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
||||||
|
|
||||||
match Self::try_from_lit_or_param(tcx, ty, expr) {
|
match Self::try_from_lit(tcx, ty, expr) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
|
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
|
||||||
def: def.to_def_id(),
|
def: def.to_def_id(),
|
||||||
@ -249,40 +212,8 @@ impl<'tcx> Const<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lower a const param to a [`Const`].
|
|
||||||
///
|
|
||||||
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
|
|
||||||
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
|
|
||||||
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
|
|
||||||
qpath
|
|
||||||
else {
|
|
||||||
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
|
|
||||||
};
|
|
||||||
|
|
||||||
match tcx.named_bound_var(hir_id) {
|
|
||||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
|
||||||
// Find the name and index of the const parameter by indexing the generics of
|
|
||||||
// the parent item and construct a `ParamConst`.
|
|
||||||
let item_def_id = tcx.parent(def_id);
|
|
||||||
let generics = tcx.generics_of(item_def_id);
|
|
||||||
let index = generics.param_def_id_to_index[&def_id];
|
|
||||||
let name = tcx.item_name(def_id);
|
|
||||||
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
|
||||||
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
|
||||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn try_from_lit_or_param(
|
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
|
||||||
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
|
// 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.
|
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||||
let expr = match &expr.kind {
|
let expr = match &expr.kind {
|
||||||
@ -321,7 +252,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
tcx.dcx().span_delayed_bug(
|
tcx.dcx().span_delayed_bug(
|
||||||
expr.span,
|
expr.span,
|
||||||
format!("Const::from_anon_const: couldn't lit_to_const {e:?}"),
|
format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,20 +345,3 @@ impl<'tcx> Const<'tcx> {
|
|||||||
matches!(self.kind(), ty::ConstKind::Infer(_))
|
matches!(self.kind(), ty::ConstKind::Infer(_))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_param_default<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
|
||||||
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
|
||||||
hir::Node::GenericParam(hir::GenericParam {
|
|
||||||
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
|
||||||
..
|
|
||||||
}) => ct,
|
|
||||||
_ => span_bug!(
|
|
||||||
tcx.def_span(def_id),
|
|
||||||
"`const_param_default` expected a generic parameter with a constant"
|
|
||||||
),
|
|
||||||
};
|
|
||||||
ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
|
|
||||||
}
|
|
||||||
|
@ -30,7 +30,7 @@ use rustc_errors::{
|
|||||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::{CtorKind, DefKind};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_hir::definitions::Definitions;
|
use rustc_hir::definitions::Definitions;
|
||||||
use rustc_hir::intravisit::Visitor;
|
use rustc_hir::intravisit::Visitor;
|
||||||
@ -230,7 +230,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||||||
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
|
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
|
||||||
DefKind::TyAlias => ty::AliasTermKind::WeakTy,
|
DefKind::TyAlias => ty::AliasTermKind::WeakTy,
|
||||||
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
|
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
|
||||||
DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
|
DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => {
|
||||||
|
ty::AliasTermKind::UnevaluatedConst
|
||||||
|
}
|
||||||
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
|
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ pub use self::closure::{
|
|||||||
place_to_string_for_capture,
|
place_to_string_for_capture,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
|
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
||||||
};
|
};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||||
@ -2249,7 +2249,6 @@ pub fn provide(providers: &mut Providers) {
|
|||||||
incoherent_impls: trait_def::incoherent_impls_provider,
|
incoherent_impls: trait_def::incoherent_impls_provider,
|
||||||
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
|
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
|
||||||
traits: trait_def::traits_provider,
|
traits: trait_def::traits_provider,
|
||||||
const_param_default: consts::const_param_default,
|
|
||||||
vtable_allocation: vtable::vtable_allocation_provider,
|
vtable_allocation: vtable::vtable_allocation_provider,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
|
@ -1226,6 +1226,7 @@ symbols! {
|
|||||||
min_const_generics,
|
min_const_generics,
|
||||||
min_const_unsafe_fn,
|
min_const_unsafe_fn,
|
||||||
min_exhaustive_patterns,
|
min_exhaustive_patterns,
|
||||||
|
min_generic_const_args,
|
||||||
min_specialization,
|
min_specialization,
|
||||||
min_type_alias_impl_trait,
|
min_type_alias_impl_trait,
|
||||||
minnumf128,
|
minnumf128,
|
||||||
|
@ -42,7 +42,8 @@ use rustc_errors::{FatalError, struct_span_code_err};
|
|||||||
use rustc_hir::PredicateOrigin;
|
use rustc_hir::PredicateOrigin;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_hir_analysis::lower_ty;
|
use rustc_hir_analysis::hir_ty_lowering::FeedConstTy;
|
||||||
|
use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
|
||||||
use rustc_middle::metadata::Reexport;
|
use rustc_middle::metadata::Reexport;
|
||||||
use rustc_middle::middle::resolve_bound_vars as rbv;
|
use rustc_middle::middle::resolve_bound_vars as rbv;
|
||||||
use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||||
@ -435,10 +436,10 @@ fn clean_middle_term<'tcx>(
|
|||||||
fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
|
fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
|
||||||
match term {
|
match term {
|
||||||
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
|
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
|
||||||
hir::Term::Const(c) => Term::Constant(clean_middle_const(
|
hir::Term::Const(c) => {
|
||||||
ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)),
|
let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::No);
|
||||||
cx,
|
Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx))
|
||||||
)),
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +626,7 @@ fn clean_generic_param<'tcx>(
|
|||||||
(param.name.ident().name, GenericParamDefKind::Const {
|
(param.name.ident().name, GenericParamDefKind::Const {
|
||||||
ty: Box::new(clean_ty(ty, cx)),
|
ty: Box::new(clean_ty(ty, cx)),
|
||||||
default: default.map(|ct| {
|
default: default.map(|ct| {
|
||||||
Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string())
|
Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string())
|
||||||
}),
|
}),
|
||||||
synthetic,
|
synthetic,
|
||||||
})
|
})
|
||||||
@ -1813,7 +1814,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||||||
// `const_eval_poly` tries to first substitute generic parameters which
|
// `const_eval_poly` tries to first substitute generic parameters which
|
||||||
// results in an ICE while manually constructing the constant and using `eval`
|
// results in an ICE while manually constructing the constant and using `eval`
|
||||||
// does nothing for `ConstKind::Param`.
|
// does nothing for `ConstKind::Param`.
|
||||||
let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
|
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
|
||||||
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
|
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
|
||||||
const_arg.kind
|
const_arg.kind
|
||||||
{
|
{
|
||||||
|
17
tests/crashes/132985.rs
Normal file
17
tests/crashes/132985.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//@ known-bug: #132985
|
||||||
|
//@ aux-build:aux132985.rs
|
||||||
|
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(min_generic_const_args)]
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
|
||||||
|
extern crate aux132985;
|
||||||
|
use aux132985::Foo;
|
||||||
|
|
||||||
|
fn bar<const N: Foo>() {}
|
||||||
|
|
||||||
|
fn baz() {
|
||||||
|
bar::<{ Foo }>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
6
tests/crashes/auxiliary/aux132985.rs
Normal file
6
tests/crashes/auxiliary/aux132985.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#![feature(adt_const_params)]
|
||||||
|
|
||||||
|
use std::marker::ConstParamTy;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||||
|
pub struct Foo;
|
6
tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs
Normal file
6
tests/ui/const-generics/auxiliary/xcrate-const-ctor-a.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#![feature(adt_const_params)]
|
||||||
|
|
||||||
|
use std::marker::ConstParamTy;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, ConstParamTy)]
|
||||||
|
pub struct Foo;
|
7
tests/ui/const-generics/using-static-as-const-arg.rs
Normal file
7
tests/ui/const-generics/using-static-as-const-arg.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
pub static STATIC: u32 = 0;
|
||||||
|
pub struct Foo<const N: u32>;
|
||||||
|
pub const FOO: Foo<{STATIC}> = Foo;
|
||||||
|
|
||||||
|
fn main() {}
|
15
tests/ui/const-generics/xcrate-const-ctor-b.rs
Normal file
15
tests/ui/const-generics/xcrate-const-ctor-b.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//@ check-pass
|
||||||
|
//@ aux-build:xcrate-const-ctor-a.rs
|
||||||
|
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
|
||||||
|
extern crate xcrate_const_ctor_a;
|
||||||
|
use xcrate_const_ctor_a::Foo;
|
||||||
|
|
||||||
|
fn bar<const N: Foo>() {}
|
||||||
|
|
||||||
|
fn baz() {
|
||||||
|
bar::<{ Foo }>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,11 @@
|
|||||||
|
trait Trait {
|
||||||
|
const ASSOC: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(min_generic_const_args): implement support for this, behind the feature gate
|
||||||
|
fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
|
||||||
|
//~^ ERROR generic parameters may not be used in const operations
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,11 @@
|
|||||||
|
error: generic parameters may not be used in const operations
|
||||||
|
--> $DIR/feature-gate-min-generic-const-args.rs:6:29
|
||||||
|
|
|
||||||
|
LL | fn foo<T: Trait>() -> [u8; <T as Trait>::ASSOC] {
|
||||||
|
| ^ cannot perform const operation using `T`
|
||||||
|
|
|
||||||
|
= note: type parameters may not be used in const expressions
|
||||||
|
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user