mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Implement const effect predicate in new solver
This commit is contained in:
parent
a16d491054
commit
cde29b9ec9
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
)
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
@ -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 => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 => {
|
||||
|
@ -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>>,
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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::{
|
||||
|
@ -132,6 +132,7 @@ parameterized_over_tcx! {
|
||||
ty::Ty,
|
||||
ty::FnSig,
|
||||
ty::GenericPredicates,
|
||||
ty::ConstConditions,
|
||||
ty::TraitRef,
|
||||
ty::Const,
|
||||
ty::Predicate,
|
||||
|
@ -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(..)
|
||||
|
@ -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), "`")
|
||||
},
|
||||
|
296
compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Normal file
296
compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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 })
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
mod alias_relate;
|
||||
mod assembly;
|
||||
mod effect_goals;
|
||||
mod eval_ctxt;
|
||||
pub mod inspect;
|
||||
mod normalizes_to;
|
||||
|
@ -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,
|
||||
|
@ -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!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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(..)
|
||||
|
@ -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?
|
||||
|
@ -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(_, _)
|
||||
|
@ -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(..)
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())();
|
||||
};
|
@ -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() {}
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -1,4 +1,6 @@
|
||||
//@ known-bug: #110395
|
||||
//@ failure-status: 101
|
||||
//@ dont-check-compiler-stderr
|
||||
// FIXME(effects) check-pass
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
|
@ -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`.
|
@ -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`.
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user