Implement const effect predicate in new solver

This commit is contained in:
Michael Goulet 2024-10-20 19:49:11 +00:00
parent a16d491054
commit cde29b9ec9
127 changed files with 1702 additions and 1170 deletions

View File

@ -81,6 +81,17 @@ impl<'tcx> Bounds<'tcx> {
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
}
/// Push a `const` or `~const` bound as a `HostEffect` predicate.
pub(crate) fn push_const_bound(
&mut self,
tcx: TyCtxt<'tcx>,
bound_trait_ref: ty::PolyTraitRef<'tcx>,
host: ty::HostPolarity,
span: Span,
) {
self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, host), span));
}
pub(crate) fn clauses(
&self,
// FIXME(effects): remove tcx

View File

@ -181,6 +181,7 @@ fn compare_method_predicate_entailment<'tcx>(
});
// Create mapping from trait method to impl method.
let impl_def_id = impl_m.container_id(tcx);
let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(
tcx,
impl_m.container_id(tcx),
@ -204,6 +205,24 @@ fn compare_method_predicate_entailment<'tcx>(
trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),
);
// FIXME(effects): This should be replaced with a more dedicated method.
let check_const_if_const = tcx.constness(impl_def_id) == hir::Constness::Const;
if check_const_if_const {
// Augment the hybrid param-env with the const conditions
// of the impl header and the trait method.
hybrid_preds.extend(
tcx.const_conditions(impl_def_id)
.instantiate_identity(tcx)
.into_iter()
.chain(
tcx.const_conditions(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args),
)
.map(|(trait_ref, _)| {
trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)
}),
);
}
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
@ -230,6 +249,34 @@ fn compare_method_predicate_entailment<'tcx>(
ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
}
// If we're within a const implementation, we need to make sure that the method
// does not assume stronger `~const` bounds than the trait definition.
//
// This registers the `~const` bounds of the impl method, which we will prove
// using the hybrid param-env that we earlier augmented with the const conditions
// from the impl header and trait method declaration.
if check_const_if_const {
for (const_condition, span) in
tcx.const_conditions(impl_m.def_id).instantiate_own_identity()
{
let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
let cause =
ObligationCause::new(span, impl_m_def_id, ObligationCauseCode::CompareImplItem {
impl_item_def_id: impl_m_def_id,
trait_item_def_id: trait_m.def_id,
kind: impl_m.kind,
});
ocx.register_obligation(traits::Obligation::new(
tcx,
cause,
param_env,
const_condition.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
));
}
}
// We now need to check that the signature of the impl method is
// compatible with that of the trait method. We do this by
// checking that `impl_fty <: trait_fty`.
@ -1846,9 +1893,10 @@ fn compare_type_predicate_entailment<'tcx>(
trait_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let impl_def_id = impl_ty.container_id(tcx);
let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id).rebase_onto(
tcx,
impl_ty.container_id(tcx),
impl_def_id,
impl_trait_ref.args,
);
@ -1856,7 +1904,9 @@ fn compare_type_predicate_entailment<'tcx>(
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
let impl_ty_own_bounds = impl_ty_predicates.instantiate_own_identity();
if impl_ty_own_bounds.len() == 0 {
let impl_ty_own_const_conditions =
tcx.const_conditions(impl_ty.def_id).instantiate_own_identity();
if impl_ty_own_bounds.len() == 0 && impl_ty_own_const_conditions.len() == 0 {
// Nothing to check.
return Ok(());
}
@ -1881,6 +1931,23 @@ fn compare_type_predicate_entailment<'tcx>(
let impl_ty_span = tcx.def_span(impl_ty_def_id);
let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let check_const_if_const = tcx.constness(impl_def_id) == hir::Constness::Const;
if check_const_if_const {
// Augment the hybrid param-env with the const conditions
// of the impl header and the trait assoc type.
hybrid_preds.extend(
tcx.const_conditions(impl_ty_predicates.parent.unwrap())
.instantiate_identity(tcx)
.into_iter()
.chain(
tcx.const_conditions(trait_ty.def_id).instantiate_own(tcx, trait_to_impl_args),
)
.map(|(trait_ref, _)| {
trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)
}),
);
}
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
debug!(caller_bounds=?param_env.caller_bounds());
@ -1901,6 +1968,27 @@ fn compare_type_predicate_entailment<'tcx>(
ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
}
if check_const_if_const {
// Validate the const conditions of the impl associated type.
for (const_condition, span) in impl_ty_own_const_conditions {
let normalize_cause = traits::ObligationCause::misc(span, impl_ty_def_id);
let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
let cause =
ObligationCause::new(span, impl_ty_def_id, ObligationCauseCode::CompareImplItem {
impl_item_def_id: impl_ty_def_id,
trait_item_def_id: trait_ty.def_id,
kind: impl_ty.kind,
});
ocx.register_obligation(traits::Obligation::new(
tcx,
cause,
param_env,
const_condition.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
));
}
}
// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();
@ -1983,7 +2071,7 @@ pub(super) fn check_type_bounds<'tcx>(
ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
};
let obligations: Vec<_> = tcx
let mut obligations: Vec<_> = tcx
.explicit_item_bounds(trait_ty.def_id)
.iter_instantiated_copied(tcx, rebased_args)
.map(|(concrete_ty_bound, span)| {
@ -1991,6 +2079,22 @@ pub(super) fn check_type_bounds<'tcx>(
traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
})
.collect();
// Only in a const implementation do we need to check that the `~const` item bounds hold.
if tcx.constness(container_id) == hir::Constness::Const {
obligations.extend(
tcx.implied_const_bounds(trait_ty.def_id)
.iter_instantiated_copied(tcx, rebased_args)
.map(|(c, span)| {
traits::Obligation::new(
tcx,
mk_cause(span),
param_env,
c.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
)
}),
);
}
debug!(item_bounds=?obligations);
// Normalize predicates with the assumption that the GAT may always normalize

View File

@ -32,7 +32,8 @@ use rustc_trait_selection::traits::misc::{
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
WellFormedLoc,
};
use rustc_type_ir::TypeFlags;
use rustc_type_ir::solve::NoSolution;
@ -86,7 +87,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.body_def_id,
ObligationCauseCode::WellFormed(loc),
);
self.ocx.register_obligation(traits::Obligation::new(
self.ocx.register_obligation(Obligation::new(
self.tcx(),
cause,
self.param_env,
@ -1173,7 +1174,7 @@ fn check_type_defn<'tcx>(
wfcx.body_def_id,
ObligationCauseCode::Misc,
);
wfcx.register_obligation(traits::Obligation::new(
wfcx.register_obligation(Obligation::new(
tcx,
cause,
wfcx.param_env,
@ -1369,6 +1370,30 @@ fn check_impl<'tcx>(
obligation.cause.span = hir_self_ty.span;
}
}
// Ensure that the `~const` where clauses of the trait hold for the impl.
if tcx.constness(item.owner_id.def_id) == hir::Constness::Const {
for (bound, _) in
tcx.const_conditions(trait_ref.def_id).instantiate(tcx, trait_ref.args)
{
let bound = wfcx.normalize(
item.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
bound,
);
wfcx.register_obligation(Obligation::new(
tcx,
ObligationCause::new(
hir_self_ty.span,
wfcx.body_def_id,
ObligationCauseCode::WellFormed(None),
),
wfcx.param_env,
bound.to_host_effect_clause(tcx, ty::HostPolarity::Maybe),
))
}
}
debug!(?obligations);
wfcx.register_obligations(obligations);
}
@ -1561,7 +1586,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
wfcx.body_def_id,
ObligationCauseCode::WhereClause(def_id.to_def_id(), DUMMY_SP),
);
traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
Obligation::new(tcx, cause, wfcx.param_env, pred)
});
let predicates = predicates.instantiate_identity(tcx);
@ -1852,7 +1877,7 @@ fn receiver_is_implemented<'tcx>(
let tcx = wfcx.tcx();
let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]);
let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
true
@ -2188,7 +2213,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
.unwrap_or(obligation_span);
}
let obligation = traits::Obligation::new(
let obligation = Obligation::new(
tcx,
traits::ObligationCause::new(
span,

View File

@ -77,6 +77,8 @@ pub fn provide(providers: &mut Providers) {
explicit_supertraits_containing_assoc_item:
predicates_of::explicit_supertraits_containing_assoc_item,
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
const_conditions: predicates_of::const_conditions,
implied_const_bounds: predicates_of::implied_const_bounds,
type_param_predicates: predicates_of::type_param_predicates,
trait_def,
adt_def,

View File

@ -40,7 +40,16 @@ fn associated_type_bounds<'tcx>(
let mut bounds = Bounds::default();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
match filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
}
// `ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
}
let trait_def_id = tcx.local_parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
@ -109,10 +118,19 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
} else {
// Only collect *self* type bounds if the filter is for self.
match filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
PredicateFilter::All => {}
PredicateFilter::SelfOnly => {
return None;
}
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
PredicateFilter::SelfThatDefines(_)
| PredicateFilter::SelfConstIfConst
| PredicateFilter::SelfAndAssociatedTypeBounds
| PredicateFilter::ConstIfConst => {
unreachable!(
"invalid predicate filter for \
`remap_gat_vars_and_recurse_into_nested_projections`"
)
}
}
clause_ty = alias_ty.self_ty();
@ -308,7 +326,17 @@ fn opaque_type_bounds<'tcx>(
let mut bounds = Bounds::default();
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
// Opaque types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
match filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
}
//`ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
}
debug!(?bounds);
tcx.arena.alloc_from_iter(bounds.clauses(tcx))

View File

@ -12,6 +12,7 @@ use rustc_span::symbol::Ident;
use rustc_span::{DUMMY_SP, Span};
use tracing::{debug, instrument, trace};
use super::item_bounds::explicit_item_bounds_with_filter;
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
@ -685,29 +686,76 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
assert_eq!(
trait_predicate.self_ty(),
ty,
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
"expected `Self` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::Projection(projection_predicate) => {
assert_eq!(
projection_predicate.self_ty(),
ty,
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
"expected `Self` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::TypeOutlives(outlives_predicate) => {
assert_eq!(
outlives_predicate.0, ty,
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
"expected `Self` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::RegionOutlives(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => {
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::HostEffect(..) => {
bug!(
"unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
"unexpected non-`Self` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
}
}
}
PredicateFilter::ConstIfConst => {
for (clause, _) in bounds {
match clause.kind().skip_binder() {
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
trait_ref: _,
host: ty::HostPolarity::Maybe,
}) => {}
_ => {
bug!(
"unexpected non-`HostEffect` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
}
}
}
PredicateFilter::SelfConstIfConst => {
for (clause, _) in bounds {
match clause.kind().skip_binder() {
ty::ClauseKind::HostEffect(pred) => {
assert_eq!(
pred.host,
ty::HostPolarity::Maybe,
"expected `~const` predicate when computing `{filter:?}` \
implied bounds: {clause:?}",
);
assert_eq!(
pred.trait_ref.self_ty(),
ty,
"expected `Self` predicate when computing `{filter:?}` \
implied bounds: {clause:?}"
);
}
_ => {
bug!(
"unexpected non-`HostEffect` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
}
@ -829,3 +877,184 @@ impl<'tcx> ItemCtxt<'tcx> {
bounds.clauses(self.tcx).collect()
}
}
/// Compute the conditions that need to hold for a conditionally-const item to be const.
/// That is, compute the set of `~const` where clauses for a given item.
///
/// This query also computes the `~const` where clauses for associated types, which are
/// not "const", but which have item bounds which may be `~const`. These must hold for
/// the `~const` item bound to hold.
pub(super) fn const_conditions<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> ty::ConstConditions<'tcx> {
// This logic is spaghetti, and should be cleaned up. The current methods that are
// defined to deal with constness are very unintuitive.
if tcx.is_const_fn_raw(def_id.to_def_id()) {
// Ok, const fn or method in const trait.
} else {
match tcx.def_kind(def_id) {
DefKind::Trait => {
if !tcx.is_const_trait(def_id.to_def_id()) {
return Default::default();
}
}
DefKind::Impl { .. } => {
// FIXME(effects): Should be using a dedicated function to
// test if this is a const trait impl.
if tcx.constness(def_id) != hir::Constness::Const {
return Default::default();
}
}
DefKind::AssocTy | DefKind::AssocFn => {
let parent_def_id = tcx.local_parent(def_id).to_def_id();
match tcx.associated_item(def_id).container {
ty::AssocItemContainer::TraitContainer => {
if !tcx.is_const_trait(parent_def_id) {
return Default::default();
}
}
ty::AssocItemContainer::ImplContainer => {
// FIXME(effects): Should be using a dedicated function to
// test if this is a const trait impl.
if tcx.constness(parent_def_id) != hir::Constness::Const {
return Default::default();
}
}
}
}
DefKind::Closure | DefKind::OpaqueTy => {
// Closures and RPITs will eventually have const conditions
// for `~const` bounds.
return Default::default();
}
_ => return Default::default(),
}
}
let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
{
Node::Item(item) => match item.kind {
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
hir::ItemKind::Fn(_, generics, _) => (generics, None, false),
hir::ItemKind::Trait(_, _, generics, supertraits, _) => {
(generics, Some((item.owner_id.def_id, supertraits)), false)
}
_ => return Default::default(),
},
// While associated types are not really const, we do allow them to have `~const`
// bounds and where clauses. `const_conditions` is responsible for gathering
// these up so we can check them in `compare_type_predicate_entailment`, and
// in `HostEffect` goal computation.
Node::TraitItem(item) => match item.kind {
hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
(item.generics, None, true)
}
_ => return Default::default(),
},
Node::ImplItem(item) => match item.kind {
hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => (item.generics, None, true),
_ => return Default::default(),
},
_ => return Default::default(),
};
let icx = ItemCtxt::new(tcx, def_id);
let mut bounds = Bounds::default();
for pred in generics.predicates {
match pred {
hir::WherePredicate::BoundPredicate(bound_pred) => {
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
icx.lowerer().lower_bounds(
ty,
bound_pred.bounds.iter(),
&mut bounds,
bound_vars,
PredicateFilter::ConstIfConst,
);
}
_ => {}
}
}
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
bounds.push_const_bound(
tcx,
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())),
ty::HostPolarity::Maybe,
DUMMY_SP,
);
icx.lowerer().lower_bounds(
tcx.types.self_param,
supertraits.into_iter(),
&mut bounds,
ty::List::empty(),
PredicateFilter::ConstIfConst,
);
}
ty::ConstConditions {
parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
predicates: tcx.arena.alloc_from_iter(bounds.clauses(tcx).map(|(clause, span)| {
(
clause.kind().map_bound(|clause| match clause {
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
trait_ref,
host: ty::HostPolarity::Maybe,
}) => trait_ref,
_ => bug!("converted {clause:?}"),
}),
span,
)
})),
}
}
pub(super) fn implied_const_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
let bounds = match tcx.hir_node_by_def_id(def_id) {
Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
if !tcx.is_const_trait(def_id.to_def_id()) {
return ty::EarlyBinder::bind(&[]);
}
implied_predicates_with_filter(
tcx,
def_id.to_def_id(),
PredicateFilter::SelfConstIfConst,
)
}
Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. }) => {
if !tcx.is_const_trait(tcx.local_parent(def_id).to_def_id()) {
return ty::EarlyBinder::bind(&[]);
}
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
}
Node::OpaqueTy(..) => {
// We should eventually collect the `~const` bounds on opaques.
return ty::EarlyBinder::bind(&[]);
}
_ => return ty::EarlyBinder::bind(&[]),
};
bounds.map_bound(|bounds| {
&*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
(
clause.kind().map_bound(|clause| match clause {
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
trait_ref,
host: ty::HostPolarity::Maybe,
}) => trait_ref,
_ => bug!("converted {clause:?}"),
}),
span,
)
}))
})
}

View File

@ -154,7 +154,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
for hir_bound in hir_bounds {
// In order to avoid cycles, when we're lowering `SelfThatDefines`,
// we skip over any traits that don't define the given associated type.
if let PredicateFilter::SelfThatDefines(assoc_name) = predicate_filter {
if let Some(trait_ref) = hir_bound.trait_ref()
&& let Some(trait_did) = trait_ref.trait_def_id()
@ -193,6 +192,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
}
hir::GenericBound::Outlives(lifetime) => {
// `ConstIfConst` is only interested in `~const` bounds.
if matches!(
predicate_filter,
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst
) {
continue;
}
let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
bounds.push_region_bound(
self.tcx(),
@ -392,21 +399,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
},
);
bounds.push_projection_bound(
tcx,
projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
projection_term,
term,
}),
constraint.span,
);
match predicate_filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
bounds.push_projection_bound(
tcx,
projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
projection_term,
term,
}),
constraint.span,
);
}
// `ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
}
}
// Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
// to a bound involving a projection: `<T as Iterator>::Item: Debug`.
hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
match predicate_filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {}
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
PredicateFilter::All
| PredicateFilter::SelfAndAssociatedTypeBounds
| PredicateFilter::ConstIfConst => {
let projection_ty = projection_term
.map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
// Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
@ -421,6 +438,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
predicate_filter,
);
}
PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_)
| PredicateFilter::SelfConstIfConst => {}
}
}
}

View File

@ -78,7 +78,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::ClauseKind::RegionOutlives(_)
| ty::ClauseKind::ConstArgHasType(..)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => {
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::HostEffect(..) => {
span_bug!(span, "did not expect {pred} clause in object bounds");
}
}

View File

@ -81,6 +81,12 @@ pub enum PredicateFilter {
/// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
/// and `<Self as Tr>::A: B`.
SelfAndAssociatedTypeBounds,
/// Filter only the `~const` bounds, which are lowered into `HostEffect` clauses.
ConstIfConst,
/// Filter only the `~const` bounds which are *also* in the supertrait position.
SelfConstIfConst,
}
#[derive(Debug)]
@ -693,8 +699,49 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bound_vars,
);
debug!(?poly_trait_ref);
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
match predicate_filter {
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(..)
| PredicateFilter::SelfAndAssociatedTypeBounds => {
debug!(?poly_trait_ref);
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
match constness {
Some(ty::BoundConstness::Const) => {
if polarity == ty::PredicatePolarity::Positive {
bounds.push_const_bound(
tcx,
poly_trait_ref,
ty::HostPolarity::Const,
span,
);
}
}
Some(ty::BoundConstness::ConstIfConst) => {
// We don't emit a const bound here, since that would mean that we
// unconditionally need to prove a `HostEffect` predicate, even when
// the predicates are being instantiated in a non-const context. This
// is instead handled in the `const_conditions` query.
}
None => {}
}
}
// On the flip side, when filtering `ConstIfConst` bounds, we only need to convert
// `~const` bounds. All other predicates are handled in their respective queries.
//
// Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering
// here because we only call this on self bounds, and deal with the recursive case
// in `lower_assoc_item_constraint`.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness {
Some(ty::BoundConstness::ConstIfConst) => {
if polarity == ty::PredicatePolarity::Positive {
bounds.push_const_bound(tcx, poly_trait_ref, ty::HostPolarity::Maybe, span);
}
}
None | Some(ty::BoundConstness::Const) => {}
},
}
let mut dup_constraints = FxIndexMap::default();
for constraint in trait_segment.args().constraints {

View File

@ -530,6 +530,7 @@ fn trait_specialization_kind<'tcx>(
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(..)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(..) => None,
| ty::ClauseKind::ConstEvaluatable(..)
| ty::ClauseKind::HostEffect(..) => None,
}
}

View File

@ -53,7 +53,8 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => {}
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::HostEffect(..) => {}
}
}

View File

@ -836,14 +836,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_sig.output()
}
#[tracing::instrument(level = "debug", skip(self, _span))]
#[tracing::instrument(level = "debug", skip(self, span))]
pub(super) fn enforce_context_effects(
&self,
_span: Span,
_callee_did: DefId,
_callee_args: GenericArgsRef<'tcx>,
span: Span,
callee_did: DefId,
callee_args: GenericArgsRef<'tcx>,
) {
todo!()
// FIXME(effects): We should be enforcing these effects unconditionally.
// This can be done as soon as we convert the standard library back to
// using const traits, since if we were to enforce these conditions now,
// we'd fail on basically every builtin trait call (i.e. `1 + 2`).
if !self.tcx.features().effects() {
return;
}
let host = match self.tcx.hir().body_const_context(self.body_id) {
Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {
ty::HostPolarity::Const
}
Some(hir::ConstContext::ConstFn) => ty::HostPolarity::Maybe,
None => return,
};
// FIXME(effects): Should this be `is_const_fn_raw`? It depends on if we move
// const stability checking here too, I guess.
if self.tcx.is_const_fn(callee_did)
|| self
.tcx
.trait_of_item(callee_did)
.is_some_and(|def_id| self.tcx.is_const_trait(def_id))
{
let q = self.tcx.const_conditions(callee_did);
// FIXME(effects): Use this span with a better cause code.
for (cond, _) in q.instantiate(self.tcx, callee_args) {
self.register_predicate(Obligation::new(
self.tcx,
self.misc(span),
self.param_env,
cond.to_host_effect_clause(self.tcx, host),
));
}
} else {
// FIXME(effects): This should eventually be caught here.
// For now, though, we defer some const checking to MIR.
}
}
fn confirm_overloaded_call(

View File

@ -52,6 +52,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
| ty::PredicateKind::Ambiguous => false,
}
}

View File

@ -813,7 +813,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => None,
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::HostEffect(..) => None,
}
});

View File

@ -24,19 +24,9 @@ pub fn explicit_outlives_bounds<'tcx>(
param_env
.caller_bounds()
.into_iter()
.map(ty::Clause::kind)
.filter_map(ty::Clause::as_region_outlives_clause)
.filter_map(ty::Binder::no_bound_vars)
.filter_map(move |kind| match kind {
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
Some(OutlivesBound::RegionSubRegion(r_b, r_a))
}
ty::ClauseKind::Trait(_)
| ty::ClauseKind::TypeOutlives(_)
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => None,
})
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a))
}
impl<'tcx> InferCtxt<'tcx> {

View File

@ -1554,7 +1554,9 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
// Ignore bounds that a user can't type
| ClauseKind::WellFormed(..)
// FIXME(generic_const_exprs): `ConstEvaluatable` can be written
| ClauseKind::ConstEvaluatable(..) => continue,
| ClauseKind::ConstEvaluatable(..)
// Users don't write this directly, only via another trait ref.
| ty::ClauseKind::HostEffect(..) => continue,
};
if predicate.is_global() {
cx.emit_span_lint(TRIVIAL_BOUNDS, span, BuiltinTrivialBounds {

View File

@ -275,6 +275,8 @@ provide! { tcx, def_id, other, cdata,
impl_parent => { table }
defaultness => { table_direct }
constness => { table_direct }
const_conditions => { table }
implied_const_bounds => { table_defaulted_array }
coerce_unsized_info => {
Ok(cdata
.root

View File

@ -1423,6 +1423,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let g = tcx.generics_of(def_id);
record!(self.tables.generics_of[def_id] <- g);
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
record!(self.tables.const_conditions[def_id] <- self.tcx.const_conditions(def_id));
let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
@ -1456,7 +1457,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.tcx.explicit_super_predicates_of(def_id).skip_binder());
record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <-
self.tcx.explicit_implied_predicates_of(def_id).skip_binder());
record_defaulted_array!(self.tables.implied_const_bounds[def_id]
<- self.tcx.implied_const_bounds(def_id).skip_binder());
let module_children = self.tcx.module_children_local(local_id);
record_array!(self.tables.module_children_non_reexports[def_id] <-
module_children.iter().map(|child| child.res.def_id().index));
@ -1467,6 +1469,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.tcx.explicit_super_predicates_of(def_id).skip_binder());
record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <-
self.tcx.explicit_implied_predicates_of(def_id).skip_binder());
record_defaulted_array!(self.tables.implied_const_bounds[def_id]
<- self.tcx.implied_const_bounds(def_id).skip_binder());
}
if let DefKind::Trait | DefKind::Impl { .. } = def_kind {
let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
@ -1649,6 +1653,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if let ty::AssocKind::Type = item.kind {
self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_super_predicates(def_id);
record_defaulted_array!(self.tables.implied_const_bounds[def_id]
<- self.tcx.implied_const_bounds(def_id).skip_binder());
}
}
AssocItemContainer::ImplContainer => {

View File

@ -392,6 +392,7 @@ define_tables! {
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
explicit_super_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
explicit_implied_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
implied_const_bounds: Table<DefIndex, LazyArray<(ty::PolyTraitRef<'static>, Span)>>,
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
@ -435,6 +436,7 @@ define_tables! {
thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::Const<'static>>>>,
impl_parent: Table<DefIndex, RawDefId>,
constness: Table<DefIndex, hir::Constness>,
const_conditions: Table<DefIndex, LazyValue<ty::ConstConditions<'static>>>,
defaultness: Table<DefIndex, hir::Defaultness>,
// FIXME(eddyb) perhaps compute this on the fly if cheap enough?
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,

View File

@ -370,6 +370,7 @@ tcx_lifetime! {
rustc_middle::ty::FnSig,
rustc_middle::ty::GenericArg,
rustc_middle::ty::GenericPredicates,
rustc_middle::ty::ConstConditions,
rustc_middle::ty::inhabitedness::InhabitedPredicate,
rustc_middle::ty::Instance,
rustc_middle::ty::InstanceKind,

View File

@ -683,6 +683,24 @@ rustc_queries! {
}
}
query const_conditions(
key: DefId
) -> ty::ConstConditions<'tcx> {
desc { |tcx| "computing the conditions for `{}` to be considered const",
tcx.def_path_str(key)
}
separate_provide_extern
}
query implied_const_bounds(
key: DefId
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
desc { |tcx| "computing the implied `~const` bounds for `{}`",
tcx.def_path_str(key)
}
separate_provide_extern
}
/// To avoid cycles within the predicates of a single item we compute
/// per-type-parameter predicates for resolving `T::AssocTy`.
query type_param_predicates(

View File

@ -386,6 +386,17 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Claus
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
for [(ty::PolyTraitRef<'tcx>, Span)]
{
fn decode(decoder: &mut D) -> &'tcx Self {
decoder
.interner()
.arena
.alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
for ty::List<ty::BoundVariableKind>
{

View File

@ -78,10 +78,10 @@ use crate::traits::solve::{
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs,
GenericArgsRef, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst,
ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
Visibility,
GenericArgsRef, GenericParamDefKind, HostPolarity, ImplPolarity, List, ListWithCachedTypeInfo,
ParamConst, ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate,
PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
TyKind, TyVid, Visibility,
};
#[allow(rustc::usage_of_ty_tykind)]
@ -383,6 +383,28 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied())
}
fn is_const_impl(self, def_id: DefId) -> bool {
self.constness(def_id) == hir::Constness::Const
}
fn const_conditions(
self,
def_id: DefId,
) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Binder<'tcx, ty::TraitRef<'tcx>>>> {
ty::EarlyBinder::bind(
self.const_conditions(def_id).instantiate_identity(self).into_iter().map(|(c, _)| c),
)
}
fn implied_const_bounds(
self,
def_id: DefId,
) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Binder<'tcx, ty::TraitRef<'tcx>>>> {
ty::EarlyBinder::bind(
self.implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c),
)
}
fn has_target_features(self, def_id: DefId) -> bool {
!self.codegen_fn_attrs(def_id).target_features.is_empty()
}
@ -2189,7 +2211,7 @@ macro_rules! nop_slice_lift {
nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
TrivialLiftImpls! {
ImplPolarity, PredicatePolarity, Promoted
ImplPolarity, PredicatePolarity, Promoted, HostPolarity,
}
macro_rules! sty_debug_print {

View File

@ -265,6 +265,12 @@ impl FlagComputation {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
self.add_args(trait_pred.trait_ref.args);
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
trait_ref,
host: _,
})) => {
self.add_args(trait_ref.args);
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
a,
b,

View File

@ -422,3 +422,73 @@ impl<'tcx> GenericPredicates<'tcx> {
instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s));
}
}
/// `~const` bounds for a given item. This is represented using a struct much like
/// `GenericPredicates`, where you can either choose to only instantiate the "own"
/// bounds or all of the bounds including those from the parent. This distinction
/// is necessary for code like `compare_method_predicate_entailment`.
#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ConstConditions<'tcx> {
pub parent: Option<DefId>,
pub predicates: &'tcx [(ty::PolyTraitRef<'tcx>, Span)],
}
impl<'tcx> ConstConditions<'tcx> {
pub fn instantiate(
self,
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
) -> Vec<(ty::PolyTraitRef<'tcx>, Span)> {
let mut instantiated = vec![];
self.instantiate_into(tcx, &mut instantiated, args);
instantiated
}
pub fn instantiate_own(
self,
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
{
EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args)
}
pub fn instantiate_own_identity(
self,
) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
{
EarlyBinder::bind(self.predicates).iter_identity_copied()
}
#[instrument(level = "debug", skip(self, tcx))]
fn instantiate_into(
self,
tcx: TyCtxt<'tcx>,
instantiated: &mut Vec<(ty::PolyTraitRef<'tcx>, Span)>,
args: GenericArgsRef<'tcx>,
) {
if let Some(def_id) = self.parent {
tcx.const_conditions(def_id).instantiate_into(tcx, instantiated, args);
}
instantiated.extend(
self.predicates.iter().map(|&(p, s)| (EarlyBinder::bind(p).instantiate(tcx, args), s)),
);
}
pub fn instantiate_identity(self, tcx: TyCtxt<'tcx>) -> Vec<(ty::PolyTraitRef<'tcx>, Span)> {
let mut instantiated = vec![];
self.instantiate_identity_into(tcx, &mut instantiated);
instantiated
}
fn instantiate_identity_into(
self,
tcx: TyCtxt<'tcx>,
instantiated: &mut Vec<(ty::PolyTraitRef<'tcx>, Span)>,
) {
if let Some(def_id) = self.parent {
tcx.const_conditions(def_id).instantiate_identity_into(tcx, instantiated);
}
instantiated.extend(self.predicates.iter().copied());
}
}

View File

@ -84,12 +84,13 @@ pub use self::parameterized::ParameterizedOverTcx;
pub use self::pattern::{Pattern, PatternKind};
pub use self::predicate::{
AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate,
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo,
OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
TraitPredicate, TraitRef, TypeOutlivesPredicate,
ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef,
HostEffectPredicate, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef,
TypeOutlivesPredicate,
};
pub use self::region::BoundRegionKind::*;
pub use self::region::{

View File

@ -132,6 +132,7 @@ parameterized_over_tcx! {
ty::Ty,
ty::FnSig,
ty::GenericPredicates,
ty::ConstConditions,
ty::TraitRef,
ty::Const,
ty::Predicate,

View File

@ -19,6 +19,7 @@ pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
pub type HostEffectPredicate<'tcx> = ir::HostEffectPredicate<TyCtxt<'tcx>>;
pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
@ -143,6 +144,7 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::AliasRelate(..)
| PredicateKind::NormalizesTo(..) => false,
PredicateKind::Clause(ClauseKind::Trait(_))
| PredicateKind::Clause(ClauseKind::HostEffect(..))
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
| PredicateKind::Clause(ClauseKind::Projection(_))
@ -644,6 +646,7 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(ClauseKind::Projection(..))
| PredicateKind::Clause(ClauseKind::HostEffect(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::NormalizesTo(..)
| PredicateKind::AliasRelate(..)
@ -664,6 +667,7 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(ClauseKind::Trait(..))
| PredicateKind::Clause(ClauseKind::HostEffect(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::NormalizesTo(..)
| PredicateKind::AliasRelate(..)

View File

@ -3075,6 +3075,15 @@ define_print! {
p!(print(self.trait_ref.print_trait_sugared()))
}
ty::HostEffectPredicate<'tcx> {
let constness = match self.host {
ty::HostPolarity::Const => { "const" }
ty::HostPolarity::Maybe => { "~const" }
};
p!(print(self.trait_ref.self_ty()), ": {constness} ");
p!(print(self.trait_ref.print_trait_sugared()))
}
ty::TypeAndMut<'tcx> {
p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
}
@ -3087,6 +3096,7 @@ define_print! {
ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)),
ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)),
ty::ClauseKind::Projection(predicate) => p!(print(predicate)),
ty::ClauseKind::HostEffect(predicate) => p!(print(predicate)),
ty::ClauseKind::ConstArgHasType(ct, ty) => {
p!("the constant `", print(ct), "` has type `", print(ty), "`")
},

View File

@ -0,0 +1,296 @@
//! Dealing with host effect goals, i.e. enforcing the constness in
//! `T: const Trait` or `T: ~const Trait`.
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner};
use tracing::instrument;
use super::assembly::Candidate;
use crate::delegate::SolverDelegate;
use crate::solve::assembly::{self};
use crate::solve::{
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution,
QueryResult,
};
impl<D, I> assembly::GoalKind<D> for ty::HostEffectPredicate<I>
where
D: SolverDelegate<Interner = I>,
I: Interner,
{
fn self_ty(self) -> I::Ty {
self.self_ty()
}
fn trait_ref(self, _: I) -> ty::TraitRef<I> {
self.trait_ref
}
fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
self.with_self_ty(cx, self_ty)
}
fn trait_def_id(self, _: I) -> I::DefId {
self.def_id()
}
fn probe_and_match_goal_against_assumption(
ecx: &mut EvalCtxt<'_, D>,
source: rustc_type_ir::solve::CandidateSource<I>,
goal: Goal<I, Self>,
assumption: <I as Interner>::Clause,
then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
) -> Result<Candidate<I>, NoSolution> {
if let Some(host_clause) = assumption.as_host_effect_clause() {
if host_clause.def_id() == goal.predicate.def_id()
&& host_clause.host().satisfies(goal.predicate.host)
{
if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
goal.predicate.trait_ref.args,
host_clause.skip_binder().trait_ref.args,
) {
return Err(NoSolution);
}
ecx.probe_trait_candidate(source).enter(|ecx| {
let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause);
ecx.eq(
goal.param_env,
goal.predicate.trait_ref,
assumption_trait_pred.trait_ref,
)?;
then(ecx)
})
} else {
Err(NoSolution)
}
} else {
Err(NoSolution)
}
}
fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
impl_def_id: <I as Interner>::DefId,
) -> Result<Candidate<I>, NoSolution> {
let cx = ecx.cx();
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
{
return Err(NoSolution);
}
let impl_polarity = cx.impl_polarity(impl_def_id);
match impl_polarity {
ty::ImplPolarity::Negative => return Err(NoSolution),
ty::ImplPolarity::Reservation => {
unimplemented!("reservation impl for const trait: {:?}", goal)
}
ty::ImplPolarity::Positive => {}
};
if !cx.is_const_impl(impl_def_id) {
return Err(NoSolution);
}
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id);
ecx.record_impl_args(impl_args);
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args);
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
let where_clause_bounds = cx
.predicates_of(impl_def_id)
.iter_instantiated(cx, impl_args)
.map(|pred| goal.with(cx, pred));
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
// For this impl to be `const`, we need to check its `~const` bounds too.
let const_conditions = cx
.const_conditions(impl_def_id)
.iter_instantiated(cx, impl_args)
.map(|bound_trait_ref| {
goal.with(cx, bound_trait_ref.to_host_effect_clause(cx, goal.predicate.host))
});
ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}
fn consider_error_guaranteed_candidate(
ecx: &mut EvalCtxt<'_, D>,
_guar: <I as Interner>::ErrorGuaranteed,
) -> Result<Candidate<I>, NoSolution> {
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
}
fn consider_auto_trait_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("auto traits are never const")
}
fn consider_trait_alias_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("trait aliases are never const")
}
fn consider_builtin_sized_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Sized is never const")
}
fn consider_builtin_copy_clone_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
todo!("Copy/Clone is not yet const")
}
fn consider_builtin_pointer_like_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("PointerLike is not const")
}
fn consider_builtin_fn_ptr_trait_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
todo!("Fn* are not yet const")
}
fn consider_builtin_fn_trait_candidates(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_kind: rustc_type_ir::ClosureKind,
) -> Result<Candidate<I>, NoSolution> {
todo!("Fn* are not yet const")
}
fn consider_builtin_async_fn_trait_candidates(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_kind: rustc_type_ir::ClosureKind,
) -> Result<Candidate<I>, NoSolution> {
todo!("AsyncFn* are not yet const")
}
fn consider_builtin_async_fn_kind_helper_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("AsyncFnKindHelper is not const")
}
fn consider_builtin_tuple_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Tuple trait is not const")
}
fn consider_builtin_pointee_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Pointee is not const")
}
fn consider_builtin_future_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Future is not const")
}
fn consider_builtin_iterator_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
todo!("Iterator is not yet const")
}
fn consider_builtin_fused_iterator_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("FusedIterator is not const")
}
fn consider_builtin_async_iterator_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("AsyncIterator is not const")
}
fn consider_builtin_coroutine_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Coroutine is not const")
}
fn consider_builtin_discriminant_kind_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("DiscriminantKind is not const")
}
fn consider_builtin_async_destruct_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("AsyncDestruct is not const")
}
fn consider_builtin_destruct_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Destruct is not const")
}
fn consider_builtin_transmute_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("TransmuteFrom is not const")
}
fn consider_structural_builtin_unsize_candidates(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Vec<Candidate<I>> {
unreachable!("Unsize is not const")
}
}
impl<D, I> EvalCtxt<'_, D>
where
D: SolverDelegate<Interner = I>,
I: Interner,
{
#[instrument(level = "trace", skip(self))]
pub(super) fn compute_host_effect_goal(
&mut self,
goal: Goal<I, ty::HostEffectPredicate<I>>,
) -> QueryResult<I> {
let candidates = self.assemble_and_evaluate_candidates(goal);
self.merge_candidates(candidates)
}
}

View File

@ -443,6 +443,9 @@ where
ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
self.compute_trait_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
self.compute_host_effect_goal(Goal { param_env, predicate })
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
self.compute_projection_goal(Goal { param_env, predicate })
}

View File

@ -13,6 +13,7 @@
mod alias_relate;
mod assembly;
mod effect_goals;
mod eval_ctxt;
pub mod inspect;
mod normalizes_to;

View File

@ -137,6 +137,10 @@ where
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
self.visit_trait(trait_ref)
}
ty::ClauseKind::HostEffect(pred) => {
try_visit!(self.visit_trait(pred.trait_ref));
pred.host.visit_with(self)
}
ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_term: projection_ty,
term,

View File

@ -689,6 +689,9 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
ClauseKind::ConstEvaluatable(const_) => {
stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
}
ClauseKind::HostEffect(..) => {
todo!()
}
}
}
}

View File

@ -156,8 +156,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
(leaf_trait_predicate, &obligation)
};
let (main_trait_predicate, leaf_trait_predicate, predicate_constness) = self.get_effects_trait_pred_override(main_trait_predicate, leaf_trait_predicate, span);
let main_trait_ref = main_trait_predicate.to_poly_trait_ref();
let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref();
@ -228,7 +226,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let err_msg = self.get_standard_error_message(
main_trait_predicate,
message,
predicate_constness,
None,
append_const_msg,
post_message,
);
@ -289,13 +287,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
}
if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Drop)
&& matches!(predicate_constness, Some(ty::BoundConstness::ConstIfConst | ty::BoundConstness::Const))
{
err.note("`~const Drop` was renamed to `~const Destruct`");
err.note("See <https://github.com/rust-lang/rust/pull/94901> for more details");
}
let explanation = get_explanation_based_on_obligation(
self.tcx,
&obligation,
@ -541,6 +532,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
err
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
// FIXME(effects): We should recompute the predicate with `~const`
// if it's `const`, and if it holds, explain that this bound only
// *conditionally* holds. If that fails, we should also do selection
// to drill this down to an impl or built-in source, so we can
// point at it and explain that while the trait *is* implemented,
// that implementation is not const.
let err_msg = self.get_standard_error_message(
bound_predicate.rebind(ty::TraitPredicate {
trait_ref: predicate.trait_ref,
polarity: ty::PredicatePolarity::Positive,
}),
None,
Some(match predicate.host {
ty::HostPolarity::Maybe => ty::BoundConstness::ConstIfConst,
ty::HostPolarity::Const => ty::BoundConstness::Const,
}),
None,
String::new(),
);
struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg)
}
ty::PredicateKind::Subtype(predicate) => {
// Errors for Subtype predicates show up as
// `FulfillmentErrorCode::SubtypeError`,
@ -2374,16 +2388,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
}
// FIXME(effects): Remove this.
fn get_effects_trait_pred_override(
&self,
p: ty::PolyTraitPredicate<'tcx>,
leaf: ty::PolyTraitPredicate<'tcx>,
_span: Span,
) -> (ty::PolyTraitPredicate<'tcx>, ty::PolyTraitPredicate<'tcx>, ty::BoundConstness) {
(p, leaf, ty::BoundConstness::NotConst)
}
fn add_tuple_trait_message(
&self,
obligation_cause_code: &ObligationCauseCode<'tcx>,

View File

@ -806,7 +806,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
| ty::PredicateKind::Subtype(..)
// FIXME(generic_const_exprs): you can absolutely add this as a where clauses
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::Coerce(..) => {}
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {}
ty::PredicateKind::Ambiguous => return false,
};
}

View File

@ -245,6 +245,7 @@ fn predicate_references_self<'tcx>(
| ty::ClauseKind::RegionOutlives(..)
// FIXME(generic_const_exprs): this can mention `Self`
| ty::ClauseKind::ConstEvaluatable(..)
| ty::ClauseKind::HostEffect(..)
=> None,
}
}
@ -284,7 +285,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => false,
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::HostEffect(..) => false,
})
}

View File

@ -372,7 +372,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..) => {
| ty::PredicateKind::ConstEquate(..)
// FIXME(effects): We may need to do this using the higher-ranked
// pred instead of just instantiating it with placeholders b/c of
// higher-ranked implied bound issues in the old solver.
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
let mut obligations = PredicateObligations::with_capacity(1);
obligations.push(obligation.with(infcx.tcx, pred));
@ -398,6 +402,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
)
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
ProcessResult::Changed(Default::default())
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
if infcx.considering_regions {
infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));

View File

@ -96,6 +96,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
// FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
// if we ever support that
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
@ -200,6 +201,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
// FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
// if we ever support that
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)

View File

@ -645,6 +645,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
// FIXME(effects): It should be relatively straightforward to implement
// old trait solver support for `HostEffect` bounds; or at least basic
// support for them.
todo!()
}
ty::PredicateKind::Subtype(p) => {
let p = bound_predicate.rebind(p);
// Does this code ever run?

View File

@ -170,6 +170,10 @@ pub fn clause_obligations<'tcx>(
ty::ClauseKind::Trait(t) => {
wf.compute_trait_pred(t, Elaborate::None);
}
ty::ClauseKind::HostEffect(..) => {
// Technically the well-formedness of this predicate is implied by
// the corresponding trait predicate it should've been generated beside.
}
ty::ClauseKind::RegionOutlives(..) => {}
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
wf.compute(ty.into());
@ -1021,6 +1025,7 @@ pub(crate) fn required_region_bounds<'tcx>(
}
}
ty::ClauseKind::Trait(_)
| ty::ClauseKind::HostEffect(..)
| ty::ClauseKind::RegionOutlives(_)
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(_, _)

View File

@ -55,6 +55,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false,
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::NormalizesTo(..)
| ty::PredicateKind::AliasRelate(..)

View File

@ -150,6 +150,15 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
});
}
// We extend the param-env of our item with the const conditions of the item,
// since we're allowed to assume `~const` bounds hold within the item itself.
predicates.extend(
tcx.const_conditions(def_id)
.instantiate_identity(tcx)
.into_iter()
.map(|(trait_ref, _)| trait_ref.to_host_effect_clause(tcx, ty::HostPolarity::Maybe)),
);
let local_did = def_id.as_local();
let unnormalized_env =

View File

@ -155,6 +155,16 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
),
};
}
// `T: ~const Trait` implies `T: ~const Supertrait`.
ty::ClauseKind::HostEffect(data) => self.extend_deduped(
cx.implied_const_bounds(data.def_id()).iter_identity().map(|trait_ref| {
elaboratable.child(
trait_ref
.to_host_effect_clause(cx, data.host)
.instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
)
}),
),
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
// We know that `T: 'a` for some type `T`. We can
// often elaborate this. For example, if we know that

View File

@ -468,6 +468,14 @@ pub trait Clause<I: Interner<Clause = Self>>:
.transpose()
}
fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
self.kind()
.map_bound(
|clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
)
.transpose()
}
fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
self.kind()
.map_bound(

View File

@ -24,6 +24,7 @@ pub trait Interner:
+ IrPrint<ty::AliasTerm<Self>>
+ IrPrint<ty::TraitRef<Self>>
+ IrPrint<ty::TraitPredicate<Self>>
+ IrPrint<ty::HostEffectPredicate<Self>>
+ IrPrint<ty::ExistentialTraitRef<Self>>
+ IrPrint<ty::ExistentialProjection<Self>>
+ IrPrint<ty::ProjectionPredicate<Self>>
@ -228,6 +229,16 @@ pub trait Interner:
def_id: Self::DefId,
) -> ty::EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>>;
fn is_const_impl(self, def_id: Self::DefId) -> bool;
fn const_conditions(
self,
def_id: Self::DefId,
) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
fn implied_const_bounds(
self,
def_id: Self::DefId,
) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
fn has_target_features(self, def_id: Self::DefId) -> bool;
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;

View File

@ -2,8 +2,8 @@ use std::fmt;
use crate::{
AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
Interner, NormalizesTo, OutlivesPredicate, ProjectionPredicate, SubtypePredicate,
TraitPredicate, TraitRef,
HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, ProjectionPredicate,
SubtypePredicate, TraitPredicate, TraitRef,
};
pub trait IrPrint<T> {
@ -53,6 +53,7 @@ define_display_via_print!(
NormalizesTo,
SubtypePredicate,
CoercePredicate,
HostEffectPredicate,
AliasTy,
AliasTerm,
FnSig,

View File

@ -111,6 +111,13 @@ impl<I: Interner> ty::Binder<I, TraitRef<I>> {
pub fn def_id(&self) -> I::DefId {
self.skip_binder().def_id
}
pub fn to_host_effect_clause(self, cx: I, host: HostPolarity) -> I::Clause {
self.map_bound(|trait_ref| {
ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, host })
})
.upcast(cx)
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
@ -745,6 +752,64 @@ impl<I: Interner> fmt::Debug for NormalizesTo<I> {
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub struct HostEffectPredicate<I: Interner> {
pub trait_ref: ty::TraitRef<I>,
pub host: HostPolarity,
}
impl<I: Interner> HostEffectPredicate<I> {
pub fn self_ty(self) -> I::Ty {
self.trait_ref.self_ty()
}
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), ..self }
}
pub fn def_id(self) -> I::DefId {
self.trait_ref.def_id
}
}
impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
pub fn def_id(self) -> I::DefId {
// Ok to skip binder since trait `DefId` does not care about regions.
self.skip_binder().def_id()
}
pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
self.map_bound(|trait_ref| trait_ref.self_ty())
}
#[inline]
pub fn host(self) -> HostPolarity {
self.skip_binder().host
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum HostPolarity {
/// May be called in const environments if the callee is const.
Maybe,
/// Always allowed to be called in const environments.
Const,
}
impl HostPolarity {
pub fn satisfies(self, goal: HostPolarity) -> bool {
match (self, goal) {
(HostPolarity::Const, HostPolarity::Const | HostPolarity::Maybe) => true,
(HostPolarity::Maybe, HostPolarity::Maybe) => true,
(HostPolarity::Maybe, HostPolarity::Const) => false,
}
}
}
/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
/// whether the `a` type is the type that we should label as "expected" when
/// presenting user diagnostics.

View File

@ -37,6 +37,12 @@ pub enum ClauseKind<I: Interner> {
/// Constant initializer must evaluate successfully.
ConstEvaluatable(I::Const),
/// Enforces the constness of the predicate we're calling. Like a projection
/// goal from a where clause, it's always going to be paired with a
/// corresponding trait clause; this just enforces the *constness* of that
/// implementation.
HostEffect(ty::HostEffectPredicate<I>),
}
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
@ -110,6 +116,7 @@ impl<I: Interner> fmt::Debug for ClauseKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ClauseKind::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
ClauseKind::HostEffect(data) => data.fmt(f),
ClauseKind::Trait(a) => a.fmt(f),
ClauseKind::RegionOutlives(pair) => pair.fmt(f),
ClauseKind::TypeOutlives(pair) => pair.fmt(f),

View File

@ -368,7 +368,9 @@ pub(crate) fn clean_predicate<'tcx>(
// FIXME(generic_const_exprs): should this do something?
ty::ClauseKind::ConstEvaluatable(..)
| ty::ClauseKind::WellFormed(..)
| ty::ClauseKind::ConstArgHasType(..) => None,
| ty::ClauseKind::ConstArgHasType(..)
// FIXME(effects): We can probably use this `HostEffect` pred to render `~const`.
| ty::ClauseKind::HostEffect(_) => None,
}
}

View File

@ -1,14 +0,0 @@
//@ known-bug: #118320
//@ edition:2021
#![feature(const_trait_impl, effects, const_closures)]
#[const_trait]
trait Bar {
fn foo(&self);
}
impl Bar for () {}
const FOO: () = {
(const || (()).foo())();
};

View File

@ -1,15 +0,0 @@
//@ known-bug: #119924
//@ compile-flags: -Znext-solver
#![feature(const_trait_impl, effects)]
struct S;
#[const_trait]
trait Trait<const N: u32> {}
const fn f<T: Trait<{
struct I<U: ~const Trait<0>>(U); // should've gotten rejected during AST validation
//~^ ICE no host param id for call in const yet no errors reported
0
}>>() {}
pub fn main() {}

View File

@ -11,30 +11,12 @@ error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{con
|
LL | impl<T: ?Sized + ConstName> const ConstName for &T
| ^^ cannot normalize `<&T as ConstName>::{constant#0}`
|
note: required for `&T` to implement `ConstName`
--> $DIR/issue-88119.rs:19:35
|
LL | impl<T: ?Sized + ConstName> const ConstName for &T
| ^^^^^^^^^ ^^
LL | where
LL | [(); name_len::<T>()]:,
| --------------------- unsatisfied trait bound introduced here
error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
--> $DIR/issue-88119.rs:26:49
|
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
| ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
|
note: required for `&mut T` to implement `ConstName`
--> $DIR/issue-88119.rs:26:35
|
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
| ^^^^^^^^^ ^^^^^^
LL | where
LL | [(); name_len::<T>()]:,
| --------------------- unsatisfied trait bound introduced here
error: aborting due to 3 previous errors

View File

@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-block-const-bound.rs:8:22
|
LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-block-const-bound.rs:8:32
|
@ -12,6 +20,6 @@ LL | const fn f<T: ~const Destruct>(x: T) {}
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0493`.

View File

@ -3,24 +3,12 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
= note: the next trait solver must be enabled globally for the effects feature to work correctly
= help: use `-Znext-solver` to enable
error[E0308]: mismatched types
error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
--> $DIR/constifconst-call-in-const-position.rs:17:38
|
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
| ^^^^^^ expected `false`, found `host`
|
= note: expected constant `false`
found constant `host`
| ^^^^^^ calling non-const function `<() as Tr>::a`
error[E0308]: mismatched types
--> $DIR/constifconst-call-in-const-position.rs:18:9
|
LL | [0; T::a()]
| ^^^^^^ expected `false`, found `host`
|
= note: expected constant `false`
found constant `host`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0080`.

View File

@ -30,6 +30,22 @@ LL | T: ~const Fn<()> + ~const Destruct,
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:13:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:13:31
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:20:15
|
@ -50,6 +66,22 @@ LL | T: ~const FnMut<()> + ~const Destruct,
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:20:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:20:34
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:27:15
|
@ -64,6 +96,14 @@ LL | T: ~const FnOnce<()>,
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:27:15
|
LL | T: ~const FnOnce<()>,
| ^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:34:15
|
@ -84,6 +124,22 @@ LL | T: ~const Fn<()> + ~const Destruct,
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:34:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:34:31
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:48:15
|
@ -104,6 +160,22 @@ LL | T: ~const FnMut<()> + ~const Destruct,
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:48:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:48:34
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const operator in constants
--> $DIR/fn_trait_refs.rs:70:17
|
@ -212,7 +284,7 @@ LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
LL | }
| - value is dropped here
error: aborting due to 25 previous errors
error: aborting due to 34 previous errors
Some errors have detailed explanations: E0015, E0493, E0635.
For more information about an error, try `rustc --explain E0015`.

View File

@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
| ^^^^^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/unstable-const-fn-in-libcore.rs:19:39
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
| ^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/unstable-const-fn-in-libcore.rs:24:26
|
@ -38,7 +46,7 @@ LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
LL | }
| - value is dropped here
error: aborting due to 4 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -4,7 +4,7 @@
// FIXME(fn_delegation): `recursive delegation` error should be emitted here
trait Trait {
reuse Trait::foo { &self.0 }
//~^ ERROR cycle detected when computing generics of `Trait::foo`
//~^ ERROR recursive delegation is not supported yet
}
reuse foo;

View File

@ -1,16 +1,8 @@
error[E0391]: cycle detected when computing generics of `Trait::foo`
error: recursive delegation is not supported yet
--> $DIR/ice-issue-124347.rs:6:18
|
LL | reuse Trait::foo { &self.0 }
| ^^^
|
= note: ...which immediately requires computing generics of `Trait::foo` again
note: cycle used when inheriting delegation signature
--> $DIR/ice-issue-124347.rs:6:18
|
LL | reuse Trait::foo { &self.0 }
| ^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
| ^^^ callee defined here
error[E0391]: cycle detected when computing generics of `foo`
--> $DIR/ice-issue-124347.rs:10:7

View File

@ -51,7 +51,7 @@ mod effects {
}
reuse Trait::foo;
//~^ ERROR delegation to a function with effect parameter is not supported yet
//~^ ERROR type annotations needed
}
fn main() {}

View File

@ -81,15 +81,15 @@ LL | pub reuse to_reuse2::foo;
LL | reuse to_reuse1::foo;
| ^^^
error: delegation to a function with effect parameter is not supported yet
error[E0283]: type annotations needed
--> $DIR/unsupported.rs:53:18
|
LL | fn foo();
| --------- callee defined here
...
LL | reuse Trait::foo;
| ^^^
| ^^^ cannot infer type
|
= note: cannot satisfy `_: effects::Trait`
error: aborting due to 5 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0391`.
Some errors have detailed explanations: E0283, E0391.
For more information about an error, try `rustc --explain E0283`.

View File

@ -10,6 +10,22 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/normalize-tait-in-const.rs:26:42
|
LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
| ^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/normalize-tait-in-const.rs:26:69
|
LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/normalize-tait-in-const.rs:27:5
|
@ -35,7 +51,7 @@ LL | fun(filter_positive());
LL | }
| - value is dropped here
error: aborting due to 4 previous errors
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,23 +1,3 @@
error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:6:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub unsafe trait Sup {
LL | fn foo() -> u32;
| - expected 0 const parameters
error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:6:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub unsafe trait Sup {
LL | fn foo() -> u32;
| - expected 0 const parameters
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const_trait_impl.rs:34:16
|
@ -36,34 +16,27 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | impl<T: ~const Default + ~const Sub> const A for T {
| ^^^^^^^
error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:29:1
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const_trait_impl.rs:40:16
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait A {
LL | fn a() -> u32;
| - expected 0 const parameters
error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:29:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait A {
LL | fn a() -> u32;
| - expected 0 const parameters
LL | impl<T: ~const Default + ~const Sup> const A for T {
| ^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:29:1
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const_trait_impl.rs:34:16
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait A {
LL | fn a() -> u32;
| - expected 0 const parameters
LL | impl<T: ~const Default> const A for T {
| ^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const_trait_impl.rs:46:16
|
LL | impl<T: ~const Default + ~const Sub> const A for T {
| ^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
@ -115,7 +88,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
LL + #![feature(effects)]
|
error: aborting due to 12 previous errors
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0015, E0049.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -3,44 +3,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
= note: the next trait solver must be enabled globally for the effects feature to work correctly
= help: use `-Znext-solver` to enable
error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-0.rs:13:5
|
LL | T::Assoc::func()
| ^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
|
note: required by a bound in `Trait::func`
--> $DIR/assoc-type-const-bound-usage-0.rs:6:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
...
LL | fn func() -> i32;
| ---- required by a bound in this associated function
help: consider further restricting the associated type
|
LL | const fn unqualified<T: ~const Trait>() -> i32 where <T as Trait>::Assoc: Trait {
| ++++++++++++++++++++++++++++++++
error: aborting due to 1 previous error
error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-0.rs:17:5
|
LL | <T as Trait>::Assoc::func()
| ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
|
note: required by a bound in `Trait::func`
--> $DIR/assoc-type-const-bound-usage-0.rs:6:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
...
LL | fn func() -> i32;
| ---- required by a bound in this associated function
help: consider further restricting the associated type
|
LL | const fn qualified<T: ~const Trait>() -> i32 where <T as Trait>::Assoc: Trait {
| ++++++++++++++++++++++++++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -3,44 +3,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
= note: the next trait solver must be enabled globally for the effects feature to work correctly
= help: use `-Znext-solver` to enable
error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-1.rs:15:44
|
LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
| ^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
|
note: required by a bound in `Trait::func`
--> $DIR/assoc-type-const-bound-usage-1.rs:7:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
...
LL | fn func() -> i32;
| ---- required by a bound in this associated function
help: consider further restricting the associated type
|
LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> where <T as Trait>::Assoc: Trait {
| ++++++++++++++++++++++++++++++++
error: aborting due to 1 previous error
error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied
--> $DIR/assoc-type-const-bound-usage-1.rs:19:42
|
LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
| ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc`
|
note: required by a bound in `Trait::func`
--> $DIR/assoc-type-const-bound-usage-1.rs:7:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
...
LL | fn func() -> i32;
| ---- required by a bound in this associated function
help: consider further restricting the associated type
|
LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> where <T as Trait>::Assoc: Trait {
| ++++++++++++++++++++++++++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -2,20 +2,7 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
--> $DIR/call-const-trait-method-fail.rs:27:5
|
LL | a.plus(b)
| ^ the trait `Plus` is not implemented for `u32`
|
note: required by a bound in `Plus::plus`
--> $DIR/call-const-trait-method-fail.rs:5:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `Plus::plus`
LL | pub trait Plus {
LL | fn plus(self, rhs: Self) -> Self;
| ---- required by a bound in this associated function
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | pub const fn add_u32(a: u32, b: u32) -> u32 where u32: Plus {
| +++++++++++++++
| ^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -16,15 +16,6 @@ LL | impl const PartialEq for Int {
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
error[E0049]: method `plus` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/call-const-trait-method-pass.rs:24:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait Plus {
LL | fn plus(self, rhs: Self) -> Self;
| - expected 0 const parameters
error[E0015]: cannot call non-const operator in constants
--> $DIR/call-const-trait-method-pass.rs:39:22
|
@ -73,7 +64,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
LL + #![feature(effects)]
|
error: aborting due to 7 previous errors
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0015, E0049.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -4,14 +4,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | impl<T: ~const PartialEq> const MyPartialEq for T {
| ^^^^^^^^^
error[E0049]: method `eq` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/call-generic-in-impl.rs:5:1
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-in-impl.rs:10:16
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | trait MyPartialEq {
LL | fn eq(&self, other: &Self) -> bool;
| - expected 0 const parameters
LL | impl<T: ~const PartialEq> const MyPartialEq for T {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const fn `<T as PartialEq>::eq` in constant functions
--> $DIR/call-generic-in-impl.rs:12:9
@ -27,5 +26,4 @@ LL + #![feature(effects)]
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0049.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -27,11 +27,27 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-chain.rs:19:32
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-chain.rs:23:40
|
LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 4 previous errors; 1 warning emitted
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-chain.rs:23:40
|
LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 6 previous errors; 1 warning emitted

View File

@ -27,11 +27,27 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-dup-bound.rs:19:44
|
LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-dup-bound.rs:26:37
|
LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 4 previous errors; 1 warning emitted
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-dup-bound.rs:26:37
|
LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 6 previous errors; 1 warning emitted

View File

@ -1,20 +1,8 @@
error[E0277]: the trait bound `S: const Foo` is not satisfied
--> $DIR/call-generic-method-nonconst.rs:25:34
--> $DIR/call-generic-method-nonconst.rs:25:22
|
LL | pub const EQ: bool = equals_self(&S);
| ----------- ^^ the trait `Foo` is not implemented for `S`
| |
| required by a bound introduced by this call
|
note: required by a bound in `equals_self`
--> $DIR/call-generic-method-nonconst.rs:18:25
|
LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
| ^^^^^^^^^^ required by this bound in `equals_self`
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | pub const EQ: bool where S: Foo = equals_self(&S);
| ++++++++++++
| ^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -27,5 +27,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 3 previous errors; 1 warning emitted
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/call-generic-method-pass.rs:19:32
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors; 1 warning emitted

View File

@ -5,6 +5,7 @@ trait NonConst {}
const fn perform<T: ~const NonConst>() {}
//~^ ERROR `~const` can only be applied to `#[const_trait]` traits
//~| ERROR `~const` can only be applied to `#[const_trait]` traits
fn operate<T: const NonConst>() {}
//~^ ERROR `const` can only be applied to `#[const_trait]` traits

View File

@ -18,11 +18,19 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn perform<T: ~const NonConst>() {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-bounds-non-const-trait.rs:6:28
|
LL | const fn perform<T: ~const NonConst>() {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `const` can only be applied to `#[const_trait]` traits
--> $DIR/const-bounds-non-const-trait.rs:9:21
--> $DIR/const-bounds-non-const-trait.rs:10:21
|
LL | fn operate<T: const NonConst>() {}
| ^^^^^^^^
error: aborting due to 3 previous errors; 1 warning emitted
error: aborting due to 4 previous errors; 1 warning emitted

View File

@ -1,17 +1,16 @@
error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-closure-trait-method-fail.rs:5:1
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-trait-method-fail.rs:14:39
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | trait Tr {
LL | fn a(self) -> i32;
| - expected 0 const parameters
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^^^^^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-trait-method-fail.rs:14:39
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closure-trait-method-fail.rs:15:5
@ -31,5 +30,4 @@ LL + #![feature(effects)]
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0049.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,17 +1,16 @@
error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-closure-trait-method.rs:5:1
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-trait-method.rs:14:39
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | trait Tr {
LL | fn a(self) -> i32;
| - expected 0 const parameters
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^^^^^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-trait-method.rs:14:39
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closure-trait-method.rs:15:5
@ -31,5 +30,4 @@ LL + #![feature(effects)]
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0049.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0015`.

View File

@ -16,12 +16,44 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | F: ~const Fn() -> u8,
| ^^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:8:19
|
LL | F: ~const FnOnce() -> u8,
| ^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:9:19
|
LL | F: ~const FnMut() -> u8,
| ^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:10:19
|
LL | F: ~const Fn() -> u8,
| ^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:23:27
|
LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
| ^^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:23:27
|
LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
| ^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/const-closures.rs:24:5
|
@ -70,6 +102,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable
LL + #![feature(effects)]
|
error: aborting due to 7 previous errors
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,21 +1,8 @@
error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
--> $DIR/const-default-method-bodies.rs:26:18
--> $DIR/const-default-method-bodies.rs:26:5
|
LL | NonConstImpl.a();
| ^ the trait `ConstDefaultFn` is not implemented for `NonConstImpl`
|
note: required by a bound in `ConstDefaultFn::a`
--> $DIR/const-default-method-bodies.rs:5:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `ConstDefaultFn::a`
...
LL | fn a(self) {
| - required by a bound in this associated function
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | const fn test() where NonConstImpl: ConstDefaultFn {
| ++++++++++++++++++++++++++++++++++
| ^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-bound.rs:9:68
|
LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-bound.rs:20:15
|
@ -16,12 +24,28 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | E: ~const Destruct,
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-bound.rs:20:15
|
LL | T: ~const Destruct,
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-bound.rs:21:15
|
LL | E: ~const Destruct,
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `E` cannot be evaluated at compile-time
--> $DIR/const-drop-bound.rs:12:13
|
LL | Err(_e) => None,
| ^^ the destructor for this type cannot be evaluated in constant functions
error: aborting due to 4 previous errors
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0493`.

View File

@ -13,6 +13,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-fail-2.rs:20:26
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-drop-fail-2.rs:20:36
|
@ -33,7 +41,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
LL + #![feature(effects)]
|
error: aborting due to 4 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -13,6 +13,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-fail.rs:23:26
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-drop-fail.rs:23:36
|
@ -71,7 +79,7 @@ LL | | }
| |_- in this macro invocation
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 5 previous errors
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0080, E0493.
For more information about an error, try `rustc --explain E0080`.

View File

@ -13,6 +13,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop-fail.rs:23:26
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-drop-fail.rs:23:36
|
@ -21,6 +29,6 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0493`.

View File

@ -40,23 +40,11 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn a<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:53:5
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop.rs:18:22
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait SomeTrait {
LL | fn foo();
| - expected 0 const parameters
error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:53:5
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait SomeTrait {
LL | fn foo();
| - expected 0 const parameters
LL | const fn a<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
@ -78,7 +66,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
LL + #![feature(effects)]
|
error: aborting due to 9 previous errors
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0015, E0049, E0493.
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -40,23 +40,11 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn a<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:53:5
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-drop.rs:18:22
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait SomeTrait {
LL | fn foo();
| - expected 0 const parameters
error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:53:5
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | pub trait SomeTrait {
LL | fn foo();
| - expected 0 const parameters
LL | const fn a<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
@ -80,7 +68,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
LL + #![feature(effects)]
|
error: aborting due to 9 previous errors
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0015, E0049, E0493.
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,4 +1,6 @@
//@ known-bug: #110395
//@ failure-status: 101
//@ dont-check-compiler-stderr
// FIXME(effects) check-pass
//@ compile-flags: -Znext-solver

View File

@ -1,20 +0,0 @@
error[E0277]: the trait bound `fn() {foo}: const FnOnce()` is not satisfied
--> $DIR/const-fns-are-early-bound.rs:31:17
|
LL | is_const_fn(foo);
| ----------- ^^^ the trait `FnOnce()` is not implemented for fn item `fn() {foo}`
| |
| required by a bound introduced by this call
|
note: required by a bound in `is_const_fn`
--> $DIR/const-fns-are-early-bound.rs:25:12
|
LL | fn is_const_fn<F>(_: F)
| ----------- required by a bound in this function
LL | where
LL | F: const FnOnce<()>,
| ^^^^^^^^^^^^^^^^ required by this bound in `is_const_fn`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,249 +0,0 @@
error[E0635]: unknown feature `const_cmp`
--> $DIR/const-impl-trait.rs:8:5
|
LL | const_cmp,
| ^^^^^^^^^
error: using `#![feature(effects)]` without enabling next trait solver globally
|
= note: the next trait solver must be enabled globally for the effects feature to work correctly
= help: use `-Znext-solver` to enable
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:13:30
|
LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:17:30
|
LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:17:49
|
LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:18:20
|
LL | -> impl ~const PartialEq + ~const Destruct
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:18:39
|
LL | -> impl ~const PartialEq + ~const Destruct
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:18:20
|
LL | -> impl ~const PartialEq + ~const Destruct
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:18:39
|
LL | -> impl ~const PartialEq + ~const Destruct
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:48
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:29:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:29:48
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:29:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:29:48
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:50:41
|
LL | const fn apit(_: impl ~const T + ~const Destruct) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:54:73
|
LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:48
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:48
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:29
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/const-impl-trait.rs:25:48
|
LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:37:26
|
LL | assert!(wrap(123) == wrap(123));
| ^^^^^^^^^- value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:37:26
|
LL | assert!(wrap(123) == wrap(123));
| ^^^^^^^^^- value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:37:13
|
LL | assert!(wrap(123) == wrap(123));
| ^^^^^^^^^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:37:13
|
LL | assert!(wrap(123) == wrap(123));
| ^^^^^^^^^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:38:26
|
LL | assert!(wrap(123) != wrap(456));
| ^^^^^^^^^- value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:38:26
|
LL | assert!(wrap(123) != wrap(456));
| ^^^^^^^^^- value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:38:13
|
LL | assert!(wrap(123) != wrap(456));
| ^^^^^^^^^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:38:13
|
LL | assert!(wrap(123) != wrap(456));
| ^^^^^^^^^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constants
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `impl ~const T + ~const Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:50:15
|
LL | const fn apit(_: impl ~const T + ~const Destruct) {}
| ^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constant functions
error[E0493]: destructor of `impl IntoIterator<Item : ~const T> + ~const Destruct` cannot be evaluated at compile-time
--> $DIR/const-impl-trait.rs:54:27
|
LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
| ^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 33 previous errors
Some errors have detailed explanations: E0493, E0635.
For more information about an error, try `rustc --explain E0493`.

View File

@ -30,5 +30,14 @@ LL | #[derive_const(PartialEq)]
|
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors; 1 warning emitted
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/derive-const-with-params.rs:7:16
|
LL | #[derive_const(PartialEq)]
| ^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors; 1 warning emitted

View File

@ -1,21 +1,8 @@
error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
--> $DIR/cross-crate.rs:19:14
--> $DIR/cross-crate.rs:19:5
|
LL | NonConst.func();
| ^^^^ the trait `cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
|
note: required by a bound in `func`
--> $DIR/auxiliary/cross-crate.rs:5:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `MyTrait::func`
...
LL | fn func(self);
| ---- required by a bound in this associated function
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | const fn const_context() where cross_crate::NonConst: cross_crate::MyTrait {
| +++++++++++++++++++++++++++++++++++++++++++++++++
| ^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View File

@ -1,21 +1,8 @@
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:9
|
LL | ().a()
| ^ the trait `Tr` is not implemented for `()`
|
note: required by a bound in `Tr::a`
--> $DIR/default-method-body-is-const-same-trait-ck.rs:5:1
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ required by this bound in `Tr::a`
LL | pub trait Tr {
LL | fn a(&self) {}
| - required by a bound in this associated function
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | pub trait Tr where (): Tr {
| ++++++++++++
| ^^^^^^
error: aborting due to 1 previous error

View File

@ -1,13 +1,13 @@
error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [check_well_formed] checking that `<impl at $DIR/minicore.rs:459:1: 459:36>` is well-formed
#1 [check_mod_type_wf] checking that types are well-formed in top-level module
#0 [typeck] type-checking `Clone::clone_from`
#1 [analysis] running analysis passes on this crate
end of query stack
error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [check_well_formed] checking that `drop` is well-formed
#1 [check_mod_type_wf] checking that types are well-formed in top-level module
#0 [typeck] type-checking `test_const_eval_select`
#1 [analysis] running analysis passes on this crate
end of query stack

View File

@ -16,17 +16,15 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
--> $DIR/no-explicit-const-params-cross-crate.rs:16:12
|
LL | <() as Bar<false>>::bar();
| ^^^ expected 0 generic arguments
| ^^^------- help: remove the unnecessary generics
| |
| expected 0 generic arguments
|
note: trait defined here, with 0 generic parameters
--> $DIR/auxiliary/cross-crate.rs:8:11
|
LL | pub trait Bar {
| ^^^
help: replace the generic bound with the associated type
|
LL | <() as Bar< = false>>::bar();
| +
error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/no-explicit-const-params-cross-crate.rs:7:5
@ -46,17 +44,15 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
--> $DIR/no-explicit-const-params-cross-crate.rs:9:12
|
LL | <() as Bar<true>>::bar();
| ^^^ expected 0 generic arguments
| ^^^------ help: remove the unnecessary generics
| |
| expected 0 generic arguments
|
note: trait defined here, with 0 generic parameters
--> $DIR/auxiliary/cross-crate.rs:8:11
|
LL | pub trait Bar {
| ^^^
help: replace the generic bound with the associated type
|
LL | <() as Bar< = true>>::bar();
| +
error: aborting due to 4 previous errors

View File

@ -23,5 +23,4 @@ const FOO: () = {
//~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied
<() as Bar<false>>::bar();
//~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
//~| ERROR: mismatched types
};

View File

@ -30,26 +30,15 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
--> $DIR/no-explicit-const-params.rs:24:12
|
LL | <() as Bar<false>>::bar();
| ^^^ expected 0 generic arguments
| ^^^------- help: remove the unnecessary generics
| |
| expected 0 generic arguments
|
note: trait defined here, with 0 generic parameters
--> $DIR/no-explicit-const-params.rs:6:7
|
LL | trait Bar {
| ^^^
help: replace the generic bound with the associated type
|
LL | <() as Bar< = false>>::bar();
| +
error[E0308]: mismatched types
--> $DIR/no-explicit-const-params.rs:24:5
|
LL | <() as Bar<false>>::bar();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `false`, found `true`
|
= note: expected constant `false`
found constant `true`
error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/no-explicit-const-params.rs:15:5
@ -69,19 +58,16 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplie
--> $DIR/no-explicit-const-params.rs:17:12
|
LL | <() as Bar<true>>::bar();
| ^^^ expected 0 generic arguments
| ^^^------ help: remove the unnecessary generics
| |
| expected 0 generic arguments
|
note: trait defined here, with 0 generic parameters
--> $DIR/no-explicit-const-params.rs:6:7
|
LL | trait Bar {
| ^^^
help: replace the generic bound with the associated type
|
LL | <() as Bar< = true>>::bar();
| +
error: aborting due to 6 previous errors; 1 warning emitted
error: aborting due to 5 previous errors; 1 warning emitted
Some errors have detailed explanations: E0107, E0308.
For more information about an error, try `rustc --explain E0107`.
For more information about this error, try `rustc --explain E0107`.

View File

@ -1,4 +1,3 @@
//@ check-fail
// Fixes #119830
#![feature(effects)] //~ WARN the feature `effects` is incomplete
@ -15,7 +14,9 @@ impl<T> const Foo for T {}
impl<T> const Foo for T where T: const Specialize {}
//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
//~| error: `const` can only be applied to `#[const_trait]` traits
//~| error: `const` can only be applied to `#[const_trait]` traits
//~| error: specialization impl does not specialize any associated items
//~| error: cannot specialize on trait `Specialize`
//~| ERROR cannot specialize on predicate
fn main() {}

View File

@ -1,5 +1,5 @@
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/spec-effectvar-ice.rs:4:12
--> $DIR/spec-effectvar-ice.rs:3:12
|
LL | #![feature(effects)]
| ^^^^^^^
@ -13,7 +13,7 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
= help: use `-Znext-solver` to enable
error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
--> $DIR/spec-effectvar-ice.rs:12:15
--> $DIR/spec-effectvar-ice.rs:11:15
|
LL | trait Foo {}
| - help: mark `Foo` as const: `#[const_trait]`
@ -25,7 +25,7 @@ LL | impl<T> const Foo for T {}
= note: adding a non-const method body in the future would be a breaking change
error: const `impl` for trait `Foo` which is not marked with `#[const_trait]`
--> $DIR/spec-effectvar-ice.rs:15:15
--> $DIR/spec-effectvar-ice.rs:14:15
|
LL | trait Foo {}
| - help: mark `Foo` as const: `#[const_trait]`
@ -37,28 +37,42 @@ LL | impl<T> const Foo for T where T: const Specialize {}
= note: adding a non-const method body in the future would be a breaking change
error: `const` can only be applied to `#[const_trait]` traits
--> $DIR/spec-effectvar-ice.rs:15:40
--> $DIR/spec-effectvar-ice.rs:14:40
|
LL | impl<T> const Foo for T where T: const Specialize {}
| ^^^^^^^^^^
error: `const` can only be applied to `#[const_trait]` traits
--> $DIR/spec-effectvar-ice.rs:14:40
|
LL | impl<T> const Foo for T where T: const Specialize {}
| ^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: specialization impl does not specialize any associated items
--> $DIR/spec-effectvar-ice.rs:15:1
--> $DIR/spec-effectvar-ice.rs:14:1
|
LL | impl<T> const Foo for T where T: const Specialize {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl is a specialization of this impl
--> $DIR/spec-effectvar-ice.rs:12:1
--> $DIR/spec-effectvar-ice.rs:11:1
|
LL | impl<T> const Foo for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^
error: cannot specialize on trait `Specialize`
--> $DIR/spec-effectvar-ice.rs:15:34
error: cannot specialize on predicate `T: const Specialize`
--> $DIR/spec-effectvar-ice.rs:14:34
|
LL | impl<T> const Foo for T where T: const Specialize {}
| ^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors; 1 warning emitted
error: cannot specialize on trait `Specialize`
--> $DIR/spec-effectvar-ice.rs:14:34
|
LL | impl<T> const Foo for T where T: const Specialize {}
| ^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors; 1 warning emitted

View File

@ -3,5 +3,6 @@
const fn with_positive<F: ~const Fn()>() {}
//~^ ERROR `~const` can only be applied to `#[const_trait]` traits
//~| ERROR `~const` can only be applied to `#[const_trait]` traits
pub fn main() {}

View File

@ -9,5 +9,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn with_positive<F: ~const Fn()>() {}
| ^^^^
error: aborting due to 2 previous errors
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/ice-123664-unexpected-bound-var.rs:4:34
|
LL | const fn with_positive<F: ~const Fn()>() {}
| ^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 3 previous errors

View File

@ -4,6 +4,14 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | const fn a<T: ~const Destruct>(t: T) {}
| ^^^^^^^^
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/issue-92111.rs:20:22
|
LL | const fn a<T: ~const Destruct>(t: T) {}
| ^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/issue-92111.rs:20:32
|
@ -12,6 +20,6 @@ LL | const fn a<T: ~const Destruct>(t: T) {}
| |
| the destructor for this type cannot be evaluated in constant functions
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0493`.

View File

@ -4,14 +4,13 @@ error: `~const` can only be applied to `#[const_trait]` traits
LL | impl<A, B> const Convert<B> for A where B: ~const From<A> {
| ^^^^^^^
error[E0049]: method `to` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/non-const-op-in-closure-in-const.rs:5:1
error: `~const` can only be applied to `#[const_trait]` traits
--> $DIR/non-const-op-in-closure-in-const.rs:10:51
|
LL | #[const_trait]
| ^^^^^^^^^^^^^^ found 1 const parameter
LL | trait Convert<T> {
LL | fn to(self) -> T;
| - expected 0 const parameters
LL | impl<A, B> const Convert<B> for A where B: ~const From<A> {
| ^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0015]: cannot call non-const fn `<B as From<A>>::from` in constant functions
--> $DIR/non-const-op-in-closure-in-const.rs:12:9
@ -27,5 +26,4 @@ LL + #![feature(effects)]
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0049.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0015`.

Some files were not shown because too many files have changed in this diff Show More