Skip to content

Commit

Permalink
Use the constness from the param env instead of having a separate dim…
Browse files Browse the repository at this point in the history
…ension for it

This breaks a ~const test that will be fixed in a follow up commit of this PR
  • Loading branch information
oli-obk authored and fee1-dead committed Nov 29, 2021
1 parent 19f2101 commit d51068c
Show file tree
Hide file tree
Showing 12 changed files with 25 additions and 142 deletions.
Expand Up @@ -817,8 +817,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
);

let implsrc = tcx.infer_ctxt().enter(|infcx| {
let mut selcx =
SelectionContext::with_constness(&infcx, hir::Constness::Const);
let mut selcx = SelectionContext::new(&infcx);
selcx.select(&obligation)
});

Expand Down
Expand Up @@ -3,7 +3,6 @@
//! See the `Qualif` trait for more info.

use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
Expand Down Expand Up @@ -167,7 +166,7 @@ impl Qualif for NeedsNonConstDrop {
);

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)
});
!matches!(
Expand Down
20 changes: 2 additions & 18 deletions compiler/rustc_infer/src/traits/engine.rs
@@ -1,7 +1,6 @@
use crate::infer::InferCtxt;
use crate::traits::Obligation;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};

Expand Down Expand Up @@ -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_with_constness_or_error(
fn select_where_possible(
&mut self,
infcx: &InferCtxt<'_, 'tcx>,
_constness: hir::Constness,
) -> 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)
}
) -> Vec<FulfillmentError<'tcx>>;

fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;

Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_infer/src/traits/mod.rs
Expand Up @@ -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.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PredicateObligation<'_>, 32);
Expand Down
39 changes: 2 additions & 37 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Expand Up @@ -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::{ObligationForest, ObligationProcessor};
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
Expand Down Expand Up @@ -231,21 +230,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
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(
&mut self,
infcx: &InferCtxt<'_, 'tcx>,
Expand All @@ -254,15 +238,6 @@ 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,
) -> 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())
}
Expand Down Expand Up @@ -679,12 +654,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
if obligation.predicate.is_known_global() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
//
// 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)
{
if infcx.predicate_must_hold_considering_regions(obligation) {
debug!(
"selecting trait at depth {} evaluated to holds",
obligation.recursion_depth
Expand Down Expand Up @@ -738,12 +708,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
if obligation.predicate.is_global(tcx) {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
//
// 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)
{
if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
return ProcessResult::Changed(vec![]);
} else {
tracing::debug!("Does NOT hold: {:?}", obligation);
Expand Down
Expand Up @@ -303,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else if lang_items.drop_trait() == Some(def_id)
&& 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)?;
} else {
debug!("passing ~const Drop bound; in non-const context");
Expand Down
38 changes: 1 addition & 37 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Expand Up @@ -128,9 +128,6 @@ pub struct SelectionContext<'cx, 'tcx> {
/// and a negative impl
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
/// policy. In essence, canonicalized queries need their errors propagated
/// rather than immediately reported because we do not have accurate spans.
Expand Down Expand Up @@ -222,7 +219,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
is_in_const_context: false,
query_mode: TraitQueryMode::Standard,
}
}
Expand All @@ -234,7 +230,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: true,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
is_in_const_context: false,
query_mode: TraitQueryMode::Standard,
}
}
Expand All @@ -250,7 +245,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls,
is_in_const_context: false,
query_mode: TraitQueryMode::Standard,
}
}
Expand All @@ -266,26 +260,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
is_in_const_context: 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,
is_in_const_context: 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
Expand Down Expand Up @@ -318,20 +296,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
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
//
Expand Down Expand Up @@ -1138,7 +1102,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

for candidate in candidates {
// Respect const trait obligations
if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
if obligation.is_const() {
match candidate {
// const impl
ImplCandidate(def_id)
Expand Down
10 changes: 2 additions & 8 deletions compiler/rustc_typeck/src/check/compare_method.rs
Expand Up @@ -1388,13 +1388,7 @@ pub fn check_type_bounds<'tcx>(
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);

tcx.infer_ctxt().enter(move |infcx| {
let constness = impl_ty
.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 inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
let infcx = &inh.infcx;
let mut selcx = traits::SelectionContext::new(&infcx);

Expand Down Expand Up @@ -1439,7 +1433,7 @@ pub fn check_type_bounds<'tcx>(
// Check that all obligations are satisfied by the implementation's
// version.
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() {
infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorReported);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Expand Up @@ -613,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let errors = self
.fulfillment_cx
.borrow_mut()
.select_all_with_constness_or_error(&self, self.inh.constness);
.select_all_or_error(&self);

if !errors.is_empty() {
self.report_fulfillment_errors(&errors, self.inh.body_id, false);
Expand All @@ -629,7 +629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut result = self
.fulfillment_cx
.borrow_mut()
.select_with_constness_where_possible(self, self.inh.constness);
.select_where_possible(self);
if !result.is_empty() {
mutate_fulfillment_errors(&mut result);
self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
Expand Down
14 changes: 0 additions & 14 deletions compiler/rustc_typeck/src/check/inherited.rs
Expand Up @@ -53,9 +53,6 @@ pub struct Inherited<'a, 'tcx> {
pub(super) deferred_generator_interiors:
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>,

/// Whenever we introduce an adjustment from `!` into a type variable,
Expand Down Expand Up @@ -102,16 +99,6 @@ impl<'tcx> InheritedBuilder<'tcx> {

impl Inherited<'a, 'tcx> {
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 item_id = tcx.hir().local_def_id_to_hir_id(def_id);
let body_id = tcx.hir().maybe_body_owned_by(item_id);
Expand All @@ -128,7 +115,6 @@ impl Inherited<'a, 'tcx> {
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_generator_interiors: RefCell::new(Vec::new()),
diverging_type_vars: RefCell::new(Default::default()),
constness,
body_id,
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
@@ -1,6 +1,6 @@
// FIXME(fee1-dead): this should have a better error message
#![feature(const_trait_impl)]

// check-pass
struct NonConstAdd(i32);

impl std::ops::Add for NonConstAdd {
Expand Down Expand Up @@ -29,3 +29,5 @@ impl const Baz for NonConstAdd {
}

fn main() {}

// TODO: this test should not pass
20 changes: 0 additions & 20 deletions src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr

This file was deleted.

0 comments on commit d51068c

Please sign in to comment.