about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan MacKenzie <ecstaticmorse@gmail.com>2020-01-13 20:30:32 -0800
committerDylan MacKenzie <ecstaticmorse@gmail.com>2020-01-20 00:00:08 -0800
commitd2aefbb286c94240e25cbe0b8cc92a1336db5408 (patch)
tree0fa0e7fb17b128b2fcdd454efc945bca905159ae
parentab3081a70e5d402188c26c6f3e671a3c44812d1b (diff)
downloadrust-d2aefbb286c94240e25cbe0b8cc92a1336db5408.tar.gz
rust-d2aefbb286c94240e25cbe0b8cc92a1336db5408.zip
Add `ConstnessAnd` that implements `ToPredicate`
-rw-r--r--src/librustc/traits/engine.rs4
-rw-r--r--src/librustc/traits/error_reporting/mod.rs28
-rw-r--r--src/librustc/traits/error_reporting/suggestions.rs17
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/object_safety.rs6
-rw-r--r--src/librustc/traits/project.rs11
-rw-r--r--src/librustc/traits/select.rs4
-rw-r--r--src/librustc/traits/util.rs25
-rw-r--r--src/librustc/traits/wf.rs10
-rw-r--r--src/librustc/ty/mod.rs56
-rw-r--r--src/librustc/ty/sty.rs10
-rw-r--r--src/librustc_ty/ty.rs3
-rw-r--r--src/librustc_typeck/astconv.rs4
-rw-r--r--src/librustc_typeck/check/autoderef.rs9
-rw-r--r--src/librustc_typeck/check/method/mod.rs4
-rw-r--r--src/librustc_typeck/check/method/probe.rs3
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/check/wfcheck.rs7
-rw-r--r--src/librustc_typeck/collect.rs12
-rw-r--r--src/librustdoc/clean/blanket_impl.rs4
21 files changed, 155 insertions, 74 deletions
diff --git a/src/librustc/traits/engine.rs b/src/librustc/traits/engine.rs
index 5b804480119..84bfc86e6a9 100644
--- a/src/librustc/traits/engine.rs
+++ b/src/librustc/traits/engine.rs
@@ -1,6 +1,6 @@
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
-use crate::ty::{self, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_hir::def_id::DefId;
 
 use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
@@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
                 cause,
                 recursion_depth: 0,
                 param_env,
-                predicate: trait_ref.to_predicate(),
+                predicate: trait_ref.without_const().to_predicate(),
             },
         );
     }
diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs
index db3173989ac..2d02dbf8230 100644
--- a/src/librustc/traits/error_reporting/mod.rs
+++ b/src/librustc/traits/error_reporting/mod.rs
@@ -19,7 +19,9 @@ use crate::ty::error::ExpectedFound;
 use crate::ty::fast_reject;
 use crate::ty::fold::TypeFolder;
 use crate::ty::SubtypePredicate;
-use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{
+    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
@@ -130,7 +132,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
 
         let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
+            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
             _ => {
                 // FIXME: make this work in other cases too.
                 return false;
@@ -138,7 +140,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         };
 
         for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
-            if let ty::Predicate::Trait(implication) = implication {
+            if let ty::Predicate::Trait(implication, _) = implication {
                 let error = error.to_poly_trait_ref();
                 let implication = implication.to_poly_trait_ref();
                 // FIXME: I'm just not taking associated types at all here.
@@ -530,7 +532,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     return;
                 }
                 match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate) => {
+                    ty::Predicate::Trait(ref trait_predicate, _) => {
                         let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
 
                         if self.tcx.sess.has_errors() && trait_predicate.references_error() {
@@ -583,7 +585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             "{}",
                             message.unwrap_or_else(|| format!(
                                 "the trait bound `{}` is not satisfied{}",
-                                trait_ref.to_predicate(),
+                                trait_ref.without_const().to_predicate(),
                                 post_message,
                             ))
                         );
@@ -695,7 +697,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                 trait_pred
                             });
                             let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(predicate),
+                                predicate: ty::Predicate::Trait(
+                                    predicate,
+                                    ast::Constness::NotConst,
+                                ),
                                 ..obligation.clone()
                             };
                             if self.predicate_may_hold(&unit_obligation) {
@@ -988,7 +993,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     ) -> PredicateObligation<'tcx> {
         let new_trait_ref =
             ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.to_predicate())
+        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
     }
 }
 
@@ -1076,7 +1081,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
 
         let mut err = match predicate {
-            ty::Predicate::Trait(ref data) => {
+            ty::Predicate::Trait(ref data, _) => {
                 let trait_ref = data.to_poly_trait_ref();
                 let self_ty = trait_ref.self_ty();
                 debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
@@ -1269,8 +1274,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             )
             .value;
 
-            let obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
+            let obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                cleaned_pred.without_const().to_predicate(),
+            );
 
             self.predicate_may_hold(&obligation)
         })
diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs
index c09fd307973..9d8fa362ebb 100644
--- a/src/librustc/traits/error_reporting/suggestions.rs
+++ b/src/librustc/traits/error_reporting/suggestions.rs
@@ -6,7 +6,7 @@ use super::{
 use crate::infer::InferCtxt;
 use crate::traits::object_safety::object_safety_violations;
 use crate::ty::TypeckTables;
-use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 
 use rustc_errors::{
     error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
@@ -50,7 +50,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             } else {
                                 " where"
                             },
-                            trait_ref.to_predicate(),
+                            trait_ref.without_const().to_predicate(),
                         ),
                         Applicability::MachineApplicable,
                     );
@@ -340,8 +340,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
             let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
             let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
-            let new_obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
+            let new_obligation = Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                new_trait_ref.without_const().to_predicate(),
+            );
             if self.predicate_must_hold_modulo_regions(&new_obligation) {
                 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                     // We have a very specific type of error, where just borrowing this argument
@@ -1122,7 +1125,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         // the type. The last generator has information about where the bound was introduced. At
         // least one generator should be present for this diagnostic to be modified.
         let (mut trait_ref, mut target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(p) => {
+            ty::Predicate::Trait(p, _) => {
                 (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
             }
             _ => (None, None),
@@ -1545,7 +1548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 err.note(&format!("required because it appears within the type `{}`", ty));
                 obligated_types.push(ty);
 
-                let parent_predicate = parent_trait_ref.to_predicate();
+                let parent_predicate = parent_trait_ref.without_const().to_predicate();
                 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
                     self.note_obligation_cause_code(
                         err,
@@ -1562,7 +1565,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     parent_trait_ref.print_only_trait_path(),
                     parent_trait_ref.skip_binder().self_ty()
                 ));
-                let parent_predicate = parent_trait_ref.to_predicate();
+                let parent_predicate = parent_trait_ref.without_const().to_predicate();
                 self.note_obligation_cause_code(
                     err,
                     &parent_predicate,
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 2e5da2b0382..7819366f892 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -29,7 +29,7 @@ use crate::mir::interpret::ErrorHandled;
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::subst::{InternalSubsts, SubstsRef};
-use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness};
 use crate::util::common::ErrorReported;
 use chalk_engine;
 use rustc_hir as hir;
@@ -732,7 +732,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
         param_env,
         cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
         recursion_depth: 0,
-        predicate: trait_ref.to_predicate(),
+        predicate: trait_ref.without_const().to_predicate(),
     };
 
     let result = infcx.predicate_must_hold_modulo_regions(&obligation);
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index ad6b821b1d7..15f81bb3f47 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -12,7 +12,7 @@ use super::elaborate_predicates;
 
 use crate::traits::{self, Obligation, ObligationCause};
 use crate::ty::subst::{InternalSubsts, Subst};
-use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
@@ -585,6 +585,7 @@ fn receiver_is_dispatchable<'tcx>(
             def_id: unsize_did,
             substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
         }
+        .without_const()
         .to_predicate();
 
         // U: Trait<Arg1, ..., ArgN>
@@ -598,7 +599,7 @@ fn receiver_is_dispatchable<'tcx>(
                     }
                 });
 
-            ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
+            ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
         };
 
         let caller_bounds: Vec<Predicate<'tcx>> = param_env
@@ -620,6 +621,7 @@ fn receiver_is_dispatchable<'tcx>(
             def_id: dispatch_from_dyn_did,
             substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
         }
+        .without_const()
         .to_predicate();
 
         Obligation::new(ObligationCause::dummy(), param_env, predicate)
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 5bc211ade40..62672a78104 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -16,7 +16,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
 use crate::ty::subst::{InternalSubsts, Subst};
-use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
@@ -738,7 +738,12 @@ fn get_paranoid_cache_value_obligation<'a, 'tcx>(
     depth: usize,
 ) -> PredicateObligation<'tcx> {
     let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() }
+    Obligation {
+        cause,
+        recursion_depth: depth,
+        param_env,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
 }
 
 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
@@ -772,7 +777,7 @@ fn normalize_to_error<'a, 'tcx>(
         cause,
         recursion_depth: depth,
         param_env,
-        predicate: trait_ref.to_predicate(),
+        predicate: trait_ref.without_const().to_predicate(),
     };
     let tcx = selcx.infcx().tcx;
     let def_id = projection_ty.item_def_id;
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 9db907e88fa..ac1ca4db9d6 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -37,7 +37,7 @@ use crate::middle::lang_items;
 use crate::ty::fast_reject;
 use crate::ty::relate::TypeRelation;
 use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_hir::def_id::DefId;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -3368,7 +3368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
                     tcx.mk_substs_trait(source, &[]),
                 );
-                nested.push(predicate_to_obligation(tr.to_predicate()));
+                nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
 
                 // If the type is `Foo + 'a`, ensure that the type
                 // being cast to `Foo + 'a` outlives `'a`:
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index a5a16a14712..f3bd98b8551 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -4,7 +4,7 @@ use smallvec::SmallVec;
 
 use crate::ty::outlives::Component;
 use crate::ty::subst::{GenericArg, Subst, SubstsRef};
-use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
+use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -99,14 +99,14 @@ pub fn elaborate_trait_ref<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
 ) -> Elaborator<'tcx> {
-    elaborate_predicates(tcx, vec![trait_ref.to_predicate()])
+    elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
 }
 
 pub fn elaborate_trait_refs<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
 ) -> Elaborator<'tcx> {
-    let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect();
+    let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
     elaborate_predicates(tcx, predicates)
 }
 
@@ -358,7 +358,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
     fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
         let tcx = self.tcx;
         let trait_ref = item.trait_ref();
-        let pred = trait_ref.to_predicate();
+        let pred = trait_ref.without_const().to_predicate();
 
         debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
 
@@ -370,13 +370,9 @@ impl<'tcx> TraitAliasExpander<'tcx> {
 
         // Don't recurse if this trait alias is already on the stack for the DFS search.
         let anon_pred = anonymize_predicate(tcx, &pred);
-        if item
-            .path
-            .iter()
-            .rev()
-            .skip(1)
-            .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred)
-        {
+        if item.path.iter().rev().skip(1).any(|(tr, _)| {
+            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
+        }) {
             return false;
         }
 
@@ -545,7 +541,12 @@ pub fn predicate_for_trait_ref<'tcx>(
     trait_ref: ty::TraitRef<'tcx>,
     recursion_depth: usize,
 ) -> PredicateObligation<'tcx> {
-    Obligation { cause, param_env, recursion_depth, predicate: trait_ref.to_predicate() }
+    Obligation {
+        cause,
+        param_env,
+        recursion_depth,
+        predicate: trait_ref.without_const().to_predicate(),
+    }
 }
 
 pub fn predicate_for_trait_def(
diff --git a/src/librustc/traits/wf.rs b/src/librustc/traits/wf.rs
index aba09c3c818..a0cb8446c92 100644
--- a/src/librustc/traits/wf.rs
+++ b/src/librustc/traits/wf.rs
@@ -3,7 +3,7 @@ use crate::infer::InferCtxt;
 use crate::middle::lang_items;
 use crate::traits::{self, AssocTypeBoundData};
 use crate::ty::subst::SubstsRef;
-use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::{kw, Ident};
@@ -350,7 +350,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         self.compute_trait_ref(&trait_ref, Elaborate::None);
 
         if !data.has_escaping_bound_vars() {
-            let predicate = trait_ref.to_predicate();
+            let predicate = trait_ref.without_const().to_predicate();
             let cause = self.cause(traits::ProjectionWf(data));
             self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
         }
@@ -378,7 +378,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
                 substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
             };
-            self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate()));
+            self.out.push(traits::Obligation::new(
+                cause,
+                self.param_env,
+                trait_ref.without_const().to_predicate(),
+            ));
         }
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c5fbf2896a4..0470ab20dc4 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -52,7 +52,7 @@ use std::ops::Deref;
 use std::ops::Range;
 use std::slice;
 use std::{mem, ptr};
-use syntax::ast::{self, Ident, Name, NodeId};
+use syntax::ast::{self, Constness, Ident, Name, NodeId};
 use syntax::attr;
 
 pub use self::sty::BoundRegion::*;
@@ -1072,7 +1072,7 @@ pub enum Predicate<'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),
+    Trait(PolyTraitPredicate<'tcx>, Constness),
 
     /// `where 'a: 'b`
     RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
@@ -1340,18 +1340,33 @@ pub trait ToPredicate<'tcx> {
     fn to_predicate(&self) -> Predicate<'tcx>;
 }
 
-impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
     fn to_predicate(&self) -> Predicate<'tcx> {
         ty::Predicate::Trait(
-            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() }),
-            ast::Constness::NotConst,
+            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+            self.constness,
         )
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
     fn to_predicate(&self) -> Predicate<'tcx> {
-        ty::Predicate::Trait(self.to_poly_trait_predicate(), ast::Constness::NotConst)
+        ty::Predicate::Trait(
+            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+            self.constness,
+        )
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
+    fn to_predicate(&self) -> Predicate<'tcx> {
+        ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&PolyTraitRef<'tcx>> {
+    fn to_predicate(&self) -> Predicate<'tcx> {
+        ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness)
     }
 }
 
@@ -1707,6 +1722,33 @@ impl<'tcx> ParamEnv<'tcx> {
     }
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ConstnessAnd<T> {
+    pub constness: Constness,
+    pub value: T,
+}
+
+// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate()` 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> {
+        ConstnessAnd { constness, value: self }
+    }
+
+    #[inline]
+    fn with_const(self) -> ConstnessAnd<Self> {
+        self.with_constness(Constness::Const)
+    }
+
+    #[inline]
+    fn without_const(self) -> ConstnessAnd<Self> {
+        self.with_constness(Constness::NotConst)
+    }
+}
+
+impl<T> WithConstness for T {}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
 pub struct ParamEnvAnd<'tcx, T> {
     pub param_env: ParamEnv<'tcx>,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 84236128482..13f623aadb1 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -12,7 +12,9 @@ use crate::mir::interpret::Scalar;
 use crate::mir::Promoted;
 use crate::ty::layout::VariantIdx;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
-use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable};
+use crate::ty::{
+    self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
+};
 use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS};
 use polonius_engine::Atom;
 use rustc_data_structures::captures::Captures;
@@ -665,14 +667,16 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
     pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
         use crate::ty::ToPredicate;
         match *self.skip_binder() {
-            ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(),
+            ExistentialPredicate::Trait(tr) => {
+                Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate()
+            }
             ExistentialPredicate::Projection(p) => {
                 ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty)))
             }
             ExistentialPredicate::AutoTrait(did) => {
                 let trait_ref =
                     Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
-                trait_ref.to_predicate()
+                trait_ref.without_const().to_predicate()
             }
         }
     }
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index d47e54366b5..8b62403e6ce 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -2,7 +2,7 @@ use rustc::hir::map as hir_map;
 use rustc::session::CrateDisambiguator;
 use rustc::traits::{self};
 use rustc::ty::subst::Subst;
-use rustc::ty::{self, ToPredicate, Ty, TyCtxt};
+use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -58,6 +58,7 @@ fn sized_constraint_for_ty(tcx: TyCtxt<'tcx>, adtdef: &ty::AdtDef, ty: Ty<'tcx>)
                 def_id: sized_trait,
                 substs: tcx.mk_substs_trait(ty, &[]),
             })
+            .without_const()
             .to_predicate();
             let predicates = tcx.predicates_of(adtdef.did).predicates;
             if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 7f196b2c4d3..9253c00e5ae 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -17,7 +17,7 @@ use rustc::traits::astconv_object_safety_violations;
 use rustc::traits::error_reporting::report_object_safety_error;
 use rustc::traits::wf::object_region_bounds;
 use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef};
-use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc::ty::{GenericParamDef, GenericParamDefKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
@@ -2980,7 +2980,7 @@ impl<'tcx> Bounds<'tcx> {
                     def_id: sized,
                     substs: tcx.mk_substs_trait(param_ty, &[]),
                 });
-                (trait_ref.to_predicate(), span)
+                (trait_ref.without_const().to_predicate(), span)
             })
         });
 
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 8d6b74c3015..367fe0c3cc1 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -5,7 +5,7 @@ use rustc::infer::{InferCtxt, InferOk};
 use rustc::session::DiagnosticMessageId;
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
-use rustc::ty::{self, TraitRef, Ty, TyCtxt};
+use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
 use rustc::ty::{ToPredicate, TypeFoldable};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
@@ -124,8 +124,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
 
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
 
-        let obligation =
-            traits::Obligation::new(cause.clone(), self.param_env, trait_ref.to_predicate());
+        let obligation = traits::Obligation::new(
+            cause.clone(),
+            self.param_env,
+            trait_ref.without_const().to_predicate(),
+        );
         if !self.infcx.predicate_may_hold(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
             return None;
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 711c285d17e..c1cf3522b5d 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -17,7 +17,7 @@ use rustc::traits;
 use rustc::ty::subst::Subst;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::GenericParamDefKind;
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -322,7 +322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             span,
             self.body_id,
             self.param_env,
-            poly_trait_ref.to_predicate(),
+            poly_trait_ref.without_const().to_predicate(),
         );
 
         // Now we want to know if this can be matched
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 67526bb70d1..ff2f150c633 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -25,6 +25,7 @@ use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc::ty::GenericParamDefKind;
 use rustc::ty::{
     self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
+    WithConstness,
 };
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
@@ -1396,7 +1397,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 }
 
                 TraitCandidate(trait_ref) => {
-                    let predicate = trait_ref.to_predicate();
+                    let predicate = trait_ref.without_const().to_predicate();
                     let obligation = traits::Obligation::new(cause, self.param_env, predicate);
                     if !self.predicate_may_hold(&obligation) {
                         if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index d6c0d9c77b4..35fffd3bcd4 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -9,7 +9,7 @@ use rustc::hir::map::Map;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::Obligation;
 use rustc::ty::print::with_crate_prefix;
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -59,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             span,
                             self.body_id,
                             self.param_env,
-                            poly_trait_ref.to_predicate(),
+                            poly_trait_ref.without_const().to_predicate(),
                         );
                         self.predicate_may_hold(&obligation)
                     })
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 7c1876f5d44..1e3927f33a7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -112,7 +112,7 @@ use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSel
 use rustc::ty::util::{Discr, IntTypeExt, Representability};
 use rustc::ty::{
     self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef,
-    ToPredicate, Ty, TyCtxt, UserType,
+    ToPredicate, Ty, TyCtxt, UserType, WithConstness,
 };
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -1423,7 +1423,7 @@ fn check_fn<'a, 'tcx>(
                 inherited.register_predicate(traits::Obligation::new(
                     cause,
                     param_env,
-                    trait_ref.to_predicate(),
+                    trait_ref.without_const().to_predicate(),
                 ));
             }
         }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 5e91e98a7df..e4df69993c5 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -6,7 +6,9 @@ use rustc::middle::lang_items;
 use rustc::session::parse::feature_err;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{
+    self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir::def_id::DefId;
@@ -955,7 +957,8 @@ fn receiver_is_implemented(
         substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
     };
 
-    let obligation = traits::Obligation::new(cause, fcx.param_env, trait_ref.to_predicate());
+    let obligation =
+        traits::Obligation::new(cause, fcx.param_env, trait_ref.without_const().to_predicate());
 
     if fcx.predicate_must_hold_modulo_regions(&obligation) {
         true
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 35f9a4fa68e..1211075d942 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -30,7 +30,7 @@ use rustc::ty::subst::GenericArgKind;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::Discr;
 use rustc::ty::util::IntTypeExt;
-use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
+use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness};
 use rustc::ty::{ReprOptions, ToPredicate};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
@@ -411,7 +411,8 @@ fn type_param_predicates(
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_hir_id {
                         let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
-                        extend = Some((identity_trait_ref.to_predicate(), item.span));
+                        extend =
+                            Some((identity_trait_ref.without_const().to_predicate(), item.span));
                     }
                     generics
                 }
@@ -2056,7 +2057,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
         let span = tcx.def_span(def_id);
         result.predicates =
             tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
-                ty::TraitRef::identity(tcx, def_id).to_predicate(),
+                ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(),
                 span,
             ))));
     }
@@ -2230,7 +2231,10 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     // (see below). Recall that a default impl is not itself an impl, but rather a
     // set of defaults that can be incorporated into another impl.
     if let Some(trait_ref) = is_default_impl_trait {
-        predicates.push((trait_ref.to_poly_trait_ref().to_predicate(), tcx.def_span(def_id)));
+        predicates.push((
+            trait_ref.to_poly_trait_ref().without_const().to_predicate(),
+            tcx.def_span(def_id),
+        ));
     }
 
     // Collect the region predicates that were declared inline as
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 525b1b2e6ec..18ebd254507 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -1,7 +1,7 @@
 use rustc::infer::InferOk;
 use rustc::traits;
 use rustc::ty::subst::Subst;
-use rustc::ty::ToPredicate;
+use rustc::ty::{ToPredicate, WithConstness};
 use rustc_hir as hir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_span::DUMMY_SP;
@@ -64,7 +64,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         match infcx.evaluate_obligation(&traits::Obligation::new(
                             cause,
                             param_env,
-                            trait_ref.to_predicate(),
+                            trait_ref.without_const().to_predicate(),
                         )) {
                             Ok(eval_result) => eval_result.may_apply(),
                             Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no