Use the constness from the param env instead of having a separate dimension for it
This breaks a ~const test that will be fixed in a follow up commit of this PR
This commit is contained in:
parent
19f2101272
commit
d51068ca28
@ -817,8 +817,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
||||||
let mut selcx =
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
SelectionContext::with_constness(&infcx, hir::Constness::Const);
|
|
||||||
selcx.select(&obligation)
|
selcx.select(&obligation)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
//! See the `Qualif` trait for more info.
|
//! See the `Qualif` trait for more info.
|
||||||
|
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
|
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
|
||||||
@ -167,7 +166,7 @@ impl Qualif for NeedsNonConstDrop {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
|
let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
|
||||||
let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
selcx.select(&obligation)
|
selcx.select(&obligation)
|
||||||
});
|
});
|
||||||
!matches!(
|
!matches!(
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
use crate::traits::Obligation;
|
use crate::traits::Obligation;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
|
use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
|
||||||
|
|
||||||
@ -48,25 +47,10 @@ pub trait TraitEngine<'tcx>: 'tcx {
|
|||||||
|
|
||||||
fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||||
|
|
||||||
fn select_all_with_constness_or_error(
|
fn select_where_possible(
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
infcx: &InferCtxt<'_, 'tcx>,
|
||||||
_constness: hir::Constness,
|
) -> Vec<FulfillmentError<'tcx>>;
|
||||||
) -> Vec<FulfillmentError<'tcx>> {
|
|
||||||
self.select_all_or_error(infcx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>)
|
|
||||||
-> Vec<FulfillmentError<'tcx>>;
|
|
||||||
|
|
||||||
// FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated
|
|
||||||
fn select_with_constness_where_possible(
|
|
||||||
&mut self,
|
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
|
||||||
_constness: hir::Constness,
|
|
||||||
) -> Vec<FulfillmentError<'tcx>> {
|
|
||||||
self.select_where_possible(infcx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
|
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
|
||||||
|
|
||||||
|
@ -69,6 +69,16 @@ impl PredicateObligation<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TraitObligation<'tcx> {
|
||||||
|
/// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
|
||||||
|
pub fn is_const(&self) -> bool {
|
||||||
|
match (self.predicate.skip_binder().constness, self.param_env.constness()) {
|
||||||
|
(ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
static_assert_size!(PredicateObligation<'_>, 32);
|
static_assert_size!(PredicateObligation<'_>, 32);
|
||||||
|
@ -4,7 +4,6 @@ use rustc_data_structures::obligation_forest::ProcessResult;
|
|||||||
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
||||||
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
||||||
@ -231,21 +230,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||||||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_all_with_constness_or_error(
|
|
||||||
&mut self,
|
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
|
||||||
constness: rustc_hir::Constness,
|
|
||||||
) -> Vec<FulfillmentError<'tcx>> {
|
|
||||||
{
|
|
||||||
let errors = self.select_with_constness_where_possible(infcx, constness);
|
|
||||||
if !errors.is_empty() {
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn select_where_possible(
|
fn select_where_possible(
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
infcx: &InferCtxt<'_, 'tcx>,
|
||||||
@ -254,15 +238,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||||||
self.select(&mut selcx)
|
self.select(&mut selcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_with_constness_where_possible(
|
|
||||||
&mut self,
|
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
|
||||||
constness: hir::Constness,
|
|
||||||
) -> Vec<FulfillmentError<'tcx>> {
|
|
||||||
let mut selcx = SelectionContext::with_constness(infcx, constness);
|
|
||||||
self.select(&mut selcx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
|
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
|
||||||
self.predicates.map_pending_obligations(|o| o.obligation.clone())
|
self.predicates.map_pending_obligations(|o| o.obligation.clone())
|
||||||
}
|
}
|
||||||
@ -679,12 +654,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||||||
if obligation.predicate.is_known_global() {
|
if obligation.predicate.is_known_global() {
|
||||||
// no type variables present, can use evaluation for better caching.
|
// no type variables present, can use evaluation for better caching.
|
||||||
// FIXME: consider caching errors too.
|
// FIXME: consider caching errors too.
|
||||||
//
|
if infcx.predicate_must_hold_considering_regions(obligation) {
|
||||||
// If the predicate is considered const, then we cannot use this because
|
|
||||||
// it will cause false negatives in the ui tests.
|
|
||||||
if !self.selcx.is_predicate_const(obligation.predicate)
|
|
||||||
&& infcx.predicate_must_hold_considering_regions(obligation)
|
|
||||||
{
|
|
||||||
debug!(
|
debug!(
|
||||||
"selecting trait at depth {} evaluated to holds",
|
"selecting trait at depth {} evaluated to holds",
|
||||||
obligation.recursion_depth
|
obligation.recursion_depth
|
||||||
@ -738,12 +708,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||||||
if obligation.predicate.is_global(tcx) {
|
if obligation.predicate.is_global(tcx) {
|
||||||
// no type variables present, can use evaluation for better caching.
|
// no type variables present, can use evaluation for better caching.
|
||||||
// FIXME: consider caching errors too.
|
// FIXME: consider caching errors too.
|
||||||
//
|
if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
|
||||||
// If the predicate is considered const, then we cannot use this because
|
|
||||||
// it will cause false negatives in the ui tests.
|
|
||||||
if !self.selcx.is_predicate_const(obligation.predicate)
|
|
||||||
&& self.selcx.infcx().predicate_must_hold_considering_regions(obligation)
|
|
||||||
{
|
|
||||||
return ProcessResult::Changed(vec![]);
|
return ProcessResult::Changed(vec![]);
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!("Does NOT hold: {:?}", obligation);
|
tracing::debug!("Does NOT hold: {:?}", obligation);
|
||||||
|
@ -303,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
} else if lang_items.drop_trait() == Some(def_id)
|
} else if lang_items.drop_trait() == Some(def_id)
|
||||||
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
|
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
|
||||||
{
|
{
|
||||||
if self.is_in_const_context {
|
if obligation.param_env.constness() == hir::Constness::Const {
|
||||||
self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?;
|
self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?;
|
||||||
} else {
|
} else {
|
||||||
debug!("passing ~const Drop bound; in non-const context");
|
debug!("passing ~const Drop bound; in non-const context");
|
||||||
|
@ -128,9 +128,6 @@ pub struct SelectionContext<'cx, 'tcx> {
|
|||||||
/// and a negative impl
|
/// and a negative impl
|
||||||
allow_negative_impls: bool,
|
allow_negative_impls: bool,
|
||||||
|
|
||||||
/// Are we in a const context that needs `~const` bounds to be const?
|
|
||||||
is_in_const_context: bool,
|
|
||||||
|
|
||||||
/// The mode that trait queries run in, which informs our error handling
|
/// The mode that trait queries run in, which informs our error handling
|
||||||
/// policy. In essence, canonicalized queries need their errors propagated
|
/// policy. In essence, canonicalized queries need their errors propagated
|
||||||
/// rather than immediately reported because we do not have accurate spans.
|
/// rather than immediately reported because we do not have accurate spans.
|
||||||
@ -222,7 +219,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
intercrate: false,
|
intercrate: false,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls: false,
|
allow_negative_impls: false,
|
||||||
is_in_const_context: false,
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
query_mode: TraitQueryMode::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +230,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
intercrate: true,
|
intercrate: true,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls: false,
|
allow_negative_impls: false,
|
||||||
is_in_const_context: false,
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
query_mode: TraitQueryMode::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +245,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
intercrate: false,
|
intercrate: false,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls,
|
allow_negative_impls,
|
||||||
is_in_const_context: false,
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
query_mode: TraitQueryMode::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,26 +260,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
intercrate: false,
|
intercrate: false,
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
allow_negative_impls: false,
|
allow_negative_impls: false,
|
||||||
is_in_const_context: false,
|
|
||||||
query_mode,
|
query_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_constness(
|
|
||||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
|
||||||
constness: hir::Constness,
|
|
||||||
) -> SelectionContext<'cx, 'tcx> {
|
|
||||||
SelectionContext {
|
|
||||||
infcx,
|
|
||||||
freshener: infcx.freshener_keep_static(),
|
|
||||||
intercrate: false,
|
|
||||||
intercrate_ambiguity_causes: None,
|
|
||||||
allow_negative_impls: false,
|
|
||||||
is_in_const_context: matches!(constness, hir::Constness::Const),
|
|
||||||
query_mode: TraitQueryMode::Standard,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enables tracking of intercrate ambiguity causes. These are
|
/// Enables tracking of intercrate ambiguity causes. These are
|
||||||
/// used in coherence to give improved diagnostics. We don't do
|
/// used in coherence to give improved diagnostics. We don't do
|
||||||
/// this until we detect a coherence error because it can lead to
|
/// this until we detect a coherence error because it can lead to
|
||||||
@ -318,20 +296,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
self.intercrate
|
self.intercrate
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
|
|
||||||
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
|
|
||||||
matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the predicate is considered `const` to
|
|
||||||
/// this selection context.
|
|
||||||
pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool {
|
|
||||||
match pred.kind().skip_binder() {
|
|
||||||
ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Selection
|
// Selection
|
||||||
//
|
//
|
||||||
@ -1138,7 +1102,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
|
|
||||||
for candidate in candidates {
|
for candidate in candidates {
|
||||||
// Respect const trait obligations
|
// Respect const trait obligations
|
||||||
if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
|
if obligation.is_const() {
|
||||||
match candidate {
|
match candidate {
|
||||||
// const impl
|
// const impl
|
||||||
ImplCandidate(def_id)
|
ImplCandidate(def_id)
|
||||||
|
@ -1388,13 +1388,7 @@ pub fn check_type_bounds<'tcx>(
|
|||||||
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
|
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
|
||||||
|
|
||||||
tcx.infer_ctxt().enter(move |infcx| {
|
tcx.infer_ctxt().enter(move |infcx| {
|
||||||
let constness = impl_ty
|
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
|
||||||
.container
|
|
||||||
.impl_def_id()
|
|
||||||
.map(|did| tcx.impl_constness(did))
|
|
||||||
.unwrap_or(hir::Constness::NotConst);
|
|
||||||
|
|
||||||
let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness);
|
|
||||||
let infcx = &inh.infcx;
|
let infcx = &inh.infcx;
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
|
|
||||||
@ -1439,7 +1433,7 @@ pub fn check_type_bounds<'tcx>(
|
|||||||
// Check that all obligations are satisfied by the implementation's
|
// Check that all obligations are satisfied by the implementation's
|
||||||
// version.
|
// version.
|
||||||
let errors =
|
let errors =
|
||||||
inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness);
|
inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.report_fulfillment_errors(&errors, None, false);
|
infcx.report_fulfillment_errors(&errors, None, false);
|
||||||
return Err(ErrorReported);
|
return Err(ErrorReported);
|
||||||
|
@ -613,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let errors = self
|
let errors = self
|
||||||
.fulfillment_cx
|
.fulfillment_cx
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.select_all_with_constness_or_error(&self, self.inh.constness);
|
.select_all_or_error(&self);
|
||||||
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
self.report_fulfillment_errors(&errors, self.inh.body_id, false);
|
self.report_fulfillment_errors(&errors, self.inh.body_id, false);
|
||||||
@ -629,7 +629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let mut result = self
|
let mut result = self
|
||||||
.fulfillment_cx
|
.fulfillment_cx
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.select_with_constness_where_possible(self, self.inh.constness);
|
.select_where_possible(self);
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
mutate_fulfillment_errors(&mut result);
|
mutate_fulfillment_errors(&mut result);
|
||||||
self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
|
self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
|
||||||
|
@ -53,9 +53,6 @@ pub struct Inherited<'a, 'tcx> {
|
|||||||
pub(super) deferred_generator_interiors:
|
pub(super) deferred_generator_interiors:
|
||||||
RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
|
RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
|
||||||
|
|
||||||
/// Reports whether this is in a const context.
|
|
||||||
pub(super) constness: hir::Constness,
|
|
||||||
|
|
||||||
pub(super) body_id: Option<hir::BodyId>,
|
pub(super) body_id: Option<hir::BodyId>,
|
||||||
|
|
||||||
/// Whenever we introduce an adjustment from `!` into a type variable,
|
/// Whenever we introduce an adjustment from `!` into a type variable,
|
||||||
@ -102,16 +99,6 @@ impl<'tcx> InheritedBuilder<'tcx> {
|
|||||||
|
|
||||||
impl Inherited<'a, 'tcx> {
|
impl Inherited<'a, 'tcx> {
|
||||||
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
|
||||||
let tcx = infcx.tcx;
|
|
||||||
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
|
||||||
Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn with_constness(
|
|
||||||
infcx: InferCtxt<'a, 'tcx>,
|
|
||||||
def_id: LocalDefId,
|
|
||||||
constness: hir::Constness,
|
|
||||||
) -> Self {
|
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||||
let body_id = tcx.hir().maybe_body_owned_by(item_id);
|
let body_id = tcx.hir().maybe_body_owned_by(item_id);
|
||||||
@ -128,7 +115,6 @@ impl Inherited<'a, 'tcx> {
|
|||||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||||
deferred_generator_interiors: RefCell::new(Vec::new()),
|
deferred_generator_interiors: RefCell::new(Vec::new()),
|
||||||
diverging_type_vars: RefCell::new(Default::default()),
|
diverging_type_vars: RefCell::new(Default::default()),
|
||||||
constness,
|
|
||||||
body_id,
|
body_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// FIXME(fee1-dead): this should have a better error message
|
// FIXME(fee1-dead): this should have a better error message
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
// check-pass
|
||||||
struct NonConstAdd(i32);
|
struct NonConstAdd(i32);
|
||||||
|
|
||||||
impl std::ops::Add for NonConstAdd {
|
impl std::ops::Add for NonConstAdd {
|
||||||
@ -29,3 +29,5 @@ impl const Baz for NonConstAdd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
|
// TODO: this test should not pass
|
@ -1,20 +0,0 @@
|
|||||||
error[E0277]: cannot add `NonConstAdd` to `NonConstAdd`
|
|
||||||
--> $DIR/assoc-type.rs:19:5
|
|
||||||
|
|
|
||||||
LL | type Bar = NonConstAdd;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd`
|
|
||||||
|
|
|
||||||
= help: the trait `Add` is not implemented for `NonConstAdd`
|
|
||||||
note: required by a bound in `Foo::Bar`
|
|
||||||
--> $DIR/assoc-type.rs:15:15
|
|
||||||
|
|
|
||||||
LL | type Bar: ~const std::ops::Add;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
|
|
||||||
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | impl const Foo for NonConstAdd where NonConstAdd: Add {
|
|
||||||
| ++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
Loading…
x
Reference in New Issue
Block a user