Skip to content

Commit

Permalink
Add constness field to ty::Predicate::Trait
Browse files Browse the repository at this point in the history
  • Loading branch information
ecstatic-morse committed Jan 20, 2020
1 parent 1a3bd57 commit ab3081a
Show file tree
Hide file tree
Showing 27 changed files with 104 additions and 55 deletions.
9 changes: 6 additions & 3 deletions src/librustc/traits/auto_trait.rs
Expand Up @@ -337,7 +337,10 @@ impl AutoTraitFinder<'tcx> {
&Err(SelectionError::Unimplemented) => {
if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
already_visited.remove(&pred);
self.add_user_pred(&mut user_computed_preds, ty::Predicate::Trait(pred));
self.add_user_pred(
&mut user_computed_preds,
ty::Predicate::Trait(pred, ast::Constness::NotConst),
);
predicates.push_back(pred);
} else {
debug!(
Expand Down Expand Up @@ -405,7 +408,7 @@ impl AutoTraitFinder<'tcx> {
let mut should_add_new = true;
user_computed_preds.retain(|&old_pred| {
match (&new_pred, old_pred) {
(&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => {
(&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
if new_trait.def_id() == old_trait.def_id() {
let new_substs = new_trait.skip_binder().trait_ref.substs;
let old_substs = old_trait.skip_binder().trait_ref.substs;
Expand Down Expand Up @@ -627,7 +630,7 @@ impl AutoTraitFinder<'tcx> {
// We check this by calling is_of_param on the relevant types
// from the various possible predicates
match &predicate {
&ty::Predicate::Trait(p) => {
&ty::Predicate::Trait(p, _) => {
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
&& !only_projections
&& is_new_pred
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/fulfill.rs
Expand Up @@ -331,7 +331,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}

match obligation.predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
let trait_obligation = obligation.with(data.clone());

if data.is_global() {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/object_safety.rs
Expand Up @@ -234,7 +234,7 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
.map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref))
.any(|predicate| {
match predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
// In the case of a trait predicate, we can skip the "self" type.
data.skip_binder().input_types().skip(1).any(has_self_ty)
}
Expand Down Expand Up @@ -285,7 +285,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
ty::Predicate::Trait(ref trait_pred) => {
ty::Predicate::Trait(ref trait_pred, _) => {
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
}
ty::Predicate::Projection(..)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/query/type_op/prove_predicate.rs
Expand Up @@ -24,7 +24,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
// `&T`, accounts for about 60% percentage of the predicates
// we have to prove. No need to canonicalize and all that for
// such cases.
if let Predicate::Trait(trait_ref) = key.value.predicate {
if let Predicate::Trait(trait_ref, _) = key.value.predicate {
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized_def_id {
if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
Expand Down
10 changes: 6 additions & 4 deletions src/librustc/traits/select.rs
Expand Up @@ -51,7 +51,7 @@ use std::cmp;
use std::fmt::{self, Display};
use std::iter;
use std::rc::Rc;
use syntax::attr;
use syntax::{ast, attr};

pub struct SelectionContext<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,
Expand Down Expand Up @@ -718,7 +718,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}

match obligation.predicate {
ty::Predicate::Trait(ref t) => {
ty::Predicate::Trait(ref t, _) => {
debug_assert!(!t.has_escaping_bound_vars());
let obligation = obligation.with(t.clone());
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
Expand Down Expand Up @@ -945,7 +945,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// trait refs. This is important because it's only a cycle
// if the regions match exactly.
let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
let cycle = cycle.map(|stack| {
ty::Predicate::Trait(stack.obligation.predicate, ast::Constness::NotConst)
});
if self.coinductive_match(cycle) {
debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
Some(EvaluatedToOk)
Expand Down Expand Up @@ -1060,7 +1062,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
let result = match predicate {
ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()),
ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
_ => false,
};
debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/traits/util.rs
Expand Up @@ -13,8 +13,8 @@ use super::{Normalized, Obligation, ObligationCause, PredicateObligation, Select

fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
match *pred {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data))
ty::Predicate::Trait(ref data, constness) => {
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
}

ty::Predicate::RegionOutlives(ref data) => {
Expand Down Expand Up @@ -127,7 +127,7 @@ impl Elaborator<'tcx> {
fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
let tcx = self.visited.tcx;
match *predicate {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());

Expand Down Expand Up @@ -471,7 +471,7 @@ impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<

fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
while let Some(pred) = self.base_iterator.next() {
if let ty::Predicate::Trait(data) = pred {
if let ty::Predicate::Trait(data, _) = pred {
return Some(data.to_poly_trait_ref());
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/wf.rs
Expand Up @@ -62,7 +62,7 @@ pub fn predicate_obligations<'a, 'tcx>(

// (*) ok to skip binders, because wf code is prepared for it
match *predicate {
ty::Predicate::Trait(ref t) => {
ty::Predicate::Trait(ref t, _) => {
wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
}
ty::Predicate::RegionOutlives(..) => {}
Expand Down Expand Up @@ -245,7 +245,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
}
}
ty::Predicate::Trait(proj) => {
ty::Predicate::Trait(proj, _) => {
// An associated item obligation born out of the `trait` failed to be met.
// Point at the `impl` that failed the obligation, the associated item that
// needed to meet the obligation, and the definition of that associated item,
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/ty/fold.rs
Expand Up @@ -150,6 +150,15 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
}
}

impl TypeFoldable<'tcx> for syntax::ast::Constness {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
}
}

/// The `TypeFolder` trait defines the actual *folding*. There is a
/// method defined for every foldable type. Each of these has a
/// default implementation that does an "identity" fold. Within each
Expand Down
21 changes: 14 additions & 7 deletions src/librustc/ty/mod.rs
Expand Up @@ -1068,7 +1068,11 @@ pub enum Predicate<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
Trait(PolyTraitPredicate<'tcx>),
///
/// A trait predicate will have `Constness::Const` if it originates
/// from a bound on a `const fn` without the `?const` opt-out (e.g.,
/// `const fn foobar<Foo: Bar>() {}`).
Trait(PolyTraitPredicate<'tcx>, ast::Constness),

/// `where 'a: 'b`
RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
Expand Down Expand Up @@ -1191,8 +1195,8 @@ impl<'tcx> Predicate<'tcx> {

let substs = &trait_ref.skip_binder().substs;
match *self {
Predicate::Trait(ref binder) => {
Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs)))
Predicate::Trait(ref binder, constness) => {
Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs)), constness)
}
Predicate::Subtype(ref binder) => {
Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs)))
Expand Down Expand Up @@ -1338,13 +1342,16 @@ pub trait ToPredicate<'tcx> {

impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() }))
ty::Predicate::Trait(
ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() }),
ast::Constness::NotConst,
)
}
}

impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> {
fn to_predicate(&self) -> Predicate<'tcx> {
ty::Predicate::Trait(self.to_poly_trait_predicate())
ty::Predicate::Trait(self.to_poly_trait_predicate(), ast::Constness::NotConst)
}
}

Expand Down Expand Up @@ -1413,7 +1420,7 @@ impl<'tcx> Predicate<'tcx> {
/// with depth 0 are bound by the predicate.
pub fn walk_tys(&'a self) -> impl Iterator<Item = Ty<'tcx>> + 'a {
match *self {
ty::Predicate::Trait(ref data) => {
ty::Predicate::Trait(ref data, _) => {
WalkTysIter::InputTypes(data.skip_binder().input_types())
}
ty::Predicate::Subtype(binder) => {
Expand All @@ -1439,7 +1446,7 @@ impl<'tcx> Predicate<'tcx> {

pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
match *self {
Predicate::Trait(ref t) => Some(t.to_poly_trait_ref()),
Predicate::Trait(ref t, _) => Some(t.to_poly_trait_ref()),
Predicate::Projection(..)
| Predicate::Subtype(..)
| Predicate::RegionOutlives(..)
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/ty/print/pretty.rs
Expand Up @@ -1791,7 +1791,12 @@ define_print_and_forward_display! {

ty::Predicate<'tcx> {
match *self {
ty::Predicate::Trait(ref data) => p!(print(data)),
ty::Predicate::Trait(ref data, constness) => {
if let ast::Constness::Const = constness {
p!(write("const "));
}
p!(print(data))
}
ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
Expand Down
12 changes: 10 additions & 2 deletions src/librustc/ty/structural_impls.rs
Expand Up @@ -15,6 +15,7 @@ use smallvec::SmallVec;
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use syntax::ast;

impl fmt::Debug for ty::GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down Expand Up @@ -234,7 +235,12 @@ impl fmt::Debug for ty::ProjectionPredicate<'tcx> {
impl fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ty::Predicate::Trait(ref a) => a.fmt(f),
ty::Predicate::Trait(ref a, constness) => {
if let ast::Constness::Const = constness {
write!(f, "const ")?;
}
a.fmt(f)
}
ty::Predicate::Subtype(ref pair) => pair.fmt(f),
ty::Predicate::RegionOutlives(ref pair) => pair.fmt(f),
ty::Predicate::TypeOutlives(ref pair) => pair.fmt(f),
Expand Down Expand Up @@ -474,7 +480,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> {
type Lifted = ty::Predicate<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match *self {
ty::Predicate::Trait(ref binder) => tcx.lift(binder).map(ty::Predicate::Trait),
ty::Predicate::Trait(ref binder, constness) => {
tcx.lift(binder).map(|binder| ty::Predicate::Trait(binder, constness))
}
ty::Predicate::Subtype(ref binder) => tcx.lift(binder).map(ty::Predicate::Subtype),
ty::Predicate::RegionOutlives(ref binder) => {
tcx.lift(binder).map(ty::Predicate::RegionOutlives)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/unused.rs
Expand Up @@ -144,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
ty::Opaque(def, _) => {
let mut has_emitted = false;
for (predicate, _) in cx.tcx.predicates_of(def).predicates {
if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
let def_id = trait_ref.def_id;
let descr_pre =
Expand Down
21 changes: 14 additions & 7 deletions src/librustc_mir/borrow_check/type_check/mod.rs
Expand Up @@ -33,6 +33,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::vec::{Idx, IndexVec};
use rustc_span::{Span, DUMMY_SP};
use syntax::ast;

use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
Expand Down Expand Up @@ -1931,12 +1932,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
traits::ObligationCauseCode::RepeatVec(should_suggest),
),
self.param_env,
ty::Predicate::Trait(ty::Binder::bind(ty::TraitPredicate {
trait_ref: ty::TraitRef::new(
self.tcx().lang_items().copy_trait().unwrap(),
tcx.mk_substs_trait(ty, &[]),
),
})),
ty::Predicate::Trait(
ty::Binder::bind(ty::TraitPredicate {
trait_ref: ty::TraitRef::new(
self.tcx().lang_items().copy_trait().unwrap(),
tcx.mk_substs_trait(ty, &[]),
),
}),
ast::Constness::NotConst,
),
),
&traits::SelectionError::Unimplemented,
false,
Expand Down Expand Up @@ -2574,7 +2578,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
category: ConstraintCategory,
) {
self.prove_predicates(
Some(ty::Predicate::Trait(trait_ref.to_poly_trait_ref().to_poly_trait_predicate())),
Some(ty::Predicate::Trait(
trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
ast::Constness::NotConst,
)),
locations,
category,
);
Expand Down
11 changes: 9 additions & 2 deletions src/librustc_mir/transform/qualify_min_const_fn.rs
Expand Up @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use std::borrow::Cow;
use syntax::attr;
use syntax::{ast, attr};

type McfResult = Result<(), (Span, Cow<'static, str>)>;

Expand All @@ -27,12 +27,19 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
bug!("closure kind predicate on function: {:#?}", predicate)
}
Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
Predicate::Trait(pred) => {
Predicate::Trait(pred, constness) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
match pred.skip_binder().self_ty().kind {
ty::Param(ref p) => {
// Allow `T: ?const Trait`
if *constness == ast::Constness::NotConst
&& feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
{
continue;
}

let generics = tcx.generics_of(current);
let def = generics.type_param(p, tcx);
let span = tcx.def_span(def.def_id);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_privacy/lib.rs
Expand Up @@ -93,7 +93,7 @@ where
let ty::GenericPredicates { parent: _, predicates } = predicates;
for (predicate, _span) in predicates {
match predicate {
ty::Predicate::Trait(poly_predicate) => {
ty::Predicate::Trait(poly_predicate, _) => {
let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder();
if self.visit_trait(trait_ref) {
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_traits/lowering/mod.rs
Expand Up @@ -94,7 +94,7 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
use rustc::ty::Predicate;

match self {
Predicate::Trait(predicate) => predicate.lower(),
Predicate::Trait(predicate, _) => predicate.lower(),
Predicate::RegionOutlives(predicate) => predicate.lower(),
Predicate::TypeOutlives(predicate) => predicate.lower(),
Predicate::Projection(predicate) => predicate.lower(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/astconv.rs
Expand Up @@ -1490,7 +1490,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref
);
match trait_ref {
ty::Predicate::Trait(pred) => {
ty::Predicate::Trait(pred, constness) => {
associated_types.entry(span).or_default().extend(
tcx.associated_items(pred.def_id())
.filter(|item| item.kind == ty::AssocKind::Type)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/coercion.rs
Expand Up @@ -565,7 +565,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let obligation = queue.remove(0);
debug!("coerce_unsized resolve step: {:?}", obligation);
let trait_ref = match obligation.predicate {
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
ty::Predicate::Trait(ref tr, _) if traits.contains(&tr.def_id()) => {
if unsize_did == tr.def_id() {
let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind;
if let ty::Tuple(..) = sty {
Expand Down

0 comments on commit ab3081a

Please sign in to comment.