Skip to content

Commit 25c3534

Browse files
committed
Pass constness to SelectionContext
1 parent 3ef7997 commit 25c3534

File tree

5 files changed

+101
-23
lines changed

5 files changed

+101
-23
lines changed

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::infer::InferCtxt;
22
use crate::traits::Obligation;
3+
use rustc_hir as hir;
34
use rustc_hir::def_id::DefId;
45
use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
56

@@ -49,11 +50,28 @@ pub trait TraitEngine<'tcx>: 'tcx {
4950
infcx: &InferCtxt<'_, 'tcx>,
5051
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
5152

53+
fn select_all_with_constness_or_error(
54+
&mut self,
55+
infcx: &InferCtxt<'_, 'tcx>,
56+
_constness: hir::Constness,
57+
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
58+
self.select_all_or_error(infcx)
59+
}
60+
5261
fn select_where_possible(
5362
&mut self,
5463
infcx: &InferCtxt<'_, 'tcx>,
5564
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
5665

66+
// FIXME this should not provide a default body for chalk as chalk should be updated
67+
fn select_with_constness_where_possible(
68+
&mut self,
69+
infcx: &InferCtxt<'_, 'tcx>,
70+
_constness: hir::Constness,
71+
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
72+
self.select_where_possible(infcx)
73+
}
74+
5775
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
5876
}
5977

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_data_structures::obligation_forest::ProcessResult;
33
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
44
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
55
use rustc_errors::ErrorReported;
6+
use rustc_hir as hir;
67
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
78
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
89
use rustc_middle::mir::interpret::ErrorHandled;
@@ -228,6 +229,22 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
228229
if errors.is_empty() { Ok(()) } else { Err(errors) }
229230
}
230231

232+
fn select_all_with_constness_or_error(
233+
&mut self,
234+
infcx: &InferCtxt<'_, 'tcx>,
235+
constness: rustc_hir::Constness,
236+
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
237+
self.select_with_constness_where_possible(infcx, constness)?;
238+
239+
let errors: Vec<_> = self
240+
.predicates
241+
.to_errors(CodeAmbiguity)
242+
.into_iter()
243+
.map(to_fulfillment_error)
244+
.collect();
245+
if errors.is_empty() { Ok(()) } else { Err(errors) }
246+
}
247+
231248
fn select_where_possible(
232249
&mut self,
233250
infcx: &InferCtxt<'_, 'tcx>,
@@ -236,6 +253,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
236253
self.select(&mut selcx)
237254
}
238255

256+
fn select_with_constness_where_possible(
257+
&mut self,
258+
infcx: &InferCtxt<'_, 'tcx>,
259+
constness: hir::Constness,
260+
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
261+
let mut selcx = SelectionContext::with_constness(infcx, constness);
262+
self.select(&mut selcx)
263+
}
264+
239265
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
240266
self.predicates.map_pending_obligations(|o| o.obligation.clone())
241267
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ pub struct SelectionContext<'cx, 'tcx> {
130130
/// and a negative impl
131131
allow_negative_impls: bool,
132132

133+
/// Do we only want const impls when we have a const trait predicate?
134+
const_impls_required: bool,
135+
133136
/// The mode that trait queries run in, which informs our error handling
134137
/// policy. In essence, canonicalized queries need their errors propagated
135138
/// rather than immediately reported because we do not have accurate spans.
@@ -221,6 +224,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
221224
intercrate: false,
222225
intercrate_ambiguity_causes: None,
223226
allow_negative_impls: false,
227+
const_impls_required: false,
224228
query_mode: TraitQueryMode::Standard,
225229
}
226230
}
@@ -232,6 +236,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
232236
intercrate: true,
233237
intercrate_ambiguity_causes: None,
234238
allow_negative_impls: false,
239+
const_impls_required: false,
235240
query_mode: TraitQueryMode::Standard,
236241
}
237242
}
@@ -247,6 +252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
247252
intercrate: false,
248253
intercrate_ambiguity_causes: None,
249254
allow_negative_impls,
255+
const_impls_required: false,
250256
query_mode: TraitQueryMode::Standard,
251257
}
252258
}
@@ -262,10 +268,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
262268
intercrate: false,
263269
intercrate_ambiguity_causes: None,
264270
allow_negative_impls: false,
271+
const_impls_required: false,
265272
query_mode,
266273
}
267274
}
268275

276+
pub fn with_constness(
277+
infcx: &'cx InferCtxt<'cx, 'tcx>,
278+
constness: hir::Constness,
279+
) -> SelectionContext<'cx, 'tcx> {
280+
SelectionContext {
281+
infcx,
282+
freshener: infcx.freshener_keep_static(),
283+
intercrate: false,
284+
intercrate_ambiguity_causes: None,
285+
allow_negative_impls: false,
286+
const_impls_required: matches!(constness, hir::Constness::Const),
287+
query_mode: TraitQueryMode::Standard,
288+
}
289+
}
290+
269291
/// Enables tracking of intercrate ambiguity causes. These are
270292
/// used in coherence to give improved diagnostics. We don't do
271293
/// this until we detect a coherence error because it can lead to
@@ -1024,26 +1046,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10241046
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
10251047
let tcx = self.tcx();
10261048
// Respect const trait obligations
1027-
if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
1028-
if Some(obligation.predicate.skip_binder().trait_ref.def_id)
1029-
!= tcx.lang_items().sized_trait()
1030-
// const Sized bounds are skipped
1031-
{
1032-
match candidate {
1033-
// const impl
1034-
ImplCandidate(def_id)
1035-
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
1036-
// const param
1037-
ParamCandidate(ty::ConstnessAnd {
1038-
constness: hir::Constness::Const, ..
1039-
}) => {}
1040-
// auto trait impl
1041-
AutoImplCandidate(..) => {}
1042-
// FIXME check if this is right, but this would allow Sized impls
1043-
// BuiltinCandidate { .. } => {}
1044-
_ => {
1045-
// reject all other types of candidates
1046-
return Err(Unimplemented);
1049+
if self.const_impls_required {
1050+
if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
1051+
if Some(obligation.predicate.skip_binder().trait_ref.def_id)
1052+
!= tcx.lang_items().sized_trait()
1053+
// const Sized bounds are skipped
1054+
{
1055+
match candidate {
1056+
// const impl
1057+
ImplCandidate(def_id)
1058+
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
1059+
// const param
1060+
ParamCandidate(ty::ConstnessAnd {
1061+
constness: hir::Constness::Const,
1062+
..
1063+
}) => {}
1064+
// auto trait impl
1065+
AutoImplCandidate(..) => {}
1066+
// FIXME check if this is right, but this would allow Sized impls
1067+
// BuiltinCandidate { .. } => {}
1068+
_ => {
1069+
// reject all other types of candidates
1070+
return Err(Unimplemented);
1071+
}
10471072
}
10481073
}
10491074
}

compiler/rustc_typeck/src/check/compare_method.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,9 @@ pub fn check_type_bounds<'tcx>(
13541354

13551355
// Check that all obligations are satisfied by the implementation's
13561356
// version.
1357-
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
1357+
if let Err(ref errors) =
1358+
inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
1359+
{
13581360
infcx.report_fulfillment_errors(errors, None, false);
13591361
return Err(ErrorReported);
13601362
}

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
739739

740740
pub(in super::super) fn select_all_obligations_or_error(&self) {
741741
debug!("select_all_obligations_or_error");
742-
if let Err(errors) = self.fulfillment_cx.borrow_mut().select_all_or_error(&self) {
742+
if let Err(errors) = self
743+
.fulfillment_cx
744+
.borrow_mut()
745+
.select_all_with_constness_or_error(&self, self.inh.constness)
746+
{
743747
self.report_fulfillment_errors(&errors, self.inh.body_id, false);
744748
}
745749
}
@@ -750,7 +754,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
750754
fallback_has_occurred: bool,
751755
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
752756
) {
753-
let result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
757+
let result = self
758+
.fulfillment_cx
759+
.borrow_mut()
760+
.select_with_constness_where_possible(self, self.inh.constness);
754761
if let Err(mut errors) = result {
755762
mutate_fulfillment_errors(&mut errors);
756763
self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);

0 commit comments

Comments
 (0)