Introduce feature(generic_const_parameter_types)
This commit is contained in:
parent
60493b8973
commit
df5b279ca9
56 changed files with 419 additions and 154 deletions
|
@ -966,7 +966,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||
|
||||
if tcx.features().unsized_const_params() {
|
||||
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(
|
||||
hir_ty.span,
|
||||
|
@ -980,7 +980,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
Ok(())
|
||||
})
|
||||
} else if tcx.features().adt_const_params() {
|
||||
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
||||
enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(
|
||||
hir_ty.span,
|
||||
|
|
|
@ -1822,6 +1822,9 @@ fn const_param_default<'tcx>(
|
|||
),
|
||||
};
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id()));
|
||||
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
let ct = icx
|
||||
.lowerer()
|
||||
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
|
||||
ty::EarlyBinder::bind(ct)
|
||||
}
|
||||
|
|
|
@ -223,10 +223,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
}
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
let param_def_id = param.def_id.to_def_id();
|
||||
let ct_ty = tcx
|
||||
.type_of(param_def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameters cannot be generic");
|
||||
let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
|
||||
let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
|
||||
predicates
|
||||
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
||||
|
|
|
@ -273,7 +273,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
|||
|
||||
// We lower to an infer even when the feature gate is not enabled
|
||||
// as it is useful for diagnostics to be able to see a `ConstKind::Infer`
|
||||
args.push(ctx.provided_kind(param, arg));
|
||||
args.push(ctx.provided_kind(&args, param, arg));
|
||||
args_iter.next();
|
||||
params.next();
|
||||
}
|
||||
|
|
|
@ -232,12 +232,15 @@ impl AssocItemQSelf {
|
|||
/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
|
||||
/// desired behavior.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FeedConstTy {
|
||||
pub enum FeedConstTy<'a, 'tcx> {
|
||||
/// Feed the type.
|
||||
///
|
||||
/// The `DefId` belongs to the const param that we are supplying
|
||||
/// this (anon) const arg to.
|
||||
Param(DefId),
|
||||
///
|
||||
/// The list of generic args is used to instantiate the parameters
|
||||
/// used by the type of the const param specified by `DefId`.
|
||||
Param(DefId, &'a [ty::GenericArg<'tcx>]),
|
||||
/// Don't feed the type.
|
||||
No,
|
||||
}
|
||||
|
@ -298,6 +301,7 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
|
|||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'tcx>,
|
||||
) -> ty::GenericArg<'tcx>;
|
||||
|
@ -481,6 +485,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
fn provided_kind(
|
||||
&mut self,
|
||||
preceding_args: &[ty::GenericArg<'tcx>],
|
||||
param: &ty::GenericParamDef,
|
||||
arg: &GenericArg<'tcx>,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
|
@ -526,7 +531,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
|
||||
.lowerer
|
||||
// Ambig portions of `ConstArg` are handled in the match arm below
|
||||
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
|
||||
.lower_const_arg(
|
||||
ct.as_unambig_ct(),
|
||||
FeedConstTy::Param(param.def_id, preceding_args),
|
||||
)
|
||||
.into(),
|
||||
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
self.lowerer.ct_infer(Some(param), inf.span).into()
|
||||
|
@ -582,8 +590,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let ty = tcx
|
||||
.at(self.span)
|
||||
.type_of(param.def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameter types cannot be generic");
|
||||
.instantiate(tcx, preceding_args);
|
||||
if let Err(guar) = ty.error_reported() {
|
||||
return ty::Const::new_error(tcx, guar).into();
|
||||
}
|
||||
|
@ -2107,14 +2114,50 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
pub fn lower_const_arg(
|
||||
&self,
|
||||
const_arg: &hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy,
|
||||
feed: FeedConstTy<'_, 'tcx>,
|
||||
) -> Const<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let FeedConstTy::Param(param_def_id) = feed
|
||||
if let FeedConstTy::Param(param_def_id, args) = feed
|
||||
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||
{
|
||||
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||
let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
|
||||
|
||||
// We must error if the instantiated type has any inference variables as we will
|
||||
// use this type to feed the `type_of` and query results must not contain inference
|
||||
// variables otherwise we will ICE.
|
||||
//
|
||||
// We also error if the type contains any regions as effectively any region will wind
|
||||
// up as a region variable in mir borrowck. It would also be somewhat concerning if
|
||||
// hir typeck was using equality but mir borrowck wound up using subtyping as that could
|
||||
// result in a non-infer in hir typeck but a region variable in borrowck.
|
||||
//
|
||||
// FIXME(generic_const_parameter_types): Ideally we remove these errors one day when
|
||||
// we have the ability to intermix typeck of anon const const args with the parent
|
||||
// bodies typeck.
|
||||
if tcx.features().generic_const_parameter_types()
|
||||
&& (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions())
|
||||
{
|
||||
let e = tcx.dcx().span_err(
|
||||
const_arg.span(),
|
||||
"anonymous constants with lifetimes in their type are not yet supported",
|
||||
);
|
||||
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
|
||||
return ty::Const::new_error(tcx, e);
|
||||
}
|
||||
if anon_const_type.has_non_region_infer() {
|
||||
let e = tcx.dcx().span_err(
|
||||
const_arg.span(),
|
||||
"anonymous constants with inferred types are not yet supported",
|
||||
);
|
||||
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
|
||||
return ty::Const::new_error(tcx, e);
|
||||
}
|
||||
|
||||
tcx.feed_anon_const_type(
|
||||
anon.def_id,
|
||||
ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)),
|
||||
);
|
||||
}
|
||||
|
||||
let hir_id = const_arg.hir_id;
|
||||
|
@ -2230,10 +2273,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let expr = &tcx.hir_body(anon.body).value;
|
||||
debug!(?expr);
|
||||
|
||||
let ty = tcx
|
||||
.type_of(anon.def_id)
|
||||
.no_bound_vars()
|
||||
.expect("const parameter types cannot be generic");
|
||||
// FIXME(generic_const_parameter_types): We should use the proper generic args
|
||||
// here. It's only used as a hint for literals so doesn't matter too much to use the right
|
||||
// generic arguments, just weaker type inference.
|
||||
let ty = tcx.type_of(anon.def_id).instantiate_identity();
|
||||
|
||||
match self.try_lower_anon_const_lit(ty, expr) {
|
||||
Some(v) => v,
|
||||
|
|
|
@ -260,7 +260,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
|||
pub fn lower_const_arg_for_rustdoc<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hir_ct: &hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy,
|
||||
feed: FeedConstTy<'_, 'tcx>,
|
||||
) -> 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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue