]> git.lizzy.rs Git - rust.git/commitdiff
Remove def_id field from ParamEnv
authorBram van den Heuvel <bram@vandenheuvel.online>
Tue, 1 Sep 2020 15:58:34 +0000 (17:58 +0200)
committerBram van den Heuvel <bram@vandenheuvel.online>
Wed, 9 Sep 2020 08:14:31 +0000 (10:14 +0200)
35 files changed:
compiler/rustc_infer/src/infer/outlives/mod.rs
compiler/rustc_infer/src/traits/mod.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/chalk.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/flags.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_mir/src/transform/qualify_min_const_fn.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/chalk/mod.rs
compiler/rustc_traits/src/implied_outlives_bounds.rs
compiler/rustc_traits/src/normalize_erasing_regions.rs
compiler/rustc_ty/src/ty.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
compiler/rustc_typeck/src/outlives/explicit.rs
src/librustdoc/clean/mod.rs
src/test/ui/chalkify/type_inference.stderr
src/test/ui/infinite/infinite-tag-type-recursion.stderr

index a1e7f1fa3e5e7df5e3dc573222e5cefd02bedf34..de98cccf25689db74a4f1e78c91cde3dc50cee0a 100644 (file)
@@ -26,7 +26,8 @@ pub fn explicit_outlives_bounds<'tcx>(
             | ty::PredicateAtom::ClosureKind(..)
             | ty::PredicateAtom::TypeOutlives(..)
             | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..) => None,
+            | ty::PredicateAtom::ConstEquate(..)
+            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
             ty::PredicateAtom::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
                 Some(OutlivesBound::RegionSubRegion(r_b, r_a))
             }
index 7e7c8588ffb40a6440bce2d38c4fdc69ad0d4fa8..a3c4920fa8af3dc593adff29ef4e209edb9b0165 100644 (file)
@@ -57,7 +57,7 @@ pub struct Obligation<'tcx, T> {
 
 // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(PredicateObligation<'_>, 40);
+static_assert_size!(PredicateObligation<'_>, 32);
 
 pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
 pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
index 93fc7f1f3b8a7e97b49ff7f4b3f35afda7a953a4..9c0d934a03529a75c39e2fac97710f4a4d02f9c0 100644 (file)
@@ -236,6 +236,9 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                         .map(|predicate| predicate_obligation(predicate, None)),
                 );
             }
+            ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                // Nothing to elaborate
+            }
         }
     }
 }
index d18d89ed641b2666c2a903eb062ce60f2f6f9fff..61ecd13c30768aab8e8eefb281f9ef024f98f440 100644 (file)
@@ -1228,7 +1228,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                     ClosureKind(..) |
                     Subtype(..) |
                     ConstEvaluatable(..) |
-                    ConstEquate(..) => continue,
+                    ConstEquate(..) |
+                    TypeWellFormedFromEnv(..) => continue,
                 };
                 if predicate.is_global() {
                     cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
index 719f0322fd72cf610ae2bf560f035820f37bf2ab..15e3110bc851e8976b41ffa27176c254f00f8f28 100644 (file)
@@ -1399,7 +1399,7 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         }
 
         query evaluate_goal(
-            goal: traits::ChalkCanonicalGoal<'tcx>
+            goal: traits::CanonicalChalkEnvironmentAndGoal<'tcx>
         ) -> Result<
             &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
             NoSolution
index 763b078e7703ed135fc7dcdae44a8753082616b1..d8507d08c1bc5217540df1d092537354d3e96057 100644 (file)
@@ -6,14 +6,11 @@
 //! interned Chalk types.
 
 use rustc_middle::mir::interpret::ConstValue;
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtDef, TyCtxt};
 
 use rustc_hir::def_id::DefId;
 use rustc_target::spec::abi::Abi;
 
-use smallvec::SmallVec;
-
 use std::cmp::Ordering;
 use std::fmt;
 use std::hash::{Hash, Hasher};
@@ -376,31 +373,10 @@ impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> {
     type Interner = Self;
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
-pub enum ChalkEnvironmentClause<'tcx> {
-    /// A normal rust `ty::Predicate` in the environment.
-    Predicate(ty::Predicate<'tcx>),
-    /// A special clause in the environment that gets lowered to
-    /// `chalk_ir::FromEnv::Ty`.
-    TypeFromEnv(Ty<'tcx>),
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ChalkEnvironmentClause<'tcx>> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
-        folder.tcx().intern_chalk_environment_clause_list(&v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.iter().any(|t| t.visit_with(visitor))
-    }
-}
-/// We have to elaborate the environment of a chalk goal *before*
-/// canonicalization. This type wraps the predicate and the elaborated
-/// environment.
+/// A chalk environment and goal.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub struct ChalkEnvironmentAndGoal<'tcx> {
-    pub environment: &'tcx ty::List<ChalkEnvironmentClause<'tcx>>,
+    pub environment: &'tcx ty::List<ty::Predicate<'tcx>>,
     pub goal: ty::Predicate<'tcx>,
 }
 
index f86403fa502bb02e225618a7a95949381e331fcf..ae89b68942c96edadaba993440d24cec82293520 100644 (file)
 
 pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
 
-pub type ChalkCanonicalGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;
+pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;
 
 pub use self::ImplSource::*;
 pub use self::ObligationCauseCode::*;
 
-pub use self::chalk::{
-    ChalkEnvironmentAndGoal, ChalkEnvironmentClause, RustInterner as ChalkRustInterner,
-};
+pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner};
 
 /// Depending on the stage of compilation, we want projection to be
 /// more or less conservative.
index aa34dedc4b286b74b02fc5e905e820b7675acc94..aacf61e5b425a28852d05b70b928ed7a160c026a 100644 (file)
@@ -91,8 +91,6 @@ pub struct CtxtInterners<'tcx> {
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
     const_: InternedSet<'tcx, Const<'tcx>>,
-
-    chalk_environment_clause_list: InternedSet<'tcx, List<traits::ChalkEnvironmentClause<'tcx>>>,
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
@@ -110,7 +108,6 @@ fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
             projs: Default::default(),
             place_elems: Default::default(),
             const_: Default::default(),
-            chalk_environment_clause_list: Default::default(),
         }
     }
 
@@ -2041,7 +2038,7 @@ pub fn $method(self, v: $ty) -> &'tcx $ty {
 }
 
 macro_rules! slice_interners {
-    ($($field:ident: $method:ident($ty:ty)),+) => (
+    ($($field:ident: $method:ident($ty:ty)),+ $(,)?) => (
         $(impl<'tcx> TyCtxt<'tcx> {
             pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
                 self.interners.$field.intern_ref(v, || {
@@ -2060,8 +2057,6 @@ pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
     predicates: _intern_predicates(Predicate<'tcx>),
     projs: _intern_projs(ProjectionKind),
     place_elems: _intern_place_elems(PlaceElem<'tcx>),
-    chalk_environment_clause_list:
-        _intern_chalk_environment_clause_list(traits::ChalkEnvironmentClause<'tcx>)
 );
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -2460,13 +2455,6 @@ pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVar
         if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
     }
 
-    pub fn intern_chalk_environment_clause_list(
-        self,
-        ts: &[traits::ChalkEnvironmentClause<'tcx>],
-    ) -> &'tcx List<traits::ChalkEnvironmentClause<'tcx>> {
-        if ts.is_empty() { List::empty() } else { self._intern_chalk_environment_clause_list(ts) }
-    }
-
     pub fn mk_fn_sig<I>(
         self,
         inputs: I,
@@ -2524,18 +2512,6 @@ pub fn mk_substs_trait(self, self_ty: Ty<'tcx>, rest: &[GenericArg<'tcx>]) -> Su
         self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned()))
     }
 
-    pub fn mk_chalk_environment_clause_list<
-        I: InternAs<
-            [traits::ChalkEnvironmentClause<'tcx>],
-            &'tcx List<traits::ChalkEnvironmentClause<'tcx>>,
-        >,
-    >(
-        self,
-        iter: I,
-    ) -> I::Output {
-        iter.intern_with(|xs| self.intern_chalk_environment_clause_list(xs))
-    }
-
     /// Walks upwards from `id` to find a node which might change lint levels with attributes.
     /// It stops at `bound` and just returns it if reached.
     pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
index f7871c4fffddbb76154d3102c1f94aa05b0f7c51..c9a4022330a7af2df9a7a9de3210ebc2d1b27697 100644 (file)
@@ -249,6 +249,9 @@ fn add_predicate_atom(&mut self, atom: ty::PredicateAtom<'_>) {
                 self.add_const(expected);
                 self.add_const(found);
             }
+            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+                self.add_ty(ty);
+            }
         }
     }
 
index 29fa3f9bb65e05c5824a6141fdaab2fc6c3caa7e..8283deb3ecc24ffaae4b71cb526fb3a733721ce2 100644 (file)
@@ -1155,6 +1155,11 @@ pub enum PredicateAtom<'tcx> {
 
     /// Constants must be equal. The first component is the const that is expected.
     ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
+
+    /// Represents a type found in the environment that we can use for implied bounds.
+    ///
+    /// Only used for Chalk.
+    TypeWellFormedFromEnv(Ty<'tcx>),
 }
 
 impl<'tcx> PredicateAtom<'tcx> {
@@ -1450,7 +1455,8 @@ pub fn to_opt_poly_trait_ref(self) -> Option<PolyTraitRef<'tcx>> {
             | PredicateAtom::ClosureKind(..)
             | PredicateAtom::TypeOutlives(..)
             | PredicateAtom::ConstEvaluatable(..)
-            | PredicateAtom::ConstEquate(..) => None,
+            | PredicateAtom::ConstEquate(..)
+            | PredicateAtom::TypeWellFormedFromEnv(..) => None,
         }
     }
 
@@ -1465,7 +1471,8 @@ pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
             | PredicateAtom::ObjectSafe(..)
             | PredicateAtom::ClosureKind(..)
             | PredicateAtom::ConstEvaluatable(..)
-            | PredicateAtom::ConstEquate(..) => None,
+            | PredicateAtom::ConstEquate(..)
+            | PredicateAtom::TypeWellFormedFromEnv(..) => None,
         }
     }
 }
@@ -1738,11 +1745,6 @@ pub struct ParamEnv<'tcx> {
     ///
     /// Note: This is packed, use the reveal() method to access it.
     packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, traits::Reveal, true>,
-
-    /// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`,
-    /// register that `def_id` (useful for transitioning to the chalk trait
-    /// solver).
-    pub def_id: Option<DefId>,
 }
 
 unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
@@ -1767,7 +1769,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("ParamEnv")
             .field("caller_bounds", &self.caller_bounds())
             .field("reveal", &self.reveal())
-            .field("def_id", &self.def_id)
             .finish()
     }
 }
@@ -1776,23 +1777,16 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         self.caller_bounds().hash_stable(hcx, hasher);
         self.reveal().hash_stable(hcx, hasher);
-        self.def_id.hash_stable(hcx, hasher);
     }
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
     fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        ParamEnv::new(
-            self.caller_bounds().fold_with(folder),
-            self.reveal().fold_with(folder),
-            self.def_id.fold_with(folder),
-        )
+        ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.caller_bounds().visit_with(visitor)
-            || self.reveal().visit_with(visitor)
-            || self.def_id.visit_with(visitor)
+        self.caller_bounds().visit_with(visitor) || self.reveal().visit_with(visitor)
     }
 }
 
@@ -1803,7 +1797,7 @@ impl<'tcx> ParamEnv<'tcx> {
     /// type-checking.
     #[inline]
     pub fn empty() -> Self {
-        Self::new(List::empty(), Reveal::UserFacing, None)
+        Self::new(List::empty(), Reveal::UserFacing)
     }
 
     #[inline]
@@ -1825,17 +1819,13 @@ pub fn reveal(self) -> traits::Reveal {
     /// or invoke `param_env.with_reveal_all()`.
     #[inline]
     pub fn reveal_all() -> Self {
-        Self::new(List::empty(), Reveal::All, None)
+        Self::new(List::empty(), Reveal::All)
     }
 
     /// Construct a trait environment with the given set of predicates.
     #[inline]
-    pub fn new(
-        caller_bounds: &'tcx List<Predicate<'tcx>>,
-        reveal: Reveal,
-        def_id: Option<DefId>,
-    ) -> Self {
-        ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal), def_id }
+    pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self {
+        ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) }
     }
 
     pub fn with_user_facing(mut self) -> Self {
@@ -1857,12 +1847,12 @@ pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
             return self;
         }
 
-        ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All, self.def_id)
+        ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All)
     }
 
     /// Returns this same environment but with no caller bounds.
     pub fn without_caller_bounds(self) -> Self {
-        Self::new(List::empty(), self.reveal(), self.def_id)
+        Self::new(List::empty(), self.reveal())
     }
 
     /// Creates a suitable environment in which to perform trait
index 538c07b9bde5ff46c1ebc01535731a1ff2634f92..9562d43791493691c2e9ea47aa1d466d8b352af7 100644 (file)
@@ -2096,6 +2096,11 @@ pub fn print_only_trait_path(self) -> ty::Binder<TraitRefPrintOnlyTraitPath<'tcx
                 print(c2),
                 write("`"))
             }
+            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+                p!(write("the type `"),
+                print(ty),
+                write("` is found in the environment"))
+            }
         }
     }
 
index f8627e2f1b6461609144438d4de857730ed2faf0..afbf805975ce76e8f5875b5be86177c39a479255 100644 (file)
@@ -260,6 +260,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
             }
             ty::PredicateAtom::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
+            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+                write!(f, "TypeWellFormedFromEnv({:?})", ty)
+            }
         }
     }
 }
@@ -536,6 +539,9 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             ty::PredicateAtom::ConstEquate(c1, c2) => {
                 tcx.lift(&(c1, c2)).map(|(c1, c2)| ty::PredicateAtom::ConstEquate(c1, c2))
             }
+            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+                tcx.lift(&ty).map(ty::PredicateAtom::TypeWellFormedFromEnv)
+            }
         }
     }
 }
@@ -551,7 +557,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
     type Lifted = ty::ParamEnv<'tcx>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&self.caller_bounds())
-            .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.def_id))
+            .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal()))
     }
 }
 
index 7d9611e07311dd18d44d711d5fd3cdbafb7dfcd3..5e102f5151d0ceebedcbe3256d8a3804e1b3be3f 100644 (file)
@@ -30,7 +30,8 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
                 | ty::PredicateAtom::WellFormed(_)
                 | ty::PredicateAtom::Projection(_)
                 | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..) => continue,
+                | ty::PredicateAtom::ConstEquate(..)
+                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
                 ty::PredicateAtom::ObjectSafe(_) => {
                     bug!("object safe predicate on function: {:#?}", predicate)
                 }
index 9cf3bbd94e03d4031214d15d25fd3c4dd7ccbc3c..28697ec4e3b9fe4cc106d4f8e4a350a47a823c7c 100644 (file)
@@ -1261,7 +1261,8 @@ pub fn may_define_opaque_type(
                 | ty::PredicateAtom::ClosureKind(..)
                 | ty::PredicateAtom::RegionOutlives(..)
                 | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..) => None,
+                | ty::PredicateAtom::ConstEquate(..)
+                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
                 ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
                     // Search for a bound of the form `erased_self_ty
                     // : 'a`, but be wary of something like `for<'a>
index ad8e9d9faa6fc995776e83aa4af83d0222b70ba5..6b87bc4f34ad4fbbc9f8901ebe4621b0e81de743 100644 (file)
@@ -373,14 +373,12 @@ fn evaluate_predicates(
                 computed_preds.clone().chain(user_computed_preds.iter().cloned()),
             )
             .map(|o| o.predicate);
-            new_env =
-                ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal(), None);
+            new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal());
         }
 
         let final_user_env = ty::ParamEnv::new(
             tcx.mk_predicates(user_computed_preds.into_iter()),
             user_env.reveal(),
-            None,
         );
         debug!(
             "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
index 0097097707f320e012cf0b8cea5ad09c659bc435..adc8ae5908656409ec91fe14e4f3e5bbfcbf6bf6 100644 (file)
@@ -4,12 +4,11 @@
 use crate::infer::InferCtxt;
 use crate::traits::query::NoSolution;
 use crate::traits::{
-    ChalkEnvironmentAndGoal, ChalkEnvironmentClause, FulfillmentError, FulfillmentErrorCode,
-    ObligationCause, PredicateObligation, SelectionError, TraitEngine,
+    ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause,
+    PredicateObligation, SelectionError, TraitEngine,
 };
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty};
 
 pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
@@ -21,132 +20,6 @@ impl FulfillmentContext<'tcx> {
     }
 }
 
-fn environment<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-) -> &'tcx ty::List<ChalkEnvironmentClause<'tcx>> {
-    use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
-    use rustc_middle::ty::subst::GenericArgKind;
-
-    debug!("environment(def_id = {:?})", def_id);
-
-    // The environment of an impl Trait type is its defining function's environment.
-    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
-        return environment(tcx, parent);
-    }
-
-    // Compute the bounds on `Self` and the type parameters.
-    let ty::InstantiatedPredicates { predicates, .. } =
-        tcx.predicates_of(def_id).instantiate_identity(tcx);
-
-    let clauses = predicates.into_iter().map(ChalkEnvironmentClause::Predicate);
-
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-    let node = tcx.hir().get(hir_id);
-
-    enum NodeKind {
-        TraitImpl,
-        InherentImpl,
-        Fn,
-        Other,
-    };
-
-    let node_kind = match node {
-        Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        Node::Item(item) => match item.kind {
-            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
-            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
-            ItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        Node::ForeignItem(item) => match item.kind {
-            ForeignItemKind::Fn(..) => NodeKind::Fn,
-            _ => NodeKind::Other,
-        },
-
-        // FIXME: closures?
-        _ => NodeKind::Other,
-    };
-
-    // FIXME(eddyb) isn't the unordered nature of this a hazard?
-    let mut inputs = FxIndexSet::default();
-
-    match node_kind {
-        // In a trait impl, we assume that the header trait ref and all its
-        // constituents are well-formed.
-        NodeKind::TraitImpl => {
-            let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
-
-            // FIXME(chalk): this has problems because of late-bound regions
-            //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
-            inputs.extend(trait_ref.substs.iter());
-        }
-
-        // In an inherent impl, we assume that the receiver type and all its
-        // constituents are well-formed.
-        NodeKind::InherentImpl => {
-            let self_ty = tcx.type_of(def_id);
-            inputs.extend(self_ty.walk());
-        }
-
-        // In an fn, we assume that the arguments and all their constituents are
-        // well-formed.
-        NodeKind::Fn => {
-            let fn_sig = tcx.fn_sig(def_id);
-            let fn_sig = tcx.liberate_late_bound_regions(def_id, &fn_sig);
-
-            inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
-        }
-
-        NodeKind::Other => (),
-    }
-    let input_clauses = inputs.into_iter().filter_map(|arg| {
-        match arg.unpack() {
-            GenericArgKind::Type(ty) => Some(ChalkEnvironmentClause::TypeFromEnv(ty)),
-
-            // FIXME(eddyb) no WF conditions from lifetimes?
-            GenericArgKind::Lifetime(_) => None,
-
-            // FIXME(eddyb) support const generics in Chalk
-            GenericArgKind::Const(_) => None,
-        }
-    });
-
-    tcx.mk_chalk_environment_clause_list(clauses.chain(input_clauses))
-}
-
-/// We need to wrap a `ty::Predicate` in an elaborated environment *before* we
-/// canonicalize. This is due to the fact that we insert extra clauses into the
-/// environment for all input types (`FromEnv`).
-fn in_environment(
-    infcx: &InferCtxt<'_, 'tcx>,
-    obligation: &PredicateObligation<'tcx>,
-) -> ChalkEnvironmentAndGoal<'tcx> {
-    assert!(!infcx.is_in_snapshot());
-    let obligation = infcx.resolve_vars_if_possible(obligation);
-
-    let environment = match obligation.param_env.def_id {
-        Some(def_id) => environment(infcx.tcx, def_id),
-        None if obligation.param_env.caller_bounds().is_empty() => ty::List::empty(),
-        // FIXME(chalk): this is hit in ui/where-clauses/where-clause-constraints-are-local-for-trait-impl
-        // and ui/generics/generic-static-methods
-        //_ => bug!("non-empty `ParamEnv` with no def-id"),
-        _ => ty::List::empty(),
-    };
-
-    ChalkEnvironmentAndGoal { environment, goal: obligation.predicate }
-}
-
 impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     fn normalize_projection_type(
         &mut self,
@@ -195,6 +68,8 @@ fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
     ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+        assert!(!infcx.is_in_snapshot());
+
         let mut errors = Vec::new();
         let mut next_round = FxIndexSet::default();
         let mut making_progress;
@@ -205,10 +80,11 @@ fn select_where_possible(
             // We iterate over all obligations, and record if we are able
             // to unambiguously prove at least one obligation.
             for obligation in self.obligations.drain(..) {
-                let goal_in_environment = in_environment(infcx, &obligation);
+                let obligation = infcx.resolve_vars_if_possible(&obligation);
+                let environment = obligation.param_env.caller_bounds();
+                let goal = ChalkEnvironmentAndGoal { environment, goal: obligation.predicate };
                 let mut orig_values = OriginalQueryValues::default();
-                let canonical_goal =
-                    infcx.canonicalize_query(&goal_in_environment, &mut orig_values);
+                let canonical_goal = infcx.canonicalize_query(&goal, &mut orig_values);
 
                 match infcx.tcx.evaluate_goal(canonical_goal) {
                     Ok(response) => {
index dcd8379803319b2e673b748db2488e0a55c2fddc..a9651144e597adad3c9a66dc5ba66c1315cb1ae4 100644 (file)
@@ -663,6 +663,11 @@ fn report_selection_error(
                             obligation
                         )
                     }
+
+                    ty::PredicateAtom::TypeWellFormedFromEnv(..) => span_bug!(
+                        span,
+                        "TypeWellFormedFromEnv predicate should only exist in the environment"
+                    ),
                 }
             }
 
index a5c6dc042abc38eea92235a890ae06a4d76fc71b..7e505e9c49125aedfa7019a1d6aedc5117939d4e 100644 (file)
@@ -86,7 +86,7 @@ pub struct PendingPredicateObligation<'tcx> {
 
 // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(PendingPredicateObligation<'_>, 64);
+static_assert_size!(PendingPredicateObligation<'_>, 56);
 
 impl<'a, 'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
@@ -354,6 +354,9 @@ fn process_obligation(
                         obligation.with(pred.to_predicate(self.selcx.tcx())),
                     ]))
                 }
+                ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                    bug!("TypeWellFormedFromEnv is only used for Chalk")
+                }
             },
             &ty::PredicateKind::Atom(atom) => match atom {
                 ty::PredicateAtom::Trait(ref data, _) => {
@@ -535,6 +538,9 @@ fn process_obligation(
                         }
                     }
                 }
+                ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                    bug!("TypeWellFormedFromEnv is only used for Chalk")
+                }
             },
         }
     }
index fe406e88c52604cbb0b2616c11b0ca7f747f5715..00ca1d0a74ac64479f1987f95b44e621186c5a70 100644 (file)
@@ -301,11 +301,8 @@ pub fn normalize_param_env_or_error<'tcx>(
 
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
 
-    let elaborated_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal(),
-        unnormalized_env.def_id,
-    );
+    let elaborated_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal());
 
     // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
     // normalization expects its param-env to be already normalized, which means we have
@@ -359,7 +356,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     let outlives_env: Vec<_> =
         non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
     let outlives_env =
-        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal(), None);
+        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal());
     let outlives_predicates = match do_normalize_predicates(
         tcx,
         region_context,
@@ -379,11 +376,7 @@ pub fn normalize_param_env_or_error<'tcx>(
     let mut predicates = non_outlives_predicates;
     predicates.extend(outlives_predicates);
     debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
-    ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal(),
-        unnormalized_env.def_id,
-    )
+    ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal())
 }
 
 pub fn fully_normalize<'a, 'tcx, T>(
index 6c0c33d3dad2eaafd9083447febb0aedf6b3f09b..2f2ac9f094dc28a29bd7400f409a73397b86ad39 100644 (file)
@@ -276,7 +276,8 @@ fn predicates_reference_self(
                 | ty::PredicateAtom::ClosureKind(..)
                 | ty::PredicateAtom::Subtype(..)
                 | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..) => None,
+                | ty::PredicateAtom::ConstEquate(..)
+                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
             }
         })
         .collect()
@@ -310,7 +311,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
             | ty::PredicateAtom::ClosureKind(..)
             | ty::PredicateAtom::TypeOutlives(..)
             | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..) => false,
+            | ty::PredicateAtom::ConstEquate(..)
+            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => false,
         }
     })
 }
@@ -654,11 +656,7 @@ fn receiver_is_dispatchable<'tcx>(
             .chain(iter::once(trait_predicate))
             .collect();
 
-        ty::ParamEnv::new(
-            tcx.intern_predicates(&caller_bounds),
-            param_env.reveal(),
-            param_env.def_id,
-        )
+        ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal())
     };
 
     // Receiver: DispatchFromDyn<Receiver[Self => U]>
index 4258d8e3010a4b48b7901608642c5b2a20d87841..1e1ae78d57df76868a50dffcc9068e99cf7c4a5f 100644 (file)
@@ -592,6 +592,9 @@ fn evaluate_predicate_recursively<'o>(
                     }
                 }
             }
+            ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                bug!("TypeWellFormedFromEnv is only used for chalk")
+            }
         }
     }
 
index eb9ee2868f93d48ea0e4501b127c2cd53730fd04..998990f374cb96ea1e2af6cf77a957eeeb35707c 100644 (file)
@@ -127,6 +127,9 @@ pub fn predicate_obligations<'a, 'tcx>(
             wf.compute(c1.into());
             wf.compute(c2.into());
         }
+        ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+            bug!("TypeWellFormedFromEnv is only used for Chalk")
+        }
     }
 
     wf.normalize()
index e89a51a81768d55085a885be1c8f00062f7a49c4..650404e8ca6ddf1896b892ad31657519e1ffa370 100644 (file)
@@ -31,9 +31,7 @@
 //! not. To lower anything wrapped in a `Binder`, we first deeply find any bound
 //! variables from the current `Binder`.
 
-use rustc_middle::traits::{
-    ChalkEnvironmentAndGoal, ChalkEnvironmentClause, ChalkRustInterner as RustInterner,
-};
+use rustc_middle::traits::{ChalkEnvironmentAndGoal, ChalkRustInterner as RustInterner};
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{
@@ -43,8 +41,6 @@
 
 use std::collections::btree_map::{BTreeMap, Entry};
 
-use chalk_ir::fold::shift::Shift;
-
 /// Essentially an `Into` with a `&RustInterner` parameter
 crate trait LowerInto<'tcx, T> {
     /// Lower a rustc construct (e.g., `ty::TraitPredicate`) to a chalk type, consuming `self`.
@@ -82,60 +78,45 @@ fn lower_into(
         self,
         interner: &RustInterner<'tcx>,
     ) -> chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>> {
-        let clauses = self.environment.into_iter().map(|clause| match clause {
-            ChalkEnvironmentClause::Predicate(predicate) => {
-                let (predicate, binders, _named_regions) =
-                    collect_bound_vars(interner, interner.tcx, &predicate.bound_atom(interner.tcx));
-                let consequence = match predicate {
-                    ty::PredicateAtom::Trait(predicate, _) => chalk_ir::DomainGoal::FromEnv(
-                        chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
-                    ),
-                    ty::PredicateAtom::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
-                        chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
-                            a: predicate.0.lower_into(interner),
-                            b: predicate.1.lower_into(interner),
-                        }),
-                    ),
-                    ty::PredicateAtom::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
-                        chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
-                            ty: predicate.0.lower_into(interner),
-                            lifetime: predicate.1.lower_into(interner),
-                        }),
-                    ),
-                    ty::PredicateAtom::Projection(predicate) => chalk_ir::DomainGoal::Holds(
-                        chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
-                    ),
-                    ty::PredicateAtom::WellFormed(..)
-                    | ty::PredicateAtom::ObjectSafe(..)
-                    | ty::PredicateAtom::ClosureKind(..)
-                    | ty::PredicateAtom::Subtype(..)
-                    | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..) => {
-                        bug!("unexpected predicate {}", predicate)
-                    }
-                };
-                let value = chalk_ir::ProgramClauseImplication {
-                    consequence,
-                    conditions: chalk_ir::Goals::empty(interner),
-                    priority: chalk_ir::ClausePriority::High,
-                    constraints: chalk_ir::Constraints::empty(interner),
-                };
-                chalk_ir::ProgramClauseData(chalk_ir::Binders::new(binders, value)).intern(interner)
-            }
-            ChalkEnvironmentClause::TypeFromEnv(ty) => {
-                chalk_ir::ProgramClauseData(chalk_ir::Binders::new(
-                    chalk_ir::VariableKinds::empty(interner),
-                    chalk_ir::ProgramClauseImplication {
-                        consequence: chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(
-                            ty.lower_into(interner).shifted_in(interner),
-                        )),
-                        conditions: chalk_ir::Goals::empty(interner),
-                        priority: chalk_ir::ClausePriority::High,
-                        constraints: chalk_ir::Constraints::empty(interner),
-                    },
-                ))
-                .intern(interner)
-            }
+        let clauses = self.environment.into_iter().map(|predicate| {
+            let (predicate, binders, _named_regions) =
+                collect_bound_vars(interner, interner.tcx, &predicate.bound_atom(interner.tcx));
+            let consequence = match predicate {
+                ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
+                    chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner)))
+                }
+                ty::PredicateAtom::Trait(predicate, _) => chalk_ir::DomainGoal::FromEnv(
+                    chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
+                ),
+                ty::PredicateAtom::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+                    chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
+                        a: predicate.0.lower_into(interner),
+                        b: predicate.1.lower_into(interner),
+                    }),
+                ),
+                ty::PredicateAtom::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
+                    chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
+                        ty: predicate.0.lower_into(interner),
+                        lifetime: predicate.1.lower_into(interner),
+                    }),
+                ),
+                ty::PredicateAtom::Projection(predicate) => chalk_ir::DomainGoal::Holds(
+                    chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
+                ),
+                ty::PredicateAtom::WellFormed(..)
+                | ty::PredicateAtom::ObjectSafe(..)
+                | ty::PredicateAtom::ClosureKind(..)
+                | ty::PredicateAtom::Subtype(..)
+                | ty::PredicateAtom::ConstEvaluatable(..)
+                | ty::PredicateAtom::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
+            };
+            let value = chalk_ir::ProgramClauseImplication {
+                consequence,
+                conditions: chalk_ir::Goals::empty(interner),
+                priority: chalk_ir::ClausePriority::High,
+                constraints: chalk_ir::Constraints::empty(interner),
+            };
+            chalk_ir::ProgramClauseData(chalk_ir::Binders::new(binders, value)).intern(interner)
         });
 
         let goal: chalk_ir::GoalData<RustInterner<'tcx>> = self.goal.lower_into(&interner);
@@ -214,6 +195,9 @@ fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData<RustInt
             | ty::PredicateAtom::ConstEquate(..) => {
                 chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
             }
+            ty::PredicateAtom::TypeWellFormedFromEnv(ty) => chalk_ir::GoalData::DomainGoal(
+                chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner))),
+            ),
         };
 
         chalk_ir::GoalData::Quantified(
@@ -684,7 +668,10 @@ fn lower_into(
             | ty::PredicateAtom::ClosureKind(..)
             | ty::PredicateAtom::Subtype(..)
             | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..) => bug!("unexpected predicate {}", &self),
+            | ty::PredicateAtom::ConstEquate(..)
+            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                bug!("unexpected predicate {}", &self)
+            }
         };
         value.map(|value| chalk_ir::Binders::new(binders, value))
     }
index c0d4a5d0e7e5c2ea78cb50502a3f2d309542e454..63c5b884357b04d47f5867282b3595cc94ad6a5c 100644 (file)
@@ -1,8 +1,7 @@
 //! Calls `chalk-solve` to solve a `ty::Predicate`
 //!
-//! In order to call `chalk-solve`, this file must convert a
-//! `ChalkCanonicalGoal` into a Chalk ucanonical goal. It then calls Chalk, and
-//! converts the answer back into rustc solution.
+//! In order to call `chalk-solve`, this file must convert a `CanonicalChalkEnvironmentAndGoal` into
+//! a Chalk uncanonical goal. It then calls Chalk, and converts the answer back into rustc solution.
 
 crate mod db;
 crate mod lowering;
@@ -20,7 +19,7 @@
 use rustc_infer::infer::canonical::{
     Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
 };
-use rustc_infer::traits::{self, ChalkCanonicalGoal};
+use rustc_infer::traits::{self, CanonicalChalkEnvironmentAndGoal};
 
 use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase;
 use crate::chalk::lowering::{
@@ -35,7 +34,7 @@
 
 crate fn evaluate_goal<'tcx>(
     tcx: TyCtxt<'tcx>,
-    obligation: ChalkCanonicalGoal<'tcx>,
+    obligation: CanonicalChalkEnvironmentAndGoal<'tcx>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, traits::query::NoSolution> {
     let interner = ChalkRustInterner { tcx };
 
index de3096eac9b193df599036065968bbcfe796ac73..79308b032eccd89e7b5bbf1521225e63adf9df46 100644 (file)
@@ -103,7 +103,8 @@ fn compute_implied_outlives_bounds<'tcx>(
                     | ty::PredicateAtom::ClosureKind(..)
                     | ty::PredicateAtom::ObjectSafe(..)
                     | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..) => vec![],
+                    | ty::PredicateAtom::ConstEquate(..)
+                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => vec![],
                     ty::PredicateAtom::WellFormed(arg) => {
                         wf_args.push(arg);
                         vec![]
index 83aee31a39f3c223ae6af037ac29ebda5cacc3b2..3e7c9ac62eb8e93a28b82952a01494d72c37330b 100644 (file)
@@ -49,6 +49,7 @@ fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool {
         | ty::PredicateAtom::ClosureKind(..)
         | ty::PredicateAtom::Subtype(..)
         | ty::PredicateAtom::ConstEvaluatable(..)
-        | ty::PredicateAtom::ConstEquate(..) => true,
+        | ty::PredicateAtom::ConstEquate(..)
+        | ty::PredicateAtom::TypeWellFormedFromEnv(..) => true,
     }
 }
index a0235444ac4fc3be6bd5f0bd39d0df032897625c..c4b6b64339a03713bf481545ee1bbf4a62984d66 100644 (file)
@@ -1,3 +1,4 @@
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -5,7 +6,9 @@
 use rustc_infer::traits::util;
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
-use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_middle::ty::{
+    self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
+};
 use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -245,7 +248,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     }
     // Compute the bounds on Self and the type parameters.
 
-    let ty::InstantiatedPredicates { predicates, .. } =
+    let ty::InstantiatedPredicates { mut predicates, .. } =
         tcx.predicates_of(def_id).instantiate_identity(tcx);
 
     // Finally, we have to normalize the bounds in the environment, in
@@ -260,11 +263,13 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     // are any errors at that point, so after type checking you can be
     // sure that this will succeed without errors anyway.
 
-    let unnormalized_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        traits::Reveal::UserFacing,
-        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
-    );
+    if tcx.sess.opts.debugging_opts.chalk {
+        let environment = well_formed_types_in_env(tcx, def_id);
+        predicates.extend(environment);
+    }
+
+    let unnormalized_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing);
 
     let body_id = def_id
         .as_local()
@@ -276,6 +281,122 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
 }
 
+/// Elaborate the environment.
+///
+/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
+/// that are assumed to be well-formed (because they come from the environment).
+///
+/// Used only in chalk mode.
+fn well_formed_types_in_env<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+) -> &'tcx ty::List<Predicate<'tcx>> {
+    use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
+    use rustc_middle::ty::subst::GenericArgKind;
+
+    debug!("environment(def_id = {:?})", def_id);
+
+    // The environment of an impl Trait type is its defining function's environment.
+    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
+        return well_formed_types_in_env(tcx, parent);
+    }
+
+    // Compute the bounds on `Self` and the type parameters.
+    let ty::InstantiatedPredicates { predicates, .. } =
+        tcx.predicates_of(def_id).instantiate_identity(tcx);
+
+    let clauses = predicates.into_iter();
+
+    if !def_id.is_local() {
+        return ty::List::empty();
+    }
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    let node = tcx.hir().get(hir_id);
+
+    enum NodeKind {
+        TraitImpl,
+        InherentImpl,
+        Fn,
+        Other,
+    };
+
+    let node_kind = match node {
+        Node::TraitItem(item) => match item.kind {
+            TraitItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        Node::ImplItem(item) => match item.kind {
+            ImplItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        Node::Item(item) => match item.kind {
+            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
+            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
+            ItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        Node::ForeignItem(item) => match item.kind {
+            ForeignItemKind::Fn(..) => NodeKind::Fn,
+            _ => NodeKind::Other,
+        },
+
+        // FIXME: closures?
+        _ => NodeKind::Other,
+    };
+
+    // FIXME(eddyb) isn't the unordered nature of this a hazard?
+    let mut inputs = FxIndexSet::default();
+
+    match node_kind {
+        // In a trait impl, we assume that the header trait ref and all its
+        // constituents are well-formed.
+        NodeKind::TraitImpl => {
+            let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+
+            // FIXME(chalk): this has problems because of late-bound regions
+            //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
+            inputs.extend(trait_ref.substs.iter());
+        }
+
+        // In an inherent impl, we assume that the receiver type and all its
+        // constituents are well-formed.
+        NodeKind::InherentImpl => {
+            let self_ty = tcx.type_of(def_id);
+            inputs.extend(self_ty.walk());
+        }
+
+        // In an fn, we assume that the arguments and all their constituents are
+        // well-formed.
+        NodeKind::Fn => {
+            let fn_sig = tcx.fn_sig(def_id);
+            let fn_sig = tcx.liberate_late_bound_regions(def_id, &fn_sig);
+
+            inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
+        }
+
+        NodeKind::Other => (),
+    }
+    let input_clauses = inputs.into_iter().filter_map(|arg| {
+        match arg.unpack() {
+            GenericArgKind::Type(ty) => {
+                let binder = Binder::dummy(PredicateAtom::TypeWellFormedFromEnv(ty));
+                Some(tcx.mk_predicate(PredicateKind::ForAll(binder)))
+            }
+
+            // FIXME(eddyb) no WF conditions from lifetimes?
+            GenericArgKind::Lifetime(_) => None,
+
+            // FIXME(eddyb) support const generics in Chalk
+            GenericArgKind::Const(_) => None,
+        }
+    });
+
+    tcx.mk_predicates(clauses.chain(input_clauses))
+}
+
 fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     tcx.param_env(def_id).with_reveal_all_normalized(tcx)
 }
index bbf5153d35d9b361b2e23ad539fc40fec8b106bf..7aa54e0ebcc6b5d5d2f9ab3a3a1a90097ab98dc7 100644 (file)
@@ -202,11 +202,8 @@ fn compare_predicate_entailment<'tcx>(
     // The key step here is to update the caller_bounds's predicates to be
     // the new hybrid bounds we computed.
     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id);
-    let param_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&hybrid_preds.predicates),
-        Reveal::UserFacing,
-        None,
-    );
+    let param_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
     let param_env = traits::normalize_param_env_or_error(
         tcx,
         impl_m.def_id,
@@ -1120,11 +1117,8 @@ fn compare_type_predicate_entailment<'tcx>(
     debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
 
     let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
-    let param_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&hybrid_preds.predicates),
-        Reveal::UserFacing,
-        None,
-    );
+    let param_env =
+        ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
     let param_env = traits::normalize_param_env_or_error(
         tcx,
         impl_ty.def_id,
@@ -1227,7 +1221,7 @@ fn compare_projection_bounds<'tcx>(
             })
             .to_predicate(tcx),
         );
-        ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing, None)
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
     };
 
     tcx.infer_ctxt().enter(move |infcx| {
index 14d80fded71220f4c3f27571a1b3627150783c9d..ebe71b86c9221f52de120bd9adfa3a01024fe2b2 100644 (file)
@@ -814,7 +814,8 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
                     | ty::PredicateAtom::ClosureKind(..)
                     | ty::PredicateAtom::TypeOutlives(..)
                     | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..) => None,
+                    | ty::PredicateAtom::ConstEquate(..)
+                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
                 },
             );
 
index cb5f5731aa6117f8ae716b3c3aa36cd5331a2676..b95034adb24d1a4f58e106cd604ace7dfbdc4356 100644 (file)
@@ -3918,6 +3918,7 @@ fn obligations_for_self_ty<'b>(
                     // code is looking for a self type of a unresolved
                     // inference variable.
                     ty::PredicateAtom::ClosureKind(..) => None,
+                    ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
                 }
             })
             .filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root))
index 3746e5778aacdb740694fc3adf08952e710cff8e..60b9467fca8b3dc05674735ec9b7e02c59cced6c 100644 (file)
@@ -405,6 +405,7 @@ fn trait_predicate_kind<'tcx>(
         | ty::PredicateAtom::ObjectSafe(_)
         | ty::PredicateAtom::ClosureKind(..)
         | ty::PredicateAtom::ConstEvaluatable(..)
-        | ty::PredicateAtom::ConstEquate(..) => None,
+        | ty::PredicateAtom::ConstEquate(..)
+        | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
     }
 }
index 135960a4c111414dc1f0d2e187e9890e83d16089..ae336ccca457d1a340c6b40f2cb9f787286eedb3 100644 (file)
@@ -57,7 +57,8 @@ pub fn explicit_predicates_of(
                     | ty::PredicateAtom::ClosureKind(..)
                     | ty::PredicateAtom::Subtype(..)
                     | ty::PredicateAtom::ConstEvaluatable(..)
-                    | ty::PredicateAtom::ConstEquate(..) => (),
+                    | ty::PredicateAtom::ConstEquate(..)
+                    | ty::PredicateAtom::TypeWellFormedFromEnv(..) => (),
                 }
             }
 
index 1bdbad4675556781bfa3a513b7714ad952be1e58..31d420c3a18549c229f555a6f2d5435a9d25cba8 100644 (file)
@@ -508,7 +508,8 @@ fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
             | ty::PredicateAtom::ObjectSafe(..)
             | ty::PredicateAtom::ClosureKind(..)
             | ty::PredicateAtom::ConstEvaluatable(..)
-            | ty::PredicateAtom::ConstEquate(..) => panic!("not user writable"),
+            | ty::PredicateAtom::ConstEquate(..)
+            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => panic!("not user writable"),
         }
     }
 }
index fb8ccbfc660bf9c0929b26c45a9365c982ad5a99..91c46b953159e40d8d01b36b572869f44bd6b897 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `{float}: Bar` is not satisfied
-  --> $DIR/type_inference.rs:27:5
+  --> $DIR/type_inference.rs:27:14
    |
 LL | fn only_bar<T: Bar>(_x: T) { }
    |                --- required by this bound in `only_bar`
 ...
 LL |     only_bar(x);
-   |     ^^^^^^^^ the trait `Bar` is not implemented for `{float}`
+   |              ^ the trait `Bar` is not implemented for `{float}`
    |
    = help: the following implementations were found:
              <i32 as Bar>
index 6d1df4fda2eb052db05b8c94464eac0b2d1fb247..45322ea96721d8be3701049615f8019961a0a9f1 100644 (file)
@@ -18,7 +18,7 @@ LL | enum MList { Cons(isize, MList), Nil }
    | ^^^^^^^^^^
    |
    = note: ...which again requires computing drop-check constraints for `MList`, completing the cycle
-   = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, def_id: None }, value: MList } }`
+   = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: MList } }`
 
 error: aborting due to 2 previous errors