Skip to content

Commit

Permalink
Add ty::BoundConstness
Browse files Browse the repository at this point in the history
  • Loading branch information
fee1-dead committed Aug 27, 2021
1 parent c75aeaa commit 80e1ee5
Show file tree
Hide file tree
Showing 18 changed files with 80 additions and 80 deletions.
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::Constness;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec;
Expand Down Expand Up @@ -497,7 +496,7 @@ pub enum ImplSource<'tcx, N> {
/// for some type parameter. The `Vec<N>` represents the
/// obligations incurred from normalizing the where-clause (if
/// any).
Param(Vec<N>, Constness),
Param(Vec<N>, ty::BoundConstness),

/// Virtual calls through an object.
Object(ImplSourceObjectData<'tcx, N>),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<T> ExpectedFound<T> {
#[derive(Clone, Debug, TypeFoldable)]
pub enum TypeError<'tcx> {
Mismatch,
ConstnessMismatch(ExpectedFound<hir::Constness>),
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
AbiMismatch(ExpectedFound<abi::Abi>),
Mutability,
Expand Down Expand Up @@ -102,7 +102,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
Mismatch => write!(f, "types differ"),
ConstnessMismatch(values) => {
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
write!(f, "expected {} bound, found {} bound", values.expected, values.found)
}
UnsafetyMismatch(values) => {
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
Expand Down
35 changes: 26 additions & 9 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
use rustc_hir::{Constness, Node};
use rustc_hir::Node;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
Expand Down Expand Up @@ -181,6 +181,25 @@ pub enum Visibility {
Invisible,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum BoundConstness {
/// `T: Trait`
NotConst,
/// `T: ~const Trait`
///
/// Requires resolving to const only when we are in a const context.
ConstIfConst,
}

impl fmt::Display for BoundConstness {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotConst => f.write_str("normal"),
Self::ConstIfConst => f.write_str("`~const`"),
}
}
}

#[derive(
Clone,
Debug,
Expand Down Expand Up @@ -628,9 +647,7 @@ impl<'tcx> Predicate<'tcx> {
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,

/// A trait predicate will have `Constness::Const` if it originates
/// from a bound marked with `~const`.
pub constness: hir::Constness,
pub constness: BoundConstness,
}

pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
Expand Down Expand Up @@ -1299,26 +1316,26 @@ impl<'tcx> ParamEnv<'tcx> {

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
pub struct ConstnessAnd<T> {
pub constness: Constness,
pub constness: BoundConstness,
pub value: T,
}

// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
// the constness of trait bounds is being propagated correctly.
pub trait WithConstness: Sized {
#[inline]
fn with_constness(self, constness: Constness) -> ConstnessAnd<Self> {
fn with_constness(self, constness: BoundConstness) -> ConstnessAnd<Self> {
ConstnessAnd { constness, value: self }
}

#[inline]
fn with_const(self) -> ConstnessAnd<Self> {
self.with_constness(Constness::Const)
fn with_const_if_const(self) -> ConstnessAnd<Self> {
self.with_constness(BoundConstness::ConstIfConst)
}

#[inline]
fn without_const(self) -> ConstnessAnd<Self> {
self.with_constness(Constness::NotConst)
self.with_constness(BoundConstness::NotConst)
}
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
}
}

impl<'tcx> Relate<'tcx> for ast::Constness {
impl<'tcx> Relate<'tcx> for ty::BoundConstness {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ast::Constness,
b: ast::Constness,
) -> RelateResult<'tcx, ast::Constness> {
a: ty::BoundConstness,
b: ty::BoundConstness,
) -> RelateResult<'tcx, ty::BoundConstness> {
if a != b {
Err(TypeError::ConstnessMismatch(expected_found(relation, a, b)))
} else {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
use rustc_data_structures::functor::IdFunctor;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::CRATE_DEF_INDEX;
use rustc_index::vec::{Idx, IndexVec};
Expand Down Expand Up @@ -155,8 +154,8 @@ impl fmt::Debug for ty::ParamConst {

impl fmt::Debug for ty::TraitPredicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let hir::Constness::Const = self.constness {
write!(f, "const ")?;
if let ty::BoundConstness::ConstIfConst = self.constness {
write!(f, "~const ")?;
}
write!(f, "TraitPredicate({:?})", self.trait_ref)
}
Expand Down Expand Up @@ -241,6 +240,7 @@ TrivialTypeFoldableAndLiftImpls! {
crate::traits::Reveal,
crate::ty::adjustment::AutoBorrowMutability,
crate::ty::AdtKind,
crate::ty::BoundConstness,
// Including `BoundRegionKind` is a *bit* dubious, but direct
// references to bound region appear in `ty::Error`, and aren't
// really meant to be folded. In general, we can only fold a fully
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
self.map_bound(|trait_ref| ty::TraitPredicate {
trait_ref,
constness: hir::Constness::NotConst,
constness: ty::BoundConstness::NotConst,
})
}
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_mir/src/borrow_check/type_check/canonical.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::fmt;

use rustc_hir as hir;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::traits::query::NoSolution;
use rustc_middle::mir::ConstraintCategory;
Expand Down Expand Up @@ -88,7 +87,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.prove_predicates(
Some(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: hir::Constness::NotConst,
constness: ty::BoundConstness::NotConst,
})),
locations,
category,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
param_env,
Binder::dummy(TraitPredicate {
trait_ref,
constness: hir::Constness::Const,
constness: ty::BoundConstness::ConstIfConst,
}),
);

Expand All @@ -831,7 +831,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
});

match implsrc {
Ok(Some(ImplSource::Param(_, hir::Constness::Const))) => {
Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
debug!(
"const_trait_impl: provided {:?} via where-clause in {:?}",
trait_ref, param_env
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ impl AutoTraitFinder<'tcx> {
def_id: trait_did,
substs: infcx.tcx.mk_substs_trait(ty, &[]),
},
constness: hir::Constness::NotConst,
constness: ty::BoundConstness::NotConst,
}));

let computed_preds = param_env.caller_bounds().iter();
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot(
let obligation = Obligation::new(
ObligationCause::dummy(),
ty::ParamEnv::reveal_all(),
ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: hir::Constness::NotConst }),
ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst }),
);

let implsrc = tcx.infer_ctxt().enter(|infcx| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
use rustc_hir::Constness;
use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
Expand Down Expand Up @@ -75,7 +74,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ProjectionCandidate(idx) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?;
// FIXME(jschievink): constness
Ok(ImplSource::Param(obligations, Constness::NotConst))
Ok(ImplSource::Param(obligations, ty::BoundConstness::NotConst))
}

ObjectCandidate(idx) => {
Expand Down Expand Up @@ -113,7 +112,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// This indicates something like `Trait + Send: Send`. In this case, we know that
// this holds because that's what the object type is telling us, and there's really
// no additional obligations to prove and no types in particular to unify, etc.
Ok(ImplSource::Param(Vec::new(), Constness::NotConst))
Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst))
}

BuiltinUnsizeCandidate => {
Expand Down
36 changes: 19 additions & 17 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::Constness;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::abstract_const::NotConstEvaluatable;
Expand Down Expand Up @@ -130,8 +129,8 @@ 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,
/// 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
Expand Down Expand Up @@ -224,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
const_impls_required: false,
is_in_const_context: false,
query_mode: TraitQueryMode::Standard,
}
}
Expand All @@ -236,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: true,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
const_impls_required: false,
is_in_const_context: false,
query_mode: TraitQueryMode::Standard,
}
}
Expand All @@ -252,7 +251,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls,
const_impls_required: false,
is_in_const_context: false,
query_mode: TraitQueryMode::Standard,
}
}
Expand All @@ -268,7 +267,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
const_impls_required: false,
is_in_const_context: false,
query_mode,
}
}
Expand All @@ -283,7 +282,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
intercrate: false,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
const_impls_required: matches!(constness, hir::Constness::Const),
is_in_const_context: matches!(constness, hir::Constness::Const),
query_mode: TraitQueryMode::Standard,
}
}
Expand Down Expand Up @@ -316,14 +315,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.tcx
}

/// Returns `true` if the trait predicate is considerd `const` to this selection context.
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
match pred.constness {
ty::BoundConstness::ConstIfConst if self.is_in_const_context => true,
_ => false
}
}

/// 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(ty::TraitPredicate {
constness: hir::Constness::Const,
..
}) if self.const_impls_required => true,
ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred),
_ => false,
}
}
Expand Down Expand Up @@ -1074,8 +1078,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
let tcx = self.tcx();
// Respect const trait obligations
if self.const_impls_required {
if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
if Some(obligation.predicate.skip_binder().trait_ref.def_id)
!= tcx.lang_items().sized_trait()
// const Sized bounds are skipped
Expand All @@ -1086,7 +1089,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
// const param
ParamCandidate(ty::ConstnessAnd {
constness: hir::Constness::Const,
constness: ty::BoundConstness::ConstIfConst,
..
}) => {}
// auto trait impl
Expand All @@ -1100,7 +1103,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
}
}
}
// Treat negative impls as unimplemented, and reservation impls as ambiguity.
if let ImplCandidate(def_id) = candidate {
Expand Down Expand Up @@ -1495,7 +1497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// probably best characterized as a "hack", since we might prefer to just do our
// best to *not* create essentially duplicate candidates in the first place.
other.value.bound_vars().len() <= victim.value.bound_vars().len()
} else if other.value == victim.value && victim.constness == Constness::NotConst {
} else if other.value == victim.value && victim.constness == ty::BoundConstness::NotConst {
// Drop otherwise equivalent non-const candidates in favor of const candidates.
true
} else {
Expand Down
Loading

0 comments on commit 80e1ee5

Please sign in to comment.