add WellFormedConst predicate
This commit is contained in:
parent
cb2308de54
commit
81831e124e
@ -20,7 +20,8 @@ pub fn explicit_outlives_bounds<'tcx>(
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => None,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => None,
|
||||
ty::PredicateKind::RegionOutlives(ref data) => data
|
||||
.no_bound_vars()
|
||||
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
|
||||
|
@ -45,6 +45,8 @@ pub fn anonymize_predicate<'tcx>(
|
||||
}
|
||||
|
||||
ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::ConstEquate(c1, c2),
|
||||
|
||||
ty::PredicateKind::WellFormedConst(ct) => ty::PredicateKind::WellFormedConst(ct),
|
||||
};
|
||||
|
||||
if new != *kind { new.to_predicate(tcx) } else { pred }
|
||||
@ -204,6 +206,9 @@ impl Elaborator<'tcx> {
|
||||
// Currently, we do not elaborate const-equate
|
||||
// predicates.
|
||||
}
|
||||
ty::PredicateKind::WellFormedConst(..) => {
|
||||
// Currently, we do not elaborate WF predicates.
|
||||
}
|
||||
ty::PredicateKind::RegionOutlives(..) => {
|
||||
// Nothing to elaborate from `'a: 'b`.
|
||||
}
|
||||
|
@ -1218,6 +1218,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
|
||||
Projection(..) |
|
||||
// Ignore bounds that a user can't type
|
||||
WellFormed(..) |
|
||||
WellFormedConst(..) |
|
||||
ObjectSafe(..) |
|
||||
ClosureKind(..) |
|
||||
Subtype(..) |
|
||||
|
@ -1079,6 +1079,9 @@ pub enum PredicateKind<'tcx> {
|
||||
|
||||
/// Constants must be equal. The first component is the const that is expected.
|
||||
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
|
||||
|
||||
/// Constant must be well formed.
|
||||
WellFormedConst(&'tcx Const<'tcx>),
|
||||
}
|
||||
|
||||
/// The crate outlives map is computed during typeck and contains the
|
||||
@ -1195,6 +1198,9 @@ impl<'tcx> Predicate<'tcx> {
|
||||
PredicateKind::ConstEquate(c1, c2) => {
|
||||
PredicateKind::ConstEquate(c1.subst(tcx, substs), c2.subst(tcx, substs))
|
||||
}
|
||||
PredicateKind::WellFormedConst(c) => {
|
||||
PredicateKind::WellFormedConst(c.subst(tcx, substs))
|
||||
}
|
||||
};
|
||||
|
||||
if new != *kind { new.to_predicate(tcx) } else { self }
|
||||
@ -1386,7 +1392,8 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::TypeOutlives(..)
|
||||
| PredicateKind::ConstEvaluatable(..)
|
||||
| PredicateKind::ConstEquate(..) => None,
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::WellFormedConst(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1401,7 +1408,8 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::ConstEvaluatable(..)
|
||||
| PredicateKind::ConstEquate(..) => None,
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::WellFormedConst(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2054,6 +2054,9 @@ define_print_and_forward_display! {
|
||||
print(c2),
|
||||
write("`"))
|
||||
}
|
||||
ty::PredicateKind::WellFormedConst(c) => {
|
||||
p!(print(c), write(" well-formed"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,6 +247,7 @@ impl fmt::Debug for ty::PredicateKind<'tcx> {
|
||||
write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
|
||||
}
|
||||
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
|
||||
ty::PredicateKind::WellFormedConst(c) => write!(f, "WellFormedConst({:?})", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -507,6 +508,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
|
||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||
tcx.lift(&(c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
|
||||
}
|
||||
ty::PredicateKind::WellFormedConst(c) => {
|
||||
tcx.lift(&c).map(ty::PredicateKind::WellFormedConst)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
|
||||
| ty::PredicateKind::WellFormed(_)
|
||||
| ty::PredicateKind::Projection(_)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => continue,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => continue,
|
||||
ty::PredicateKind::ObjectSafe(_) => {
|
||||
bug!("object safe predicate on function: {:#?}", predicate)
|
||||
}
|
||||
|
@ -1277,7 +1277,8 @@ crate fn required_region_bounds(
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::RegionOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => None,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => None,
|
||||
ty::PredicateKind::TypeOutlives(predicate) => {
|
||||
// Search for a bound of the form `erased_self_ty
|
||||
// : 'a`, but be wary of something like `for<'a>
|
||||
|
@ -610,6 +610,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::WellFormedConst(ct) => {
|
||||
// Const WF predicates cannot themselves make
|
||||
// errors. They can only block due to
|
||||
// ambiguity; otherwise, they always
|
||||
// degenerate into other obligations
|
||||
// (which may fail).
|
||||
span_bug!(span, "const WF predicate not satisfied for {:?}", ct);
|
||||
}
|
||||
|
||||
ty::PredicateKind::ConstEvaluatable(..) => {
|
||||
// Errors for `ConstEvaluatable` predicates show up as
|
||||
// `SelectionError::ConstEvalFailure`,
|
||||
@ -1540,6 +1549,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
|
||||
}
|
||||
|
||||
ty::PredicateKind::WellFormedConst(ct) => {
|
||||
// Same hacky approach as above to avoid deluging user
|
||||
// with error messages.
|
||||
if ct.references_error() || self.tcx.sess.has_errors() {
|
||||
return;
|
||||
}
|
||||
self.need_type_info_err_const(body_id, span, ct, ErrorCode::E0282)
|
||||
}
|
||||
|
||||
ty::PredicateKind::Subtype(ref data) => {
|
||||
if data.references_error() || self.tcx.sess.has_errors() {
|
||||
// no need to overload user in such cases
|
||||
|
@ -476,6 +476,21 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::PredicateKind::WellFormedConst(constant) => match wf::const_obligations(
|
||||
self.selcx.infcx(),
|
||||
obligation.param_env,
|
||||
obligation.cause.body_id,
|
||||
constant,
|
||||
obligation.cause.span,
|
||||
) {
|
||||
Some(predicates) => ProcessResult::Changed(mk_pending(predicates)),
|
||||
None => {
|
||||
pending_obligation.stalled_on =
|
||||
vec![TyOrConstInferVar::maybe_from_const(constant).unwrap()];
|
||||
ProcessResult::Unchanged
|
||||
}
|
||||
},
|
||||
|
||||
&ty::PredicateKind::Subtype(subtype) => {
|
||||
match self.selcx.infcx().subtype_predicate(
|
||||
&obligation.cause,
|
||||
|
@ -283,7 +283,8 @@ fn predicates_reference_self(
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => None,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
@ -318,7 +319,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => false,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -450,6 +450,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
None => Ok(EvaluatedToAmbig),
|
||||
},
|
||||
|
||||
ty::PredicateKind::WellFormedConst(constant) => match wf::const_obligations(
|
||||
self.infcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.body_id,
|
||||
constant,
|
||||
obligation.cause.span,
|
||||
) {
|
||||
Some(mut obligations) => {
|
||||
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
|
||||
self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
|
||||
}
|
||||
None => Ok(EvaluatedToAmbig),
|
||||
},
|
||||
|
||||
ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::RegionOutlives(..) => {
|
||||
// We do not consider region relationships when evaluating trait matches.
|
||||
Ok(EvaluatedToOkModuloRegions)
|
||||
|
@ -128,15 +128,15 @@ pub fn predicate_obligations<'a, 'tcx>(
|
||||
let obligations = wf.nominal_obligations(def_id, substs);
|
||||
wf.out.extend(obligations);
|
||||
|
||||
for subst in substs.iter().copied() {
|
||||
for subst in substs.iter() {
|
||||
wf.compute(subst);
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||
wf.compute(c1.ty.into());
|
||||
wf.compute(c2.ty.into());
|
||||
&ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||
wf.compute(c1.into());
|
||||
wf.compute(c2.into());
|
||||
}
|
||||
ty::Predicate::WellFormedConst(constant) => {
|
||||
&ty::PredicateKind::WellFormedConst(constant) => {
|
||||
wf.compute(constant.into());
|
||||
}
|
||||
}
|
||||
@ -368,7 +368,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
let obligations = self.nominal_obligations(def_id, substs);
|
||||
self.out.extend(obligations);
|
||||
|
||||
let predicate = ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(self.tcx());
|
||||
let predicate = ty::PredicateKind::ConstEvaluatable(def_id, substs)
|
||||
.to_predicate(self.tcx());
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
self.out.push(traits::Obligation::new(
|
||||
cause,
|
||||
@ -389,11 +390,20 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
self.out.push(traits::Obligation::new(
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::PredicateKind::WellFormedConst(resolved_constant).to_predicate(self.tcx()),
|
||||
ty::PredicateKind::WellFormedConst(resolved_constant)
|
||||
.to_predicate(self.tcx()),
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
ty::ConstKind::Error
|
||||
| ty::ConstKind::Param(_)
|
||||
| ty::ConstKind::Bound(..)
|
||||
| ty::ConstKind::Placeholder(..) => {
|
||||
// These variants are trivially WF, so nothing to do here.
|
||||
}
|
||||
ty::ConstKind::Value(..) => {
|
||||
// FIXME: Enforce that values are structually-matchable.
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
|
||||
) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
|
||||
let clauses = self.environment.into_iter().filter_map(|clause| match clause {
|
||||
ChalkEnvironmentClause::Predicate(predicate) => {
|
||||
match &predicate.kind() {
|
||||
match predicate.kind() {
|
||||
ty::PredicateKind::Trait(predicate, _) => {
|
||||
let (predicate, binders, _named_regions) =
|
||||
collect_bound_vars(interner, interner.tcx, predicate);
|
||||
@ -126,7 +126,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => {
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => {
|
||||
bug!("unexpected predicate {}", predicate)
|
||||
}
|
||||
}
|
||||
@ -193,7 +194,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => {
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => {
|
||||
chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
|
||||
}
|
||||
}
|
||||
@ -460,7 +462,8 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", &self),
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => bug!("unexpected predicate {}", &self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,8 @@ fn compute_implied_outlives_bounds<'tcx>(
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => vec![],
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => vec![],
|
||||
|
||||
ty::PredicateKind::WellFormed(subty) => {
|
||||
wf_types.push(subty);
|
||||
|
@ -49,6 +49,7 @@ fn not_outlives_predicate(p: &ty::Predicate<'_>) -> bool {
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => true,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => true,
|
||||
}
|
||||
}
|
||||
|
@ -814,7 +814,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::TypeOutlives(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => None,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => None,
|
||||
});
|
||||
|
||||
self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
|
||||
|
@ -3353,28 +3353,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> {
|
||||
let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
|
||||
let c = ty::Const::from_anon_const(self.tcx, const_def_id);
|
||||
|
||||
// HACK(eddyb) emulate what a `WellFormedConst` obligation would do.
|
||||
// This code should be replaced with the proper WF handling ASAP.
|
||||
if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = c.val {
|
||||
assert!(promoted.is_none());
|
||||
|
||||
// HACK(eddyb) let's hope these are always empty.
|
||||
// let obligations = self.nominal_obligations(def_id, substs);
|
||||
// self.out.extend(obligations);
|
||||
|
||||
let cause = traits::ObligationCause::new(
|
||||
self.tcx.def_span(const_def_id.to_def_id()),
|
||||
self.body_id,
|
||||
traits::MiscObligation,
|
||||
);
|
||||
self.register_predicate(traits::Obligation::new(
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(self.tcx),
|
||||
));
|
||||
}
|
||||
|
||||
self.register_wf_const_obligation(
|
||||
c,
|
||||
self.tcx.hir().span(ast_c.hir_id),
|
||||
ObligationCauseCode::MiscObligation,
|
||||
);
|
||||
c
|
||||
}
|
||||
|
||||
@ -3424,11 +3407,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
));
|
||||
}
|
||||
|
||||
/// Registers obligations that all types appearing in `substs` are well-formed.
|
||||
/// Registers an obligation for checking later, during regionck, that the type `ty` must
|
||||
/// outlive the region `r`.
|
||||
pub fn register_wf_const_obligation(
|
||||
&self,
|
||||
ct: &'tcx ty::Const<'tcx>,
|
||||
span: Span,
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
// WF obligations never themselves fail, so no real need to give a detailed cause:
|
||||
let cause = traits::ObligationCause::new(span, self.body_id, code);
|
||||
self.register_predicate(traits::Obligation::new(
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::PredicateKind::WellFormedConst(ct).to_predicate(self.tcx),
|
||||
));
|
||||
}
|
||||
|
||||
/// Registers obligations that all `substs` are well-formed.
|
||||
pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr<'_>) {
|
||||
for ty in substs.types() {
|
||||
if !ty.references_error() {
|
||||
self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
|
||||
for subst in substs {
|
||||
match subst.unpack() {
|
||||
GenericArgKind::Lifetime(..) => {
|
||||
// Nothing to do for lifetimes.
|
||||
}
|
||||
GenericArgKind::Type(ty) => {
|
||||
if !ty.references_error() {
|
||||
self.register_wf_obligation(ty, expr.span, traits::MiscObligation);
|
||||
}
|
||||
}
|
||||
GenericArgKind::Const(ct) => {
|
||||
if !ct.references_error() {
|
||||
self.register_wf_const_obligation(ct, expr.span, traits::MiscObligation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3860,6 +3872,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::PredicateKind::RegionOutlives(..) => None,
|
||||
ty::PredicateKind::TypeOutlives(..) => None,
|
||||
ty::PredicateKind::WellFormed(..) => None,
|
||||
ty::PredicateKind::WellFormedConst(..) => None,
|
||||
ty::PredicateKind::ObjectSafe(..) => None,
|
||||
ty::PredicateKind::ConstEvaluatable(..) => None,
|
||||
ty::PredicateKind::ConstEquate(..) => None,
|
||||
|
@ -405,6 +405,7 @@ fn trait_predicate_kind<'tcx>(
|
||||
| ty::PredicateKind::ObjectSafe(_)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => None,
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => None,
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => (),
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,7 +491,8 @@ impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..) => panic!("not user writable"),
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::WellFormedConst(..) => panic!("not user writable"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,9 @@ error[E0282]: type annotations needed
|
||||
--> $DIR/cannot-infer-const-args.rs:9:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^ cannot infer type for fn item `fn() -> usize {foo::<{_: usize}>}`
|
||||
| ^^^
|
||||
|
|
||||
= note: unable to infer the value of a const parameter
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
|
||||
@ -7,6 +5,7 @@ struct Const<const N: usize>;
|
||||
|
||||
impl<const C: usize> Const<{C}> {
|
||||
fn successor() -> Const<{C + 1}> {
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
Const
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-61747.rs:3:12
|
||||
--> $DIR/issue-61747.rs:1:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
@ -7,5 +7,13 @@ LL | #![feature(const_generics)]
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
warning: 1 warning emitted
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-61747.rs:7:23
|
||||
|
|
||||
LL | fn successor() -> Const<{C + 1}> {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
// build-pass
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![feature(const_generics)]
|
||||
|
||||
pub struct Vector<T, const N: usize>([T; N]);
|
||||
|
||||
pub type TruncatedVector<T, const N: usize> = Vector<T, { N - 1 }>;
|
||||
@ -9,6 +8,7 @@ pub type TruncatedVector<T, const N: usize> = Vector<T, { N - 1 }>;
|
||||
impl<T, const N: usize> Vector<T, { N }> {
|
||||
/// Drop the last component and return the vector with one fewer dimension.
|
||||
pub fn trunc(self) -> (TruncatedVector<T, { N }>, T) {
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
10
src/test/ui/const-generics/issues/issue-62220.stderr
Normal file
10
src/test/ui/const-generics/issues/issue-62220.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-62220.rs:10:27
|
||||
|
|
||||
LL | pub fn trunc(self) -> (TruncatedVector<T, { N }>, T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(incomplete_features, dead_code, unconditional_recursion)]
|
||||
#![allow(dead_code, unconditional_recursion)]
|
||||
#![feature(const_generics)]
|
||||
#![feature(lazy_normalization_consts)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
|
||||
fn fact<const N: usize>() {
|
||||
fact::<{ N - 1 }>();
|
||||
|
@ -1,3 +1,12 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-66205.rs:2:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-66205.rs:6:12
|
||||
|
|
||||
@ -6,5 +15,5 @@ LL | fact::<{ N - 1 }>();
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
40
src/test/ui/const-generics/issues/issue-68977.rs
Normal file
40
src/test/ui/const-generics/issues/issue-68977.rs
Normal file
@ -0,0 +1,40 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
|
||||
struct PhantomU8<const X: u8>;
|
||||
|
||||
trait FxpStorage {
|
||||
type SInt; // Add arithmetic traits as needed.
|
||||
}
|
||||
|
||||
macro_rules! fxp_storage_impls {
|
||||
($($($n:literal)|+ => $sint:ty),* $(,)?) => {
|
||||
$($(impl FxpStorage for PhantomU8<$n> {
|
||||
type SInt = $sint;
|
||||
})*)*
|
||||
}
|
||||
}
|
||||
|
||||
fxp_storage_impls! {
|
||||
1 => i8,
|
||||
2 => i16,
|
||||
3 | 4 => i32,
|
||||
5 | 6 | 7 | 8 => i64,
|
||||
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 => i128,
|
||||
}
|
||||
|
||||
type FxpStorageHelper<const INT_BITS: u8, const FRAC_BITS: u8> =
|
||||
PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>;
|
||||
|
||||
struct Fxp<const INT_BITS: u8, const FRAC_BITS: u8>
|
||||
where
|
||||
FxpStorageHelper<INT_BITS, FRAC_BITS>: FxpStorage,
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
{
|
||||
storage: <FxpStorageHelper<INT_BITS, FRAC_BITS> as FxpStorage>::SInt,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Fxp::<1, 15> { storage: 0i16 };
|
||||
Fxp::<2, 15> { storage: 0i32 };
|
||||
}
|
19
src/test/ui/const-generics/issues/issue-68977.stderr
Normal file
19
src/test/ui/const-generics/issues/issue-68977.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68977.rs:1:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/issue-68977.rs:31:44
|
||||
|
|
||||
LL | FxpStorageHelper<INT_BITS, FRAC_BITS>: FxpStorage,
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
16
src/test/ui/const-generics/wf-misc.rs
Normal file
16
src/test/ui/const-generics/wf-misc.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete
|
||||
|
||||
pub fn arr_len<const N: usize>() {
|
||||
let _: [u8; N + 1];
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
}
|
||||
|
||||
struct Const<const N: usize>;
|
||||
|
||||
pub fn func_call<const N: usize>() {
|
||||
let _: Const::<{N + 1}>;
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
}
|
||||
|
||||
fn main() {}
|
27
src/test/ui/const-generics/wf-misc.stderr
Normal file
27
src/test/ui/const-generics/wf-misc.stderr
Normal file
@ -0,0 +1,27 @@
|
||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/wf-misc.rs:1:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/wf-misc.rs:5:12
|
||||
|
|
||||
LL | let _: [u8; N + 1];
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/wf-misc.rs:12:12
|
||||
|
|
||||
LL | let _: Const::<{N + 1}>;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
Loading…
Reference in New Issue
Block a user