Pass constness to SelectionContext

This commit is contained in:
Deadbeef 2021-07-26 10:52:17 +08:00
parent a00f2bcf5c
commit 01bb3710b5
No known key found for this signature in database
GPG key ID: 027DF9338862ADDD
5 changed files with 101 additions and 23 deletions

View file

@ -1,5 +1,6 @@
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::Obligation; use crate::traits::Obligation;
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};
@ -49,11 +50,28 @@ pub trait TraitEngine<'tcx>: 'tcx {
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
) -> Result<(), Vec<FulfillmentError<'tcx>>>; ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
fn select_all_with_constness_or_error(
&mut self,
infcx: &InferCtxt<'_, 'tcx>,
_constness: hir::Constness,
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
self.select_all_or_error(infcx)
}
fn select_where_possible( fn select_where_possible(
&mut self, &mut self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
) -> Result<(), Vec<FulfillmentError<'tcx>>>; ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
// FIXME 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,
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
self.select_where_possible(infcx)
}
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>; fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
} }

View file

@ -3,6 +3,7 @@ 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::abstract_const::NotConstEvaluatable; use rustc_middle::mir::abstract_const::NotConstEvaluatable;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
@ -228,6 +229,22 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
if errors.is_empty() { Ok(()) } else { Err(errors) } if errors.is_empty() { Ok(()) } else { Err(errors) }
} }
fn select_all_with_constness_or_error(
&mut self,
infcx: &InferCtxt<'_, 'tcx>,
constness: rustc_hir::Constness,
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
self.select_with_constness_where_possible(infcx, constness)?;
let errors: Vec<_> = self
.predicates
.to_errors(CodeAmbiguity)
.into_iter()
.map(to_fulfillment_error)
.collect();
if errors.is_empty() { Ok(()) } else { Err(errors) }
}
fn select_where_possible( fn select_where_possible(
&mut self, &mut self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
@ -236,6 +253,15 @@ 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,
) -> Result<(), 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())
} }

View file

@ -130,6 +130,9 @@ pub struct SelectionContext<'cx, 'tcx> {
/// and a negative impl /// and a negative impl
allow_negative_impls: bool, allow_negative_impls: bool,
/// Do we only want const impls when we have a const trait predicate?
const_impls_required: 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.
@ -221,6 +224,7 @@ 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,
const_impls_required: false,
query_mode: TraitQueryMode::Standard, query_mode: TraitQueryMode::Standard,
} }
} }
@ -232,6 +236,7 @@ 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,
const_impls_required: false,
query_mode: TraitQueryMode::Standard, query_mode: TraitQueryMode::Standard,
} }
} }
@ -247,6 +252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false, intercrate: false,
intercrate_ambiguity_causes: None, intercrate_ambiguity_causes: None,
allow_negative_impls, allow_negative_impls,
const_impls_required: false,
query_mode: TraitQueryMode::Standard, query_mode: TraitQueryMode::Standard,
} }
} }
@ -262,10 +268,26 @@ 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,
const_impls_required: 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,
const_impls_required: 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
@ -1024,6 +1046,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
let tcx = self.tcx(); let tcx = self.tcx();
// Respect const trait obligations // Respect const trait obligations
if self.const_impls_required {
if let hir::Constness::Const = obligation.predicate.skip_binder().constness { if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
if Some(obligation.predicate.skip_binder().trait_ref.def_id) if Some(obligation.predicate.skip_binder().trait_ref.def_id)
!= tcx.lang_items().sized_trait() != tcx.lang_items().sized_trait()
@ -1035,7 +1058,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if tcx.impl_constness(def_id) == hir::Constness::Const => {} if tcx.impl_constness(def_id) == hir::Constness::Const => {}
// const param // const param
ParamCandidate(ty::ConstnessAnd { ParamCandidate(ty::ConstnessAnd {
constness: hir::Constness::Const, .. constness: hir::Constness::Const,
..
}) => {} }) => {}
// auto trait impl // auto trait impl
AutoImplCandidate(..) => {} AutoImplCandidate(..) => {}
@ -1048,6 +1072,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
} }
} }
}
// Treat negative impls as unimplemented, and reservation impls as ambiguity. // Treat negative impls as unimplemented, and reservation impls as ambiguity.
if let ImplCandidate(def_id) = candidate { if let ImplCandidate(def_id) = candidate {
match tcx.impl_polarity(def_id) { match tcx.impl_polarity(def_id) {

View file

@ -1354,7 +1354,9 @@ 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.
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { if let Err(ref errors) =
inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
{
infcx.report_fulfillment_errors(errors, None, false); infcx.report_fulfillment_errors(errors, None, false);
return Err(ErrorReported); return Err(ErrorReported);
} }

View file

@ -714,7 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn select_all_obligations_or_error(&self) { pub(in super::super) fn select_all_obligations_or_error(&self) {
debug!("select_all_obligations_or_error"); debug!("select_all_obligations_or_error");
if let Err(errors) = self.fulfillment_cx.borrow_mut().select_all_or_error(&self) { if let Err(errors) = self
.fulfillment_cx
.borrow_mut()
.select_all_with_constness_or_error(&self, self.inh.constness)
{
self.report_fulfillment_errors(&errors, self.inh.body_id, false); self.report_fulfillment_errors(&errors, self.inh.body_id, false);
} }
} }
@ -725,7 +729,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fallback_has_occurred: bool, fallback_has_occurred: bool,
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>), mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
) { ) {
let result = self.fulfillment_cx.borrow_mut().select_where_possible(self); let result = self
.fulfillment_cx
.borrow_mut()
.select_with_constness_where_possible(self, self.inh.constness);
if let Err(mut errors) = result { if let Err(mut errors) = result {
mutate_fulfillment_errors(&mut errors); mutate_fulfillment_errors(&mut errors);
self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred); self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);