diff options
| author | Deadbeef <ent3rm4n@gmail.com> | 2021-07-26 10:52:17 +0800 |
|---|---|---|
| committer | Deadbeef <ent3rm4n@gmail.com> | 2021-08-13 09:28:50 +0000 |
| commit | 01bb3710b5e7114a470f07b6d0463a70ae728607 (patch) | |
| tree | e59919553f05738dcc24ba2cb38b8ec4fe59b444 | |
| parent | a00f2bcf5c8d98852d6cfda2468185eda41ff2ba (diff) | |
| download | rust-01bb3710b5e7114a470f07b6d0463a70ae728607.tar.gz rust-01bb3710b5e7114a470f07b6d0463a70ae728607.zip | |
Pass constness to SelectionContext
| -rw-r--r-- | compiler/rustc_infer/src/traits/engine.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/fulfill.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 65 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/compare_method.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 11 |
5 files changed, 101 insertions, 23 deletions
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 2710debea94..d60388b31c1 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,5 +1,6 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; +use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness}; @@ -49,11 +50,28 @@ pub trait TraitEngine<'tcx>: 'tcx { infcx: &InferCtxt<'_, '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( &mut self, infcx: &InferCtxt<'_, '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>>; } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index cf50c34530e..4c5d8b5ec79 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -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::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; +use rustc_hir as hir; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_middle::mir::abstract_const::NotConstEvaluatable; 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) } } + 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( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -236,6 +253,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { 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>> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5321993f0ce..f7c66f8b284 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -130,6 +130,9 @@ pub struct SelectionContext<'cx, 'tcx> { /// and a negative impl 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 /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -221,6 +224,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, + const_impls_required: false, query_mode: TraitQueryMode::Standard, } } @@ -232,6 +236,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: true, intercrate_ambiguity_causes: None, allow_negative_impls: false, + const_impls_required: false, query_mode: TraitQueryMode::Standard, } } @@ -247,6 +252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls, + const_impls_required: false, query_mode: TraitQueryMode::Standard, } } @@ -262,10 +268,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, + const_impls_required: false, 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 /// used in coherence to give improved diagnostics. We don't do /// this until we detect a coherence error because it can lead to @@ -1024,26 +1046,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Respect const trait obligations - if let hir::Constness::Const = obligation.predicate.skip_binder().constness { - if Some(obligation.predicate.skip_binder().trait_ref.def_id) - != tcx.lang_items().sized_trait() - // const Sized bounds are skipped - { - match candidate { - // const impl - ImplCandidate(def_id) - if tcx.impl_constness(def_id) == hir::Constness::Const => {} - // const param - ParamCandidate(ty::ConstnessAnd { - constness: hir::Constness::Const, .. - }) => {} - // auto trait impl - AutoImplCandidate(..) => {} - // FIXME check if this is right, but this would allow Sized impls - // BuiltinCandidate { .. } => {} - _ => { - // reject all other types of candidates - return Err(Unimplemented); + if self.const_impls_required { + if let hir::Constness::Const = obligation.predicate.skip_binder().constness { + if Some(obligation.predicate.skip_binder().trait_ref.def_id) + != tcx.lang_items().sized_trait() + // const Sized bounds are skipped + { + match candidate { + // const impl + ImplCandidate(def_id) + if tcx.impl_constness(def_id) == hir::Constness::Const => {} + // const param + ParamCandidate(ty::ConstnessAnd { + constness: hir::Constness::Const, + .. + }) => {} + // auto trait impl + AutoImplCandidate(..) => {} + // FIXME check if this is right, but this would allow Sized impls + // BuiltinCandidate { .. } => {} + _ => { + // reject all other types of candidates + return Err(Unimplemented); + } } } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 01890f75026..0ce2746b128 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1354,7 +1354,9 @@ pub fn check_type_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // 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); return Err(ErrorReported); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index ee226aa82c6..c13901ae8be 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -714,7 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn select_all_obligations_or_error(&self) { 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); } } @@ -725,7 +729,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: bool, 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 { mutate_fulfillment_errors(&mut errors); self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred); |
