Auto merge of #107965 - BoxyUwU:add_const_arg_has_type_predicate, r=compiler-errors
Add `Clause::ConstArgHasType` Currently the way that we check that a const arg has the correct type for the const param it is an argument for is by setting the expected type of `typeck` on the anon const of the argument to be the const param's type. In the future for a potential `min_generic_const_exprs` we will allow providing const arguments that do not have an associated anon const that can be typeck'd which will require us to actually check that the const argument has the correct type. While it would potentially be possible to just call `eq` when creating substs this would not work if we support generics of the form `const N: T, T` (the const parameters type referencing generics declared after itself). Additionally having `ConstArgHasType` will allow us to potentially make progress on removing the `ty` field of `Const` which may be desirable. Once progress has been made on this, `ConstArgHasType` will also be helpful in ensuring we do not make mistakes in trait/impl checking by declaring functions with the wrong const parameter types as the checks that the param env is compatible would catch it. (We have messed this up in the past, and with generic const parameter types these checks will get more complex) There is a [document](https://hackmd.io/wuCS6CJBQ9-fWbwaW7nQRw?view) about the types of const generics that may provide some general information on this subject --- This PR shouldn't have any impact on whether code compiles or not on stable, it primarily exists to make progress on unstable const generics features that are desirable.
This commit is contained in:
commit
f4f5fc3e5c
@ -1328,7 +1328,7 @@ fn conv_object_ty_poly_trait_ref(
|
||||
ty::Clause::TypeOutlives(_) => {
|
||||
// Do nothing, we deal with regions separately
|
||||
}
|
||||
ty::Clause::RegionOutlives(_) => bug!(),
|
||||
ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(),
|
||||
},
|
||||
ty::PredicateKind::WellFormed(_)
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
|
@ -9,8 +9,8 @@
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::ToPredicate;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericPredicates, ToPredicate};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
@ -151,7 +151,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
||||
trace!(?generics);
|
||||
|
||||
// Collect the predicates that were written inline by the user on each
|
||||
// type parameter (e.g., `<T: Foo>`).
|
||||
// type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
|
||||
// for each const parameter.
|
||||
for param in ast_generics.params {
|
||||
match param.kind {
|
||||
// We already dealt with early bound lifetimes above.
|
||||
@ -175,7 +176,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
||||
trace!(?predicates);
|
||||
}
|
||||
GenericParamKind::Const { .. } => {
|
||||
// Bounds on const parameters are currently not possible.
|
||||
let name = param.name.ident().name;
|
||||
let param_const = ty::ParamConst::new(index, name);
|
||||
|
||||
let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity();
|
||||
|
||||
let ct = tcx.mk_const(param_const, ct_ty);
|
||||
|
||||
let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
|
||||
ty::Clause::ConstArgHasType(ct, ct_ty),
|
||||
))
|
||||
.to_predicate(tcx);
|
||||
predicates.insert((predicate, param.span));
|
||||
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
@ -439,7 +452,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||
let parent_def_id = tcx.hir().get_parent_item(hir_id);
|
||||
|
||||
if tcx.hir().opt_const_param_default_param_def_id(hir_id).is_some() {
|
||||
if let Some(defaulted_param_def_id) =
|
||||
tcx.hir().opt_const_param_default_param_def_id(hir_id)
|
||||
{
|
||||
// In `generics_of` we set the generics' parent to be our parent's parent which means that
|
||||
// we lose out on the predicates of our actual parent if we dont return those predicates here.
|
||||
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
|
||||
@ -452,7 +467,39 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||
//
|
||||
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
|
||||
// and we would be calling `explicit_predicates_of(Foo)` here
|
||||
return tcx.explicit_predicates_of(parent_def_id);
|
||||
let parent_preds = tcx.explicit_predicates_of(parent_def_id);
|
||||
|
||||
// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
|
||||
// will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
|
||||
// to #106994 is implemented.
|
||||
let filtered_predicates = parent_preds
|
||||
.predicates
|
||||
.into_iter()
|
||||
.filter(|(pred, _)| {
|
||||
if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) =
|
||||
pred.kind().skip_binder()
|
||||
{
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Param(param_const) => {
|
||||
let defaulted_param_idx = tcx
|
||||
.generics_of(parent_def_id)
|
||||
.param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
|
||||
param_const.index < defaulted_param_idx
|
||||
}
|
||||
_ => bug!(
|
||||
"`ConstArgHasType` in `predicates_of`\
|
||||
that isn't a `Param` const"
|
||||
),
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.cloned();
|
||||
return GenericPredicates {
|
||||
parent: parent_preds.parent,
|
||||
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
|
||||
};
|
||||
}
|
||||
|
||||
let parent_def_kind = tcx.def_kind(parent_def_id);
|
||||
|
@ -496,6 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
|
||||
// FIXME(min_specialization), FIXME(const_generics):
|
||||
// It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
|
||||
// about the actual rules that would be sound. Can't just always error here because otherwise
|
||||
// std/core doesn't even compile as they have `const N: usize` in some specializing impls.
|
||||
//
|
||||
// While we do not support constructs like `<T, const N: T>` there is probably no risk of
|
||||
// soundness bugs, but when we support generic const parameter types this will need to be
|
||||
// revisited.
|
||||
}
|
||||
_ => {
|
||||
tcx.sess
|
||||
.struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
|
||||
@ -517,6 +527,7 @@ fn trait_predicate_kind<'tcx>(
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
|
||||
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(_))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::WellFormed(_)
|
||||
| ty::PredicateKind::Subtype(_)
|
||||
|
@ -54,6 +54,7 @@ pub(crate) fn explicit_predicates_of(
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::WellFormed(..)
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
|
@ -663,6 +663,7 @@ pub(in super::super) fn obligations_for_self_ty<'b>(
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
|
||||
|
@ -826,6 +826,7 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
|
||||
|
@ -21,6 +21,7 @@ pub fn explicit_outlives_bounds<'tcx>(
|
||||
.filter_map(move |kind| match kind {
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
|
@ -297,6 +297,9 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
|
||||
ty::PredicateKind::AliasEq(..) => {
|
||||
// No
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
|
||||
// Nothing to elaborate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1595,6 +1595,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||
Clause(Clause::TypeOutlives(..)) |
|
||||
Clause(Clause::RegionOutlives(..)) => "lifetime",
|
||||
|
||||
// `ConstArgHasType` is never global as `ct` is always a param
|
||||
Clause(Clause::ConstArgHasType(..)) |
|
||||
// Ignore projections, as they can only be global
|
||||
// if the trait bound is global
|
||||
Clause(Clause::Projection(..)) |
|
||||
|
@ -251,6 +251,10 @@ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
|
||||
self.add_ty(ty);
|
||||
self.add_region(region);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
self.add_const(ct);
|
||||
self.add_ty(ty);
|
||||
}
|
||||
ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
|
||||
self.add_ty(a);
|
||||
self.add_ty(b);
|
||||
|
@ -552,6 +552,7 @@ pub fn allow_normalization(self) -> bool {
|
||||
| PredicateKind::Clause(Clause::RegionOutlives(_))
|
||||
| PredicateKind::Clause(Clause::TypeOutlives(_))
|
||||
| PredicateKind::Clause(Clause::Projection(_))
|
||||
| PredicateKind::Clause(Clause::ConstArgHasType(..))
|
||||
| PredicateKind::AliasEq(..)
|
||||
| PredicateKind::ObjectSafe(_)
|
||||
| PredicateKind::ClosureKind(_, _, _)
|
||||
@ -590,6 +591,10 @@ pub enum Clause<'tcx> {
|
||||
/// `where <T as TraitRef>::Name == X`, approximately.
|
||||
/// See the `ProjectionPredicate` struct for details.
|
||||
Projection(ProjectionPredicate<'tcx>),
|
||||
|
||||
/// Ensures that a const generic argument to a parameter `const N: u8`
|
||||
/// is of type `u8`.
|
||||
ConstArgHasType(Const<'tcx>, Ty<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
@ -1193,6 +1198,7 @@ pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
|
||||
PredicateKind::Clause(Clause::Projection(..))
|
||||
| PredicateKind::Clause(Clause::ConstArgHasType(..))
|
||||
| PredicateKind::AliasEq(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
| PredicateKind::Coerce(..)
|
||||
@ -1213,6 +1219,7 @@ pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
|
||||
PredicateKind::Clause(Clause::Trait(..))
|
||||
| PredicateKind::Clause(Clause::ConstArgHasType(..))
|
||||
| PredicateKind::AliasEq(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
| PredicateKind::Coerce(..)
|
||||
@ -1233,6 +1240,7 @@ pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
|
||||
PredicateKind::Clause(Clause::Trait(..))
|
||||
| PredicateKind::Clause(Clause::ConstArgHasType(..))
|
||||
| PredicateKind::Clause(Clause::Projection(..))
|
||||
| PredicateKind::AliasEq(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
|
@ -2822,15 +2822,18 @@ pub struct PrintClosureAsImpl<'tcx> {
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)),
|
||||
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)),
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)),
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
p!("the constant `", print(ct), "` has type `", print(ty), "`")
|
||||
},
|
||||
ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
|
||||
ty::PredicateKind::ObjectSafe(trait_def_id) => {
|
||||
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
|
||||
}
|
||||
ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
|
||||
p!("the closure `",
|
||||
ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => p!(
|
||||
"the closure `",
|
||||
print_value_path(closure_def_id, &[]),
|
||||
write("` implements the trait `{}`", kind))
|
||||
}
|
||||
write("` implements the trait `{}`", kind)
|
||||
),
|
||||
ty::PredicateKind::ConstEvaluatable(ct) => {
|
||||
p!("the constant `", print(ct), "` can be evaluated")
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ty::Clause::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
|
||||
ty::Clause::Trait(ref a) => a.fmt(f),
|
||||
ty::Clause::RegionOutlives(ref pair) => pair.fmt(f),
|
||||
ty::Clause::TypeOutlives(ref pair) => pair.fmt(f),
|
||||
|
@ -159,9 +159,21 @@ fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::
|
||||
_region,
|
||||
))) => ty.visit_with(self),
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => ControlFlow::Continue(()),
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
ct.visit_with(self)?;
|
||||
ty.visit_with(self)
|
||||
}
|
||||
ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
|
||||
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
|
||||
_ => bug!("unexpected predicate: {:?}", predicate),
|
||||
|
||||
ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(_, _, _)
|
||||
| ty::PredicateKind::Subtype(_)
|
||||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::ConstEquate(_, _)
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(_)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::infer::canonical::Certainty as OldCertainty;
|
||||
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{
|
||||
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
|
||||
};
|
||||
@ -290,6 +290,9 @@ fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
|
||||
self.compute_region_outlives_goal(Goal { param_env, predicate })
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
|
||||
}
|
||||
ty::PredicateKind::Subtype(predicate) => {
|
||||
self.compute_subtype_goal(Goal { param_env, predicate })
|
||||
}
|
||||
@ -471,6 +474,16 @@ fn compute_alias_eq_goal(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn compute_const_arg_has_type_goal(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
|
||||
) -> QueryResult<'tcx> {
|
||||
let (ct, ty) = goal.predicate;
|
||||
let nested_goals = self.infcx.eq(goal.param_env, ct.ty(), ty)?;
|
||||
self.evaluate_all_and_make_canonical_response(nested_goals)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
|
@ -830,6 +830,7 @@ fn evaluate_nested_obligations(
|
||||
// and these don't correspond to adding any new bounds to
|
||||
// the `ParamEnv`.
|
||||
ty::PredicateKind::WellFormed(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
|
@ -1282,6 +1282,13 @@ fn report_selection_error(
|
||||
span,
|
||||
"AliasEq predicate should never be the predicate cause of a SelectionError"
|
||||
),
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
self.tcx.sess.struct_span_err(
|
||||
span,
|
||||
&format!("the constant `{}` is not of type `{}`", ct, ty),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,7 @@ fn process_obligation(
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
|
||||
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::WellFormed(_)
|
||||
| ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
@ -600,6 +601,19 @@ fn process_obligation(
|
||||
ty::PredicateKind::AliasEq(..) => {
|
||||
bug!("AliasEq is only used for new solver")
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
match self
|
||||
.selcx
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(ct.ty(), ty)
|
||||
{
|
||||
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
|
||||
Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
|
||||
SelectionError::Unimplemented,
|
||||
)),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -327,6 +327,10 @@ fn predicate_references_self<'tcx>(
|
||||
// possible alternatives.
|
||||
data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(_ct, ty)) => {
|
||||
has_self_ty(&ty.into()).then_some(sp)
|
||||
}
|
||||
|
||||
ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
|
||||
|
||||
ty::PredicateKind::WellFormed(..)
|
||||
@ -362,6 +366,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
|
||||
|
@ -993,6 +993,15 @@ fn evaluate_predicate_recursively<'o>(
|
||||
bug!("AliasEq is only used for new solver")
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) {
|
||||
Ok(inf_ok) => self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
inf_ok.into_obligations(),
|
||||
),
|
||||
Err(_) => Ok(EvaluatedToErr),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -163,6 +163,10 @@ pub fn predicate_obligations<'tcx>(
|
||||
ty::TermKind::Const(c) => c.into(),
|
||||
})
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
|
||||
wf.compute(ct.into());
|
||||
wf.compute(ty.into());
|
||||
}
|
||||
ty::PredicateKind::WellFormed(arg) => {
|
||||
wf.compute(arg);
|
||||
}
|
||||
@ -922,6 +926,7 @@ pub(crate) fn required_region_bounds<'tcx>(
|
||||
match obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::WellFormed(..)
|
||||
|
@ -117,6 +117,7 @@ fn lower_into(
|
||||
)),
|
||||
},
|
||||
ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
@ -212,6 +213,7 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GoalData<RustInte
|
||||
// We can defer this, but ultimately we'll want to express
|
||||
// some of these in terms of chalk operations.
|
||||
ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
@ -646,6 +648,7 @@ fn lower_into(
|
||||
Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
|
||||
}
|
||||
ty::PredicateKind::WellFormed(_ty) => None,
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
|
||||
|
||||
ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
@ -780,6 +783,7 @@ fn lower_into(
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_predicate)) => None,
|
||||
ty::PredicateKind::WellFormed(_ty) => None,
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
|
@ -99,6 +99,9 @@ fn compute_implied_outlives_bounds<'tcx>(
|
||||
};
|
||||
match pred {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
// FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
|
||||
// if we ever support that
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
|
@ -60,6 +60,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
|
||||
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) => false,
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::WellFormed(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
|
@ -320,6 +320,7 @@ pub(crate) fn clean_predicate<'tcx>(
|
||||
// FIXME(generic_const_exprs): should this do something?
|
||||
ty::PredicateKind::ConstEvaluatable(..) => None,
|
||||
ty::PredicateKind::WellFormed(..) => None,
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
|
||||
|
||||
ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
|
@ -30,7 +30,8 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
|
||||
ty::Clause::RegionOutlives(_)
|
||||
| ty::Clause::TypeOutlives(_)
|
||||
| ty::Clause::Projection(_)
|
||||
| ty::Clause::Trait(..),
|
||||
| ty::Clause::Trait(..)
|
||||
| ty::Clause::ConstArgHasType(..),
|
||||
)
|
||||
| ty::PredicateKind::WellFormed(_)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
|
@ -1,3 +1,11 @@
|
||||
error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants
|
||||
--> $DIR/nested-type.rs:15:5
|
||||
|
|
||||
LL | Foo::<17>::value()
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error: `[u8; {
|
||||
struct Foo<const N: usize>;
|
||||
|
||||
@ -24,5 +32,6 @@ LL | | }]>;
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
= help: more complex types are supported with `#![feature(adt_const_params)]`
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
|
@ -13,7 +13,7 @@ fn value() -> usize {
|
||||
}
|
||||
|
||||
Foo::<17>::value()
|
||||
//[full]~^ ERROR cannot call non-const fn
|
||||
//~^ ERROR cannot call non-const fn
|
||||
}]>;
|
||||
|
||||
fn main() {}
|
||||
|
Loading…
Reference in New Issue
Block a user