Remove constness from TraitPredicate

This commit is contained in:
Deadbeef 2023-07-29 08:20:25 +00:00
parent 7637653b9f
commit 4fec845c3f
90 changed files with 446 additions and 390 deletions

View File

@ -90,11 +90,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
) {
self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait(
ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
},
ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive },
))),
locations,
category,

View File

@ -746,6 +746,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
// Attempting to call a trait method?
// FIXME(effects) do we need this?
if let Some(trait_id) = tcx.trait_of_item(callee) {
trace!("attempting to call a trait method");
if !self.tcx.features().const_trait_impl {
@ -761,7 +762,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args);
let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);

View File

@ -155,12 +155,12 @@ impl Qualif for NeedsNonConstDrop {
return false;
}
// FIXME(effects) constness
let obligation = Obligation::new(
cx.tcx,
ObligationCause::dummy_with_span(cx.body.span),
cx.param_env,
ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty])
.with_constness(ty::BoundConstness::ConstIfConst),
ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]),
);
let infcx = cx.tcx.infer_ctxt().build();

View File

@ -713,7 +713,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
);
debug!(?poly_trait_ref, ?assoc_bindings);
bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity);
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
let mut dup_bindings = FxHashMap::default();
for binding in &assoc_bindings {

View File

@ -62,11 +62,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
match bound_pred.skip_binder() {
ty::ClauseKind::Trait(trait_pred) => {
assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
trait_bounds.push((
bound_pred.rebind(trait_pred.trait_ref),
span,
trait_pred.constness,
));
trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span));
}
ty::ClauseKind::Projection(proj) => {
projection_bounds.push((bound_pred.rebind(proj), span));
@ -86,7 +82,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Expand trait aliases recursively and check that only one regular (non-auto) trait
// is used and no 'maybe' bounds are used.
let expanded_traits =
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
.filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
@ -126,7 +122,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if regular_traits.is_empty() && auto_traits.is_empty() {
let trait_alias_span = trait_bounds
.iter()
.map(|&(trait_ref, _, _)| trait_ref.def_id())
.map(|&(trait_ref, _)| trait_ref.def_id())
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
.map(|trait_ref| tcx.def_span(trait_ref));
let reported =
@ -157,10 +153,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let regular_traits_refs_spans = trait_bounds
.into_iter()
.filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
assert_eq!(constness, ty::BoundConstness::NotConst);
for (base_trait_ref, span) in regular_traits_refs_spans {
let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
for pred in traits::elaborate(tcx, [base_pred]) {
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);

View File

@ -42,13 +42,12 @@ impl<'tcx> Bounds<'tcx> {
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) {
self.clauses.push((
trait_ref
.map_bound(|trait_ref| {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
})
.to_predicate(tcx),
span,

View File

@ -194,7 +194,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match (tcx.impl_polarity(def_id), impl_.polarity) {
(ty::ImplPolarity::Positive, _) => {
check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness);
check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
}
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
// FIXME(#27579): what amount of WF checking do we need for neg impls?
@ -1191,7 +1191,6 @@ fn check_impl<'tcx>(
item: &'tcx hir::Item<'tcx>,
ast_self_ty: &hir::Ty<'_>,
ast_trait_ref: &Option<hir::TraitRef<'_>>,
constness: hir::Constness,
) {
enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
match ast_trait_ref {
@ -1205,14 +1204,8 @@ fn check_impl<'tcx>(
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
trait_ref,
);
let trait_pred = ty::TraitPredicate {
trait_ref,
constness: match constness {
hir::Constness::Const => ty::BoundConstness::ConstIfConst,
hir::Constness::NotConst => ty::BoundConstness::NotConst,
},
polarity: ty::ImplPolarity::Positive,
};
let trait_pred =
ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive };
let mut obligations = traits::wf::trait_obligations(
wfcx.infcx,
wfcx.param_env,

View File

@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
use rustc_span::symbol::{sym, Ident};
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol, DUMMY_SP};
/// Returns a list of all type predicates (explicit and implicit) for the definition with
@ -37,17 +37,10 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
// from the trait itself that *shouldn't* be shown as the source of
// an obligation and instead be skipped. Otherwise we'd use
// `tcx.def_span(def_id);`
let constness = if tcx.has_attr(def_id, sym::const_trait) {
ty::BoundConstness::ConstIfConst
} else {
ty::BoundConstness::NotConst
};
let span = rustc_span::DUMMY_SP;
result.predicates =
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
ty::TraitRef::identity(tcx, def_id).to_predicate(tcx),
span,
))));
}
@ -204,7 +197,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// (see below). Recall that a default impl is not itself an impl, but rather a
// set of defaults that can be incorporated into another impl.
if let Some(trait_ref) = is_default_impl_trait {
predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id)));
predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id)));
}
// Collect the region predicates that were declared inline as
@ -777,8 +770,7 @@ pub(super) fn type_param_predicates(
if param_id == item_hir_id {
let identity_trait_ref =
ty::TraitRef::identity(tcx, item_def_id.to_def_id());
extend =
Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
extend = Some((identity_trait_ref.to_predicate(tcx), item.span));
}
generics
}

View File

@ -431,45 +431,13 @@ fn check_predicates<'tcx>(
///
/// So we make that check in this function and try to raise a helpful error message.
fn trait_predicates_eq<'tcx>(
tcx: TyCtxt<'tcx>,
_tcx: TyCtxt<'tcx>,
predicate1: ty::Predicate<'tcx>,
predicate2: ty::Predicate<'tcx>,
span: Span,
_span: Span,
) -> bool {
let pred1_kind = predicate1.kind().skip_binder();
let pred2_kind = predicate2.kind().skip_binder();
let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) {
(
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred1)),
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred2)),
) => (pred1, pred2),
// Just use plain syntactic equivalence if either of the predicates aren't
// trait predicates or have bound vars.
_ => return predicate1 == predicate2,
};
let predicates_equal_modulo_constness = {
let pred1_unconsted =
ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred1 };
let pred2_unconsted =
ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred2 };
pred1_unconsted == pred2_unconsted
};
if !predicates_equal_modulo_constness {
return false;
}
// Check that the predicate on the specializing impl is at least as const as
// the one on the base.
match (trait_pred2.constness, trait_pred1.constness) {
(ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => {
tcx.sess.emit_err(errors::MissingTildeConst { span });
}
_ => {}
}
true
// FIXME(effects)
predicate1 == predicate2
}
#[instrument(level = "debug", skip(tcx))]
@ -482,7 +450,6 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
// items.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
})) => {
if !matches!(
@ -536,7 +503,6 @@ fn trait_predicate_kind<'tcx>(
match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))

View File

@ -156,7 +156,6 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
match pred.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref: ty::TraitRef { def_id: _, args, .. },
constness: _,
polarity: _,
}) => {
for subst in &args[1..] {

View File

@ -2988,7 +2988,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Binder::dummy(ty::TraitPredicate {
trait_ref: impl_trait_ref,
polarity: ty::ImplPolarity::Positive,
constness: ty::BoundConstness::NotConst,
}),
|derived| {
traits::ImplDerivedObligation(Box::new(

View File

@ -1461,10 +1461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
param_env,
bounds,
) {
// N.B. We are remapping all predicates to non-const since we don't know if we just
// want them as function pointers or we are calling them from a const-context. The
// actual checking will occur in `rustc_const_eval::transform::check_consts`.
self.register_predicate(obligation.without_const(self.tcx));
self.register_predicate(obligation);
}
}

View File

@ -1856,19 +1856,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.adjust_fulfillment_error_for_expr_obligation(error)
|| before_span != error.obligation.cause.span
{
// Store both the predicate and the predicate *without constness*
// since sometimes we instantiate and check both of these in a
// method call, for example.
remap_cause.insert((
before_span,
error.obligation.predicate,
error.obligation.cause.clone(),
));
remap_cause.insert((
before_span,
error.obligation.predicate.without_const(self.tcx),
error.obligation.cause.clone(),
));
} else {
// If it failed to be adjusted once around, it may be adjusted
// via the "remap cause" mapping the second time...

View File

@ -341,15 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Construct an obligation
let poly_trait_ref = ty::Binder::dummy(trait_ref);
(
traits::Obligation::new(
self.tcx,
cause,
self.param_env,
poly_trait_ref.without_const(),
),
args,
)
(traits::Obligation::new(self.tcx, cause, self.param_env, poly_trait_ref), args)
}
/// `lookup_method_in_trait` is used for overloaded operators.

View File

@ -1599,8 +1599,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
}
let predicate =
ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx);
let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx);
parent_pred = Some(predicate);
let obligation =
traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate);

View File

@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span,
self.body_id,
self.param_env,
poly_trait_ref.without_const(),
poly_trait_ref,
);
self.predicate_may_hold(&obligation)
})

View File

@ -25,7 +25,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
cause,
recursion_depth: 0,
param_env,
predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(infcx.tcx),
predicate: ty::Binder::dummy(trait_ref).to_predicate(infcx.tcx),
},
);
}

View File

@ -77,13 +77,6 @@ impl<'tcx> PredicateObligation<'tcx> {
recursion_depth: self.recursion_depth,
})
}
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> {
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() {
self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const()))));
}
self
}
}
impl<'tcx> PolyTraitObligation<'tcx> {

View File

@ -264,11 +264,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
};
let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(mut clause, span))| {
// when parent predicate is non-const, elaborate it to non-const predicates.
if data.constness == ty::BoundConstness::NotConst {
clause = clause.without_const(tcx);
}
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
elaboratable.child_with_derived_cause(
clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
span,

View File

@ -498,11 +498,9 @@ impl<'tcx> Predicate<'tcx> {
.map_bound(|kind| match kind {
PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity,
})) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity: polarity.flip()?,
}))),
@ -513,19 +511,6 @@ impl<'tcx> Predicate<'tcx> {
Some(tcx.mk_predicate(kind))
}
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
if let PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
&& constness != BoundConstness::NotConst
{
self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness: BoundConstness::NotConst,
polarity,
}))));
}
self
}
#[instrument(level = "debug", skip(tcx), ret)]
pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind().skip_binder() {
@ -629,10 +614,6 @@ impl<'tcx> Clause<'tcx> {
None
}
}
pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
self.as_predicate().without_const(tcx).expect_clause()
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@ -852,8 +833,6 @@ impl<'tcx> Clause<'tcx> {
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,
pub constness: BoundConstness,
/// If polarity is Positive: we are proving that the trait is implemented.
///
/// If polarity is Negative: we are proving that a negative impl of this trait
@ -878,24 +857,6 @@ impl<'tcx> TraitPredicate<'tcx> {
pub fn self_ty(self) -> Ty<'tcx> {
self.trait_ref.self_ty()
}
#[inline]
pub fn is_const_if_const(self) -> bool {
self.constness == BoundConstness::ConstIfConst
}
pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
match (self.constness, constness) {
(BoundConstness::NotConst, _)
| (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
(BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
}
}
pub fn without_const(mut self) -> Self {
self.constness = BoundConstness::NotConst;
self
}
}
impl<'tcx> PolyTraitPredicate<'tcx> {
@ -908,11 +869,6 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
self.map_bound(|trait_ref| trait_ref.self_ty())
}
#[inline]
pub fn is_const_if_const(self) -> bool {
self.skip_binder().is_const_if_const()
}
#[inline]
pub fn polarity(self) -> ImplPolarity {
self.skip_binder().polarity
@ -1287,7 +1243,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
self.without_const()
TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive }
}
}
@ -1328,7 +1284,6 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
self.map_bound(|trait_ref| TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
})
}
@ -1826,24 +1781,6 @@ impl<'tcx> ParamEnv<'tcx> {
}
}
// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
// the constness of trait bounds is being propagated correctly.
impl<'tcx> PolyTraitRef<'tcx> {
#[inline]
pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> {
self.map_bound(|trait_ref| ty::TraitPredicate {
trait_ref,
constness,
polarity: ty::ImplPolarity::Positive,
})
}
#[inline]
pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
self.with_constness(BoundConstness::NotConst)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
#[derive(HashStable, Lift)]
pub struct ParamEnvAnd<'tcx, T> {

View File

@ -2806,10 +2806,7 @@ define_print_and_forward_display! {
}
TraitPredPrintModifiersAndPath<'tcx> {
if let ty::BoundConstness::ConstIfConst = self.0.constness {
p!("~const ")
}
// FIXME(effects) print `~const` here
if let ty::ImplPolarity::Negative = self.0.polarity {
p!("!")
}
@ -2843,9 +2840,7 @@ define_print_and_forward_display! {
ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), ": ");
if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl {
p!("~const ");
}
// FIXME(effects) print `~const` here
if let ty::ImplPolarity::Negative = self.polarity {
p!("!");
}

View File

@ -826,7 +826,6 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
Ok(ty::TraitPredicate {
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
constness: relation.relate(a.constness, b.constness)?,
polarity: relation.relate(a.polarity, b.polarity)?,
})
}

View File

@ -172,9 +172,7 @@ impl fmt::Debug for ty::ParamConst {
impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let ty::BoundConstness::ConstIfConst = self.constness {
write!(f, "~const ")?;
}
// FIXME(effects) printing?
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
}
}

View File

@ -722,7 +722,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
use crate::ty::ToPredicate;
match self.skip_binder() {
ExistentialPredicate::Trait(tr) => {
self.rebind(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx)
self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx)
}
ExistentialPredicate::Projection(p) => {
self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
@ -737,7 +737,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]);
ty::TraitRef::new(tcx, did, err_args)
};
self.rebind(trait_ref).without_const().to_predicate(tcx)
self.rebind(trait_ref).to_predicate(tcx)
}
}
}
@ -869,18 +869,6 @@ impl<'tcx> TraitRef<'tcx> {
)
}
/// Converts this trait ref to a trait predicate with a given `constness` and a positive polarity.
#[inline]
pub fn with_constness(self, constness: ty::BoundConstness) -> ty::TraitPredicate<'tcx> {
ty::TraitPredicate { trait_ref: self, constness, polarity: ty::ImplPolarity::Positive }
}
/// Converts this trait ref to a trait predicate without `const` and a positive polarity.
#[inline]
pub fn without_const(self) -> ty::TraitPredicate<'tcx> {
self.with_constness(ty::BoundConstness::NotConst)
}
#[inline]
pub fn self_ty(&self) -> Ty<'tcx> {
self.args.type_at(0)

View File

@ -147,7 +147,7 @@ where
fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow<V::BreakTy> {
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
self.visit_trait(trait_ref)
}
ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {

View File

@ -72,7 +72,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
cause: traits::ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx),
predicate: ty::Binder::dummy(trait_ref).to_predicate(self.tcx),
};
self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
}

View File

@ -727,7 +727,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
self.tcx(),
ty::TraitPredicate {
trait_ref: self_trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
},
);

View File

@ -97,7 +97,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
orig_env,
ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: if polarity {
ImplPolarity::Positive
} else {
@ -260,7 +259,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
predicates.push_back(ty::Binder::dummy(ty::TraitPredicate {
trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]),
constness: ty::BoundConstness::NotConst,
// Auto traits are positive
polarity: ty::ImplPolarity::Positive,
}));

View File

@ -97,7 +97,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
cause,
recursion_depth: 0,
param_env,
predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx),
});
}

View File

@ -100,7 +100,6 @@ pub trait InferCtxtExt<'tcx> {
&self,
param_env: ty::ParamEnv<'tcx>,
ty: ty::Binder<'tcx, Ty<'tcx>>,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
}
@ -356,7 +355,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
param_env: ty::ParamEnv<'tcx>,
ty: ty::Binder<'tcx, Ty<'tcx>>,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
self.commit_if_ok(|_| {
@ -372,12 +370,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
});
// FIXME(effects)
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
let obligation = Obligation::new(
self.tcx,
ObligationCause::dummy(),
param_env,
ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }),
ty.rebind(ty::TraitPredicate { trait_ref, polarity }),
);
let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation);
@ -689,8 +688,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
let predicate_is_const = ty::BoundConstness::ConstIfConst
== trait_predicate.skip_binder().constness;
// FIXME(effects)
let predicate_is_const = false;
if self.tcx.sess.has_errors().is_some()
&& trait_predicate.references_error()
@ -1909,9 +1908,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.all_impls(trait_pred.def_id())
.filter_map(|def_id| {
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
|| !trait_pred
.skip_binder()
.is_constness_satisfied_by(self.tcx.constness(def_id))
|| !self.tcx.is_user_visible_dep(def_id.krate)
{
return None;
@ -2996,7 +2992,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
obligation.param_env,
trait_ref.self_ty(),
trait_predicate.skip_binder().constness,
trait_predicate.skip_binder().polarity,
)
{
@ -3099,14 +3094,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn maybe_add_note_for_unsatisfied_const(
&self,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
err: &mut Diagnostic,
span: Span,
_obligation: &PredicateObligation<'tcx>,
_trait_ref: ty::PolyTraitRef<'tcx>,
_trait_predicate: &ty::PolyTraitPredicate<'tcx>,
_err: &mut Diagnostic,
_span: Span,
) -> UnsatisfiedConst {
let mut unsatisfied_const = UnsatisfiedConst(false);
if trait_predicate.is_const_if_const() {
let unsatisfied_const = UnsatisfiedConst(false);
// FIXME(effects)
/* if trait_predicate.is_const_if_const() {
let non_const_predicate = trait_ref.without_const();
let non_const_obligation = Obligation {
cause: obligation.cause.clone(),
@ -3126,7 +3122,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
),
);
}
}
} */
unsatisfied_const
}

View File

@ -133,7 +133,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
def_id: DefId,
) -> bool {
let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const())
pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref)
}
/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?

View File

@ -574,7 +574,6 @@ fn virtual_call_violation_for_method<'tcx>(
// implement auto traits if the underlying type does as well.
if let ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref: pred_trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}) = pred.kind().skip_binder()
&& pred_trait_ref.self_ty() == tcx.types.self_param

View File

@ -1306,7 +1306,7 @@ fn normalize_to_error<'a, 'tcx>(
cause,
recursion_depth: depth,
param_env,
predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
predicate: trait_ref.to_predicate(selcx.tcx()),
};
let tcx = selcx.infcx.tcx;
let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
@ -1867,8 +1867,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
if selcx.infcx.predicate_must_hold_modulo_regions(
&obligation.with(
selcx.tcx(),
ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty])
.without_const(),
ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]),
),
) =>
{
@ -2152,8 +2151,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
LangItem::Sized,
obligation.cause.span(),
[self_ty],
)
.without_const();
);
obligations.push(obligation.with(tcx, sized_predicate));
}
(metadata_ty.into(), obligations)

View File

@ -154,9 +154,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
candidates
.vec
.extend(result.into_iter().map(|(idx, constness)| ProjectionCandidate(idx, constness)));
// FIXME(effects) proper constness needed?
candidates.vec.extend(
result.into_iter().map(|idx| ProjectionCandidate(idx, ty::BoundConstness::NotConst)),
);
}
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller

View File

@ -59,7 +59,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ParamCandidate(param) => {
let obligations =
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
ImplSource::Param(param.skip_binder().constness, obligations)
// FIXME(effects)
ImplSource::Param(ty::BoundConstness::NotConst, obligations)
}
ImplCandidate(impl_def_id) => {
@ -128,14 +129,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
subobligation.set_depth_from_parent(obligation.recursion_depth);
}
if !obligation.predicate.is_const_if_const() {
// normalize nested predicates according to parent predicate's constness.
impl_src = impl_src.map(|mut o| {
o.predicate = o.predicate.without_const(self.tcx());
o
});
}
Ok(impl_src)
}
@ -1305,6 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
ty::Alias(ty::Projection | ty::Inherent, ..) => {
// FIXME(effects) this needs constness
let predicate = normalize_with_depth_to(
self,
obligation.param_env,
@ -1317,7 +1311,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
cause.span,
[nested_ty],
),
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
}),
&mut nested,
@ -1336,6 +1329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// since it's either not `const Drop` (and we raise an error during selection),
// or it's an ADT (and we need to check for a custom impl during selection)
_ => {
// FIXME(effects) this needs constness
let predicate = self_ty.rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef::from_lang_item(
self.tcx(),
@ -1343,7 +1337,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
cause.span,
[nested_ty],
),
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
});

View File

@ -1583,7 +1583,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
) -> smallvec::SmallVec<[usize; 2]> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
@ -1632,7 +1632,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => false,
}
}) {
return Some((idx, pred.constness));
return Some(idx);
}
}
None
@ -1820,7 +1820,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
(ParamCandidate(other), ParamCandidate(victim)) => {
let same_except_bound_vars = other.skip_binder().trait_ref
== victim.skip_binder().trait_ref
&& other.skip_binder().constness == victim.skip_binder().constness
&& other.skip_binder().polarity == victim.skip_binder().polarity
&& !other.skip_binder().trait_ref.has_escaping_bound_vars();
if same_except_bound_vars {
@ -1830,12 +1829,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// probably best characterized as a "hack", since we might prefer to just do our
// best to *not* create essentially duplicate candidates in the first place.
DropVictim::drop_if(other.bound_vars().len() <= victim.bound_vars().len())
} else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
&& victim.skip_binder().constness == ty::BoundConstness::NotConst
&& other.skip_binder().polarity == victim.skip_binder().polarity
{
// Drop otherwise equivalent non-const candidates in favor of const candidates.
DropVictim::Yes
} else {
DropVictim::No
}

View File

@ -500,16 +500,12 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
let mut pretty_predicates =
Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
for (mut p, _) in predicates {
for (p, _) in predicates {
if let Some(poly_trait_ref) = p.as_trait_clause() {
if Some(poly_trait_ref.def_id()) == sized_trait {
types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder());
continue;
}
if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness {
p = p.without_const(tcx);
}
}
pretty_predicates.push(p.to_string());
}

View File

@ -101,7 +101,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
let tcx = self.tcx;
let trait_ref = item.trait_ref();
let pred = trait_ref.without_const().to_predicate(tcx);
let pred = trait_ref.to_predicate(tcx);
debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
@ -113,9 +113,13 @@ impl<'tcx> TraitAliasExpander<'tcx> {
// Don't recurse if this trait alias is already on the stack for the DFS search.
let anon_pred = anonymize_predicate(tcx, pred);
if item.path.iter().rev().skip(1).any(|&(tr, _)| {
anonymize_predicate(tcx, tr.without_const().to_predicate(tcx)) == anon_pred
}) {
if item
.path
.iter()
.rev()
.skip(1)
.any(|&(tr, _)| anonymize_predicate(tcx, tr.to_predicate(tcx)) == anon_pred)
{
return false;
}

View File

@ -86,7 +86,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
let mut emit_vptr_on_new_entry = false;
let mut visited = PredicateSet::new(tcx);
let predicate = trait_ref.without_const().to_predicate(tcx);
let predicate = trait_ref.to_predicate(tcx);
let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))];
visited.insert(predicate);

View File

@ -348,11 +348,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
// if the trait predicate is not const, the wf obligations should not be const as well.
let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.args)
} else {
self.nominal_obligations(trait_ref.def_id, trait_ref.args)
};
let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.args);
debug!("compute_trait_pred obligations {:?}", obligations);
let param_env = self.param_env;
@ -445,8 +441,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// `i32: Clone`
// `i32: Copy`
// ]
// Projection types do not require const predicates.
let obligations = self.nominal_obligations_without_const(data.def_id, data.args);
let obligations = self.nominal_obligations(data.def_id, data.args);
self.out.extend(obligations);
self.compute_projection_args(data.args);
@ -472,8 +467,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
self.recursion_depth,
&mut self.out,
);
// Inherent projection types do not require const predicates.
let obligations = self.nominal_obligations_without_const(data.def_id, args);
let obligations = self.nominal_obligations(data.def_id, args);
self.out.extend(obligations);
}
@ -516,7 +510,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause,
self.recursion_depth,
self.param_env,
ty::Binder::dummy(trait_ref).without_const(),
ty::Binder::dummy(trait_ref),
));
}
}
@ -667,7 +661,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
ty::FnDef(did, args) => {
let obligations = self.nominal_obligations_without_const(did, args);
let obligations = self.nominal_obligations(did, args);
self.out.extend(obligations);
}
@ -822,11 +816,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
fn nominal_obligations_inner(
fn nominal_obligations(
&mut self,
def_id: DefId,
args: GenericArgsRef<'tcx>,
remap_constness: bool,
) -> Vec<traits::PredicateObligation<'tcx>> {
let predicates = self.tcx().predicates_of(def_id);
let mut origins = vec![def_id; predicates.predicates.len()];
@ -841,16 +834,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
debug_assert_eq!(predicates.predicates.len(), origins.len());
iter::zip(predicates, origins.into_iter().rev())
.map(|((mut pred, span), origin_def_id)| {
.map(|((pred, span), origin_def_id)| {
let code = if span.is_dummy() {
traits::ItemObligation(origin_def_id)
} else {
traits::BindingObligation(origin_def_id, span)
};
let cause = self.cause(code);
if remap_constness {
pred = pred.without_const(self.tcx());
}
traits::Obligation::with_depth(
self.tcx(),
cause,
@ -863,22 +853,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
.collect()
}
fn nominal_obligations(
&mut self,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Vec<traits::PredicateObligation<'tcx>> {
self.nominal_obligations_inner(def_id, args, false)
}
fn nominal_obligations_without_const(
&mut self,
def_id: DefId,
args: GenericArgsRef<'tcx>,
) -> Vec<traits::PredicateObligation<'tcx>> {
self.nominal_obligations_inner(def_id, args, true)
}
fn from_object_ty(
&mut self,
ty: Ty<'tcx>,

View File

@ -370,9 +370,8 @@ fn clean_poly_trait_predicate<'tcx>(
cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
if pred.skip_binder().constness == ty::BoundConstness::ConstIfConst
&& Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait()
{
// FIXME(effects) check constness
if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() {
return None;
}

View File

@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::{
self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv,
self, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv,
ToPredicate, TraitPredicate, Ty, TyCtxt,
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -523,7 +523,6 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
if let ClauseKind::Trait(p) = p.kind().skip_binder()
&& p.trait_ref.def_id == eq_trait_id
&& let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
&& p.constness == BoundConstness::NotConst
{
// Flag types which already have an `Eq` bound.
params[self_ty.index as usize].1 = false;
@ -535,7 +534,6 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
ClauseKind::Trait(TraitPredicate {
trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]),
constness: BoundConstness::NotConst,
polarity: ImplPolarity::Positive,
})
.to_predicate(tcx)

View File

@ -10,7 +10,7 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPat
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{
self, Binder, BoundConstness, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind,
self, Binder, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind,
GenericArgsRef, ImplPolarity, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults,
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -171,7 +171,6 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
= cx.tcx.infer_ctxt().build().type_implements_fn_trait(
cx.param_env,
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
BoundConstness::NotConst,
ImplPolarity::Positive,
) && path_to_local(callee)
.map_or(

View File

@ -16,7 +16,7 @@ use rustc_middle::mir::{
};
use rustc_middle::traits::{ImplSource, ObligationCause, BuiltinImplSource};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, BoundConstness, GenericArgKind, TraitRef, Ty, TyCtxt};
use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt};
use rustc_semver::RustcVersion;
use rustc_span::symbol::sym;
use rustc_span::Span;
@ -399,11 +399,12 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
return true;
}
// FIXME(effects) constness
let obligation = Obligation::new(
tcx,
ObligationCause::dummy_with_span(body.span),
ConstCx::new(tcx, body).param_env,
TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst),
TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]),
);
let infcx = tcx.infer_ctxt().build();

View File

@ -267,7 +267,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx),
};
infcx
.evaluate_obligation(&obligation)

View File

@ -1,5 +1,6 @@
// compile-flags: -Zmir-opt-level=0
// run-pass
// known-bug: #110395
// FIXME run-pass
#![feature(const_float_bits_conv)]
#![feature(const_float_classify)]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<A as MyEq<B>>::eq` in constant functions
--> $DIR/const-float-classify.rs:31:7
|
LL | x.eq(y)
| ^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -7,12 +7,22 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
error[E0015]: cannot call non-const fn `<T as Tr>::a` in constants
--> $DIR/constifconst-call-in-const-position.rs:17:9
|
LL | [0; T::a()]
| ^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<T as Tr>::a` in constants
--> $DIR/constifconst-call-in-const-position.rs:16:38
|
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
| ^^^^^^ calling non-const function `<() as Tr>::a`
| ^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error; 1 warning emitted
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0080`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -20,6 +20,7 @@ impl<T> Opt<T> {
match self {
Opt::Some(t) => t,
Opt::None => f(),
//~^ ERROR cannot call
}
}
}

View File

@ -1,3 +1,15 @@
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/unstable-const-fn-in-libcore.rs:22:26
|
LL | Opt::None => f(),
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
| +++++++++++++++++++++++++++++
error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:17:60
|
@ -16,6 +28,7 @@ LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
LL | }
| - value is dropped here
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0493`.
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
// Test that we can call methods from const trait impls inside of generic const items.

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Create>::create` in constants
--> $DIR/const-trait-impl.rs:11:37
|
LL | const CREATE<T: ~const Create>: T = T::create();
| ^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,3 +1,15 @@
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/normalize-tait-in-const.rs:26:5
|
LL | fun(filter_positive());
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) {
| ++++++++++++++++++++++++++++++++++++
error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/normalize-tait-in-const.rs:25:79
|
@ -7,6 +19,7 @@ LL | fun(filter_positive());
LL | }
| - value is dropped here
error: aborting due to previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0493`.
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl)]
#[const_trait]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<<T as Foo>::Assoc as Foo>::foo` in constant functions
--> $DIR/assoc-type-const-bound-usage.rs:12:5
|
LL | <T as Foo>::Assoc::foo();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,21 +1,15 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
= note: calling non-const function `<() as Tr>::a`
|
note: inside `<fn(()) -> i32 {<() as Tr>::a} as FnOnce<((),)>>::call_once - shim(fn(()) -> i32 {<() as Tr>::a})`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
note: inside `need_const_closure::<fn(()) -> i32 {<() as Tr>::a}>`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closure-trait-method-fail.rs:15:5
|
LL | x(())
| ^^^^^
note: inside `_`
--> $DIR/const-closure-trait-method-fail.rs:18:23
|
LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 {
| ++++++++++++++++++++++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl)]
#[const_trait]

View File

@ -0,0 +1,15 @@
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closure-trait-method.rs:15:5
|
LL | x(())
| ^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 {
| ++++++++++++++++++++++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl)]

View File

@ -0,0 +1,39 @@
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closures.rs:12:5
|
LL | f() * 7
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>,
| +++++++++++++++++++++++++
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closures.rs:24:5
|
LL | f() + f()
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 {
| +++++++++++++++++++++++++
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closures.rs:24:11
|
LL | f() + f()
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 {
| +++++++++++++++++++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,3 +1,11 @@
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
--> $DIR/const-drop-fail-2.rs:25:9
|
LL | T::a();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-drop-fail-2.rs:29:36
|
@ -6,6 +14,15 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
--> $DIR/const-drop-fail-2.rs:39:9
|
LL | T::a();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0493`.
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -14,6 +14,15 @@ LL | let _ = S(&mut c);
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 2 previous errors
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
--> $DIR/const-drop.rs:70:13
|
LL | T::foo();
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0493`.
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -14,6 +14,15 @@ LL | let _ = S(&mut c);
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 2 previous errors
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
--> $DIR/const-drop.rs:70:13
|
LL | T::foo();
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0493`.
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -13,7 +13,7 @@ const fn foo<T>() where T: ~const Tr {}
pub trait Foo {
fn foo() {
foo::<()>();
//FIXME ~^ ERROR the trait bound `(): ~const Tr` is not satisfied
//FIXME ~^ ERROR the trait bound `(): Tr` is not satisfied
}
}

View File

@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
error[E0277]: the trait bound `(): Tr` is not satisfied
--> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
|
LL | ().a()
| ^ the trait `~const Tr` is not implemented for `()`
| ^ the trait `Tr` is not implemented for `()`
|
= help: the trait `Tr` is implemented for `()`

View File

@ -1,6 +1,7 @@
// Tests that trait bounds on specializing trait impls must be `~const` if the
// same bound is present on the default impl and is `~const` there.
// known-bug: #110395
// check-pass
// FIXME(effects) ^ should error
#![feature(const_trait_impl)]
#![feature(rustc_attrs)]

View File

@ -1,14 +0,0 @@
error: missing `~const` qualifier for specialization
--> $DIR/const-default-bound-non-const-specialized-bound.rs:33:8
|
LL | T: Foo, //FIXME ~ ERROR missing `~const` qualifier
| ^^^
error: missing `~const` qualifier for specialization
--> $DIR/const-default-bound-non-const-specialized-bound.rs:53:8
|
LL | T: Foo,
| ^^^
error: aborting due to 2 previous errors

View File

@ -1,7 +1,8 @@
// Tests that a const default trait impl can be specialized by another const
// trait impl and that the specializing impl will be used during const-eval.
// run-pass
// known-bug: #110395
// FIXME run-pass
#![feature(const_trait_impl)]
#![feature(min_specialization)]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions
--> $DIR/const-default-const-specialized.rs:16:5
|
LL | T::value()
| ^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,7 +1,7 @@
// Tests that a non-const default impl can be specialized by a const trait impl,
// but that the default impl cannot be used in a const context.
// run-pass
// known-bug: #110395
// FIXME run-pass
#![feature(const_trait_impl)]
#![feature(min_specialization)]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions
--> $DIR/non-const-default-const-specialized.rs:15:5
|
LL | T::value()
| ^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -22,7 +22,7 @@ impl<T: ~const Spec> const A for T {
impl<T: Spec + Sup> A for T {
//~^ ERROR: cannot specialize
//~| ERROR: missing `~const` qualifier
//FIXME(effects) ~| ERROR: missing `~const` qualifier
fn a() -> u32 {
3
}

View File

@ -4,11 +4,5 @@ error: cannot specialize on const impl with non-const impl
LL | impl<T: Spec + Sup> A for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing `~const` qualifier for specialization
--> $DIR/specializing-constness.rs:23:9
|
LL | impl<T: Spec + Sup> A for T {
| ^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error

View File

@ -1,17 +1,17 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:12:19
--> $DIR/super-traits-fail-3.rs:13:19
|
LL | trait Bar: ~const Foo {}
| ^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:12:19
--> $DIR/super-traits-fail-3.rs:13:19
|
LL | trait Bar: ~const Foo {}
| ^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:16:24
--> $DIR/super-traits-fail-3.rs:17:24
|
LL | const fn foo<T: ~const Bar>(x: &T) {
| ^^^

View File

@ -1,11 +1,11 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:12:19
--> $DIR/super-traits-fail-3.rs:13:19
|
LL | trait Bar: ~const Foo {}
| ^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:12:19
--> $DIR/super-traits-fail-3.rs:13:19
|
LL | trait Bar: ~const Foo {}
| ^^^

View File

@ -1,7 +1,8 @@
#![feature(const_trait_impl)]
// revisions: yy yn ny nn
//[yy] check-pass
//[yy] known-bug: #110395
//FIXME [yy] check-pass
#[cfg_attr(any(yy, yn), const_trait)]
trait Foo {

View File

@ -1,5 +1,5 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/super-traits-fail-3.rs:16:24
--> $DIR/super-traits-fail-3.rs:17:24
|
LL | const fn foo<T: ~const Bar>(x: &T) {
| ^^^

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
--> $DIR/super-traits-fail-3.rs:19:7
|
LL | x.a();
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl)]
#[const_trait]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
--> $DIR/super-traits.rs:21:7
|
LL | t.a();
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -24,6 +24,7 @@ impl const Add42 for () {
fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
//~^ ERROR `~const` is not allowed here
//~| ERROR cannot call
Foo
}

View File

@ -10,5 +10,14 @@ note: this function is not `const`, so it cannot have `~const` trait bounds
LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
| ^^^
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<A as Add42>::add` in constants
--> $DIR/tilde-const-and-const-params.rs:25:61
|
LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
| ^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl)]
#[const_trait]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Foo>::foo` in constant functions
--> $DIR/tilde_const_on_impl_bound.rs:14:16
|
LL | self.0.foo()
| ^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -3,7 +3,7 @@
// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a
// test is not enough.
// known-bug: #110395
// check-pass
// FIXME check-pass
#![feature(const_trait_impl)]
#[const_trait]

View File

@ -0,0 +1,51 @@
error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
--> $DIR/trait-where-clause-const.rs:20:5
|
LL | T::a();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<T as Foo>::b` in constant functions
--> $DIR/trait-where-clause-const.rs:21:5
|
LL | T::b();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<T as Foo>::c::<T>` in constant functions
--> $DIR/trait-where-clause-const.rs:23:5
|
LL | T::c::<T>();
| ^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
--> $DIR/trait-where-clause-const.rs:28:5
|
LL | T::a();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<T as Foo>::b` in constant functions
--> $DIR/trait-where-clause-const.rs:29:5
|
LL | T::b();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<T as Foo>::c::<T>` in constant functions
--> $DIR/trait-where-clause-const.rs:30:5
|
LL | T::c::<T>();
| ^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// run-pass
// known-bug: #110395
// FIXME run-pass
#![feature(const_trait_impl)]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<Self as Bar>::bar` in constant functions
--> $DIR/trait-where-clause-run.rs:14:9
|
LL | <Self as Bar>::bar() * 6
| ^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl)]

View File

@ -0,0 +1,11 @@
error[E0015]: cannot call non-const fn `<T as Foo>::bar` in constant functions
--> $DIR/trait-where-clause-self-referential.rs:22:5
|
LL | T::bar();
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.