&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!(
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;
// 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
}
match obligation.predicate {
- ty::Predicate::Trait(ref data) => {
+ ty::Predicate::Trait(ref data, _) => {
let trait_obligation = obligation.with(data.clone());
if data.is_global() {
.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)
}
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(..)
// `&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) {
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>,
}
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)
// 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)
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);
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) => {
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());
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());
}
}
// (*) 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(..) => {}
}
}
}
- 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,
}
}
+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
/// 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>),
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)))
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)
}
}
/// 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) => {
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(..)
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)),
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 {
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),
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)
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 =
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;
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,
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,
);
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>)>;
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);
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;
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(),
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)
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 {
let predicate_matches_closure = |p: &'_ Predicate<'tcx>| {
let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
match (predicate, p) {
- (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(),
+ (Predicate::Trait(a, _), Predicate::Trait(b, _)) => relator.relate(a, b).is_ok(),
(Predicate::Projection(a), Predicate::Projection(b)) => {
relator.relate(a, b).is_ok()
}
traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
.filter_map(|predicate| match predicate {
- ty::Predicate::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => {
+ ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
Some(trait_pred)
}
_ => None,
// FIXME: do we want to commit to this behavior for param bounds?
let bounds = self.param_env.caller_bounds.iter().filter_map(|predicate| match *predicate {
- ty::Predicate::Trait(ref trait_predicate) => {
+ ty::Predicate::Trait(ref trait_predicate, _) => {
match trait_predicate.skip_binder().trait_ref.self_ty().kind {
ty::Param(ref p) if *p == param_ty => Some(trait_predicate.to_poly_trait_ref()),
_ => None,
let o = self.resolve_vars_if_possible(&o);
if !self.predicate_may_hold(&o) {
result = ProbeResult::NoMatch;
- if let &ty::Predicate::Trait(ref pred) = &o.predicate {
+ if let &ty::Predicate::Trait(ref pred, _) = &o.predicate {
possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);
}
}
parent: None,
predicates: tcx.arena.alloc_from_iter(self.param_env.caller_bounds.iter().filter_map(
|&predicate| match predicate {
- ty::Predicate::Trait(ref data)
+ ty::Predicate::Trait(ref data, _)
if data.skip_binder().self_ty().is_param(index) =>
{
// HACK(eddyb) should get the original `Span`.
ty::Predicate::Projection(ref data) => {
Some((data.to_poly_trait_ref(self.tcx), obligation))
}
- ty::Predicate::Trait(ref data) => Some((data.to_poly_trait_ref(), obligation)),
+ ty::Predicate::Trait(ref data, _) => Some((data.to_poly_trait_ref(), obligation)),
ty::Predicate::Subtype(..) => None,
ty::Predicate::RegionOutlives(..) => None,
ty::Predicate::TypeOutlives(..) => None,
continue;
}
- if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
+ if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate {
// Collect the argument position for all arguments that could have caused this
// `FulfillmentError`.
let mut referenced_in = final_arg_types
if let hir::ExprKind::Path(qpath) = &path.kind {
if let hir::QPath::Resolved(_, path) = &qpath {
for error in errors {
- if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
+ if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate {
// If any of the type arguments in this path segment caused the
// `FullfillmentError`, point at its span (#61860).
for arg in path
icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
.into_iter()
.filter(|(predicate, _)| match predicate {
- ty::Predicate::Trait(ref data) => data.skip_binder().self_ty().is_param(index),
+ ty::Predicate::Trait(ref data, _) => data.skip_binder().self_ty().is_param(index),
_ => false,
}),
);
// which will, in turn, reach indirect supertraits.
for &(pred, span) in superbounds {
debug!("superbound: {:?}", pred);
- if let ty::Predicate::Trait(bound) = pred {
+ if let ty::Predicate::Trait(bound, _) = pred {
tcx.at(span).super_predicates_of(bound.def_id());
}
}
.filter(|p| {
!orig_bounds.contains(p)
|| match p {
- &&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait,
+ ty::Predicate::Trait(pred, _) => pred.def_id() == sized_trait,
_ => false,
}
})
use rustc::ty::Predicate;
match *self {
- Predicate::Trait(ref pred) => Some(pred.clean(cx)),
+ Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
Predicate::TypeOutlives(ref pred) => pred.clean(cx),
.predicates
.iter()
.filter_map(|(pred, _)| {
- if let ty::Predicate::Trait(ref pred) = *pred {
+ if let ty::Predicate::Trait(ref pred, _) = *pred {
if pred.skip_binder().trait_ref.self_ty() == self_ty {
Some(pred.def_id())
} else {
}
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(HashStable_Generic)]
pub enum Constness {
Const,
NotConst,