]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #55912 - kennytm:rollup, r=kennytm
authorbors <bors@rust-lang.org>
Tue, 13 Nov 2018 22:17:46 +0000 (22:17 +0000)
committerbors <bors@rust-lang.org>
Tue, 13 Nov 2018 22:17:46 +0000 (22:17 +0000)
Rollup of 20 pull requests

Successful merges:

 - #55136 (Remove short doc where it starts with a codeblock)
 - #55711 (Format BtreeMap::range_mut example)
 - #55722 (impl_stable_hash_for: support enums and tuple structs with generic parameters)
 - #55754 (Avoid converting bytes to UTF-8 strings to print, just pass bytes to stdout/err)
 - #55804 (rustdoc: don't inline `pub use some_crate` unless directly asked to)
 - #55805 (Move `static_assert!` into librustc_data_structures)
 - #55837 (Make PhantomData #[structural_match])
 - #55840 (Fix TLS errors when downloading stage0)
 - #55843 (add FromIterator<A> to Box<[A]>)
 - #55858 (Small fixes on code blocks in rustdoc)
 - #55863 (Fix a typo in std::panic)
 - #55870 (Fix typos.)
 - #55874 (string: Add documentation for `From` impls)
 - #55879 (save-analysis: Don't panic for macro-generated use globs)
 - #55882 (Reference count `crate_inherent_impls`s return value.)
 - #55888 (miri: for uniformity, also move memory_deallocated to AllocationExtra)
 - #55889 (global allocators: add a few comments)
 - #55896 (Document optimizations enabled by FusedIterator)
 - #55905 (Change `Lit::short_name` to `Lit::literal_name`.)
 - #55908 (Fix their/there grammar nit)

84 files changed:
src/Cargo.lock
src/librustc/infer/canonical/substitute.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/mod.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/mem_categorization.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/context.rs
src/librustc/ty/fold.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/subst.rs
src/librustc/util/ppaux.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/mir/place.rs
src/librustc_lint/Cargo.toml
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/borrow_check/nll/type_check/input_output.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/matches/util.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/interpret/visitor.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_target/Cargo.toml
src/librustc_target/abi/mod.rs
src/librustc_target/lib.rs
src/librustc_traits/Cargo.toml
src/librustc_traits/chalk_context.rs [deleted file]
src/librustc_traits/chalk_context/mod.rs [new file with mode: 0644]
src/librustc_traits/chalk_context/program_clauses.rs [new file with mode: 0644]
src/librustc_traits/lib.rs
src/librustc_traits/lowering/environment.rs
src/librustc_traits/lowering/mod.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/mod.rs
src/test/rustdoc/issue-55321.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_env1.rs
src/test/ui/chalkify/lower_env1.stderr
src/test/ui/chalkify/lower_env2.rs
src/test/ui/chalkify/lower_env2.stderr
src/test/ui/chalkify/lower_env3.stderr
src/test/ui/chalkify/lower_impl.stderr
src/test/ui/chalkify/lower_struct.rs
src/test/ui/chalkify/lower_struct.stderr
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/chalkify/lower_trait_higher_rank.rs
src/test/ui/chalkify/lower_trait_higher_rank.stderr
src/test/ui/chalkify/lower_trait_where_clause.rs
src/test/ui/chalkify/lower_trait_where_clause.stderr
src/test/ui/consts/const-eval/ub-enum.stderr
src/test/ui/nll/user-annotations/dump-fn-method.rs
src/test/ui/nll/user-annotations/dump-fn-method.stderr

index 32304c81182f16464301837615f71871247c279b..0c08e35c18df33d53a1ea3b6a82480ca1da76423 100644 (file)
@@ -2246,6 +2246,7 @@ version = "0.0.0"
 dependencies = [
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
  "rustc_mir 0.0.0",
  "rustc_target 0.0.0",
  "syntax 0.0.0",
@@ -2400,6 +2401,7 @@ dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
+ "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
 ]
 
@@ -2417,6 +2419,7 @@ dependencies = [
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
+ "rustc_target 0.0.0",
  "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
index b8c1ed236c0ba17aededa8aff24c46641052eb22..70ce5d0d8dc0c13e6bd6a6a02c3690c9319ca383 100644 (file)
@@ -80,6 +80,6 @@ pub(super) fn substitute_value<'a, 'tcx, T>(
             }
         };
 
-        tcx.replace_escaping_bound_vars(value, fld_r, fld_t)
+        tcx.replace_escaping_bound_vars(value, fld_r, fld_t).0
     }
 }
index 3e08a4e021aedb5660041fbed31271699adc7781..642382bcf0fa31311e17bb035a75c552b17ed31d 100644 (file)
@@ -59,11 +59,11 @@ pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expect
             // with a fresh region variable. These region variables --
             // but no other pre-existing region variables -- can name
             // the placeholders.
-            let (a_prime, _) =
-                self.infcx.replace_late_bound_regions_with_fresh_var(
-                    span,
-                    HigherRankedType,
-                    a);
+            let (a_prime, _) = self.infcx.replace_bound_vars_with_fresh_vars(
+                span,
+                HigherRankedType,
+                a
+            );
 
             debug!("a_prime={:?}", a_prime);
             debug!("b_prime={:?}", b_prime);
index f5513acecf9e7b23fbd518455abbe9aa3dac5b50..4ddf47c88ddbaa8e21cba5b59f59be173195da62 100644 (file)
@@ -1328,18 +1328,18 @@ pub fn report_mismatched_types(
         self.report_and_explain_type_error(trace, &err)
     }
 
-    pub fn replace_late_bound_regions_with_fresh_var<T>(
+    pub fn replace_bound_vars_with_fresh_vars<T>(
         &self,
         span: Span,
         lbrct: LateBoundRegionConversionTime,
-        value: &ty::Binder<T>,
+        value: &ty::Binder<T>
     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
     where
-        T: TypeFoldable<'tcx>,
+        T: TypeFoldable<'tcx>
     {
-        self.tcx.replace_late_bound_regions(value, |br| {
-            self.next_region_var(LateBoundRegion(span, br, lbrct))
-        })
+        let fld_r = |br| self.next_region_var(LateBoundRegion(span, br, lbrct));
+        let fld_t = |_| self.next_ty_var(TypeVariableOrigin::MiscVariable(span));
+        self.tcx.replace_bound_vars(value, fld_r, fld_t)
     }
 
     /// Given a higher-ranked projection predicate like:
index 0a5b1e184deec4ff98f7ecbd8210cd3643f3cac7..d2be0e4dcb9b9cef74b204431ba00b4df0e17a83 100644 (file)
 use hir::def::Def;
 use hir::def_id::DefId;
 use ty::{self, Ty, TyCtxt};
-use ty::layout::{LayoutError, Pointer, SizeSkeleton};
+use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
 
 use rustc_target::spec::abi::Abi::RustIntrinsic;
+use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir;
@@ -48,10 +49,13 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() {
         let data_idx;
 
-        if def.variants[0].fields.is_empty() {
-            data_idx = 1;
-        } else if def.variants[1].fields.is_empty() {
-            data_idx = 0;
+        let one = VariantIdx::new(1);
+        let zero = VariantIdx::new(0);
+
+        if def.variants[zero].fields.is_empty() {
+            data_idx = one;
+        } else if def.variants[one].fields.is_empty() {
+            data_idx = zero;
         } else {
             return ty;
         }
index 9d3f37bc36a9d5873796ba3bd66a3f8582ba8947..59ef8fa14484b6837876aa25b56323df03e4e6f9 100644 (file)
@@ -76,6 +76,7 @@
 use ty::adjustment;
 use ty::{self, Ty, TyCtxt};
 use ty::fold::TypeFoldable;
+use ty::layout::VariantIdx;
 
 use hir::{MutImmutable, MutMutable, PatKind};
 use hir::pat_util::EnumerateAndAdjustIterator;
@@ -87,6 +88,7 @@
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
 use std::rc::Rc;
 use util::nodemap::ItemLocalSet;
 
@@ -227,7 +229,7 @@ fn resolve_field(&self, field_index: usize) -> Option<(&'tcx ty::AdtDef, &'tcx t
             }
             _ => {
                 assert_eq!(adt_def.variants.len(), 1);
-                &adt_def.variants[0]
+                &adt_def.variants[VariantIdx::new(0)]
             }
         };
         Some((adt_def, &variant_def.fields[field_index]))
index 73800074cc7e88a18c5992d9976d99eacaaaf04d..548d0e0c7905f096c399543439c5441896f12f12 100644 (file)
@@ -40,6 +40,7 @@
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::subst::{CanonicalUserSubsts, Subst, Substs};
 use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
+use ty::layout::VariantIdx;
 use util::ppaux;
 
 pub use mir::interpret::AssertMessage;
@@ -1753,7 +1754,7 @@ pub enum StatementKind<'tcx> {
     /// Write the discriminant for a variant to the enum Place.
     SetDiscriminant {
         place: Place<'tcx>,
-        variant_index: usize,
+        variant_index: VariantIdx,
     },
 
     /// Start a live range for the storage of the local.
@@ -1939,7 +1940,7 @@ pub enum ProjectionElem<'tcx, V, T> {
     /// "Downcast" to a variant of an ADT. Currently, we only introduce
     /// this for ADTs with more than one variant. It may be better to
     /// just introduce it always, or always for enums.
-    Downcast(&'tcx AdtDef, usize),
+    Downcast(&'tcx AdtDef, VariantIdx),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
@@ -1950,6 +1951,11 @@ pub enum ProjectionElem<'tcx, V, T> {
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
 
+// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
+static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
+    mem::size_of::<PlaceElem<'_>>() <= 16
+);
+
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
 pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>;
@@ -1969,7 +1975,7 @@ pub fn deref(self) -> Place<'tcx> {
         self.elem(ProjectionElem::Deref)
     }
 
-    pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> {
+    pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
         self.elem(ProjectionElem::Downcast(adt_def, variant_index))
     }
 
@@ -2211,7 +2217,7 @@ pub enum AggregateKind<'tcx> {
     /// active field index would identity the field `c`
     Adt(
         &'tcx AdtDef,
-        usize,
+        VariantIdx,
         &'tcx Substs<'tcx>,
         Option<UserTypeAnnotation<'tcx>>,
         Option<usize>,
index f773f46b6f58cd0d3b98c6065ab2e6b54372db7e..baa88dba459156b49fb5aae9b7efdf054817c0f1 100644 (file)
@@ -16,6 +16,7 @@
 use mir::*;
 use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, Ty, TyCtxt};
+use ty::layout::VariantIdx;
 use hir;
 use ty::util::IntTypeExt;
 
@@ -27,9 +28,13 @@ pub enum PlaceTy<'tcx> {
     /// Downcast to a particular variant of an enum.
     Downcast { adt_def: &'tcx AdtDef,
                substs: &'tcx Substs<'tcx>,
-               variant_index: usize },
+               variant_index: VariantIdx },
 }
 
+static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
+    mem::size_of::<PlaceTy<'_>>() <= 24
+);
+
 impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
         PlaceTy::Ty { ty }
@@ -54,7 +59,7 @@ pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
     pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
     {
         // Pass `0` here so it can be used as a "default" variant_index in first arm below
-        let answer = match (self, 0) {
+        let answer = match (self, VariantIdx::new(0)) {
             (PlaceTy::Ty {
                 ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
             (PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
@@ -134,7 +139,7 @@ pub fn projection_ty_core<V, T, E>(
                 match self.to_ty(tcx).sty {
                     ty::Adt(adt_def, substs) => {
                         assert!(adt_def.is_enum());
-                        assert!(index < adt_def.variants.len());
+                        assert!(index.as_usize() < adt_def.variants.len());
                         assert_eq!(adt_def, adt_def1);
                         PlaceTy::Downcast { adt_def,
                                             substs,
index 8239e5ac56e44c4a5d5eab84ce07ff0cac543755..c3cca149c2c57bc541b679e4ee01778db6aa460c 100644 (file)
@@ -309,7 +309,7 @@ pub fn evaluate_predicates<'b, 'gcx, 'c>(
     ) -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> {
         let tcx = infcx.tcx;
 
-        let mut select = SelectionContext::new(&infcx);
+        let mut select = SelectionContext::with_negative(&infcx, true);
 
         let mut already_visited = FxHashSet::default();
         let mut predicates = VecDeque::new();
@@ -338,6 +338,21 @@ pub fn evaluate_predicates<'b, 'gcx, 'c>(
 
             match &result {
                 &Ok(Some(ref vtable)) => {
+                    // If we see an explicit negative impl (e.g. 'impl !Send for MyStruct'),
+                    // we immediately bail out, since it's impossible for us to continue.
+                    match vtable {
+                        Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
+                            // Blame tidy for the weird bracket placement
+                            if infcx.tcx.impl_polarity(*impl_def_id) == hir::ImplPolarity::Negative
+                            {
+                                debug!("evaluate_nested_obligations: Found explicit negative impl\
+                                        {:?}, bailing out", impl_def_id);
+                                return None;
+                            }
+                        },
+                        _ => {}
+                    }
+
                     let obligations = vtable.clone().nested_obligations().into_iter();
 
                     if !self.evaluate_nested_obligations(
index fbada789956be660c0e10ae04b213cc81993e45d..2761a954cea88deb69adb23334728fb9cb839698 100644 (file)
@@ -212,10 +212,11 @@ fn report_projection_error(&self,
             // cause I have no idea for a good error message.
             if let ty::Predicate::Projection(ref data) = predicate {
                 let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_late_bound_regions_with_fresh_var(
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
                     obligation.cause.span,
                     infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data);
+                    data
+                );
                 let mut obligations = vec![];
                 let normalized_ty = super::normalize_projection_type(
                     &mut selcx,
index e83d085971caa32ef52c6b2fbab491d53c5cc58d..3e417f10c4494833340e5c582c47fbf1798d2a3a 100644 (file)
 use traits::project::Normalized;
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::{self, Lift, TyCtxt};
+use syntax::symbol::InternedString;
 
 use std::fmt;
 use std::rc::Rc;
+use std::collections::{BTreeSet, BTreeMap};
 
 // structural impls for the structs in traits
 
@@ -169,6 +171,290 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::WhereClause::*;
+
+        // Bypass ppaux because it does not print out anonymous regions.
+        fn write_region_name<'tcx>(
+            r: ty::Region<'tcx>,
+            fmt: &mut fmt::Formatter<'_>
+        ) -> fmt::Result {
+            match r {
+                ty::ReLateBound(index, br) => match br {
+                    ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
+                    ty::BoundRegion::BrAnon(var) => {
+                        if *index == ty::INNERMOST {
+                            write!(fmt, "'^{}", var)
+                        } else {
+                            write!(fmt, "'^{}_{}", index.index(), var)
+                        }
+                    }
+                    _ => write!(fmt, "'_"),
+                }
+
+                _ => write!(fmt, "{}", r),
+            }
+        }
+
+        match self {
+            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
+            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+            RegionOutlives(predicate) => {
+                write!(fmt, "RegionOutlives({}: ", predicate.0)?;
+                write_region_name(predicate.1, fmt)?;
+                write!(fmt, ")")
+            }
+            TypeOutlives(predicate) => {
+                write!(fmt, "TypeOutlives({}: ", predicate.0)?;
+                write_region_name(predicate.1, fmt)?;
+                write!(fmt, ")")
+            }
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::WellFormed::*;
+
+        match self {
+            Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
+            Ty(ty) => write!(fmt, "WellFormed({})", ty),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::FromEnv::*;
+
+        match self {
+            Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
+            Ty(ty) => write!(fmt, "FromEnv({})", ty),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::DomainGoal::*;
+
+        match self {
+            Holds(wc) => write!(fmt, "{}", wc),
+            WellFormed(wf) => write!(fmt, "{}", wf),
+            FromEnv(from_env) => write!(fmt, "{}", from_env),
+            Normalize(projection) => write!(
+                fmt,
+                "Normalize({} -> {})",
+                projection.projection_ty,
+                projection.ty
+            ),
+        }
+    }
+}
+
+impl fmt::Display for traits::QuantifierKind {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::QuantifierKind::*;
+
+        match self {
+            Universal => write!(fmt, "forall"),
+            Existential => write!(fmt, "exists"),
+        }
+    }
+}
+
+/// Collect names for regions / types bound by a quantified goal / clause.
+/// This collector does not try to do anything clever like in ppaux, it's just used
+/// for debug output in tests anyway.
+struct BoundNamesCollector {
+    // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
+    regions: BTreeSet<InternedString>,
+
+    // Sort by `BoundVar` index, so usually this should be equivalent to the order given
+    // by the list of type parameters.
+    types: BTreeMap<u32, InternedString>,
+
+    binder_index: ty::DebruijnIndex,
+}
+
+impl BoundNamesCollector {
+    fn new() -> Self {
+        BoundNamesCollector {
+            regions: BTreeSet::new(),
+            types: BTreeMap::new(),
+            binder_index: ty::INNERMOST,
+        }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.regions.is_empty() && self.types.is_empty()
+    }
+
+    fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut start = true;
+        for r in &self.regions {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", r)?;
+        }
+        for (_, t) in &self.types {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", t)?;
+        }
+        Ok(())
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
+    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: ty::Ty<'tcx>) -> bool {
+        use syntax::symbol::Symbol;
+
+        match t.sty {
+            ty::Bound(bound_ty) if bound_ty.index == self.binder_index => {
+                self.types.insert(
+                    bound_ty.var.as_u32(),
+                    match bound_ty.kind {
+                        ty::BoundTyKind::Param(name) => name,
+                        ty::BoundTyKind::Anon => Symbol::intern(
+                            &format!("^{}", bound_ty.var.as_u32())
+                        ).as_interned_str(),
+                    }
+                );
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+        use syntax::symbol::Symbol;
+
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => {
+                match br {
+                    ty::BoundRegion::BrNamed(_, name) => {
+                        self.regions.insert(*name);
+                    }
+
+                    ty::BoundRegion::BrAnon(var) => {
+                        self.regions.insert(Symbol::intern(
+                            &format!("'^{}", var)
+                        ).as_interned_str());
+                    }
+
+                    _ => (),
+                }
+            }
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Goal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::GoalKind::*;
+
+        match self {
+            Implies(hypotheses, goal) => {
+                write!(fmt, "if (")?;
+                for (index, hyp) in hypotheses.iter().enumerate() {
+                    if index > 0 {
+                        write!(fmt, ", ")?;
+                    }
+                    write!(fmt, "{}", hyp)?;
+                }
+                write!(fmt, ") {{ {} }}", goal)
+            }
+            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
+            Not(goal) => write!(fmt, "not {{ {} }}", goal),
+            DomainGoal(goal) => write!(fmt, "{}", goal),
+            Quantified(qkind, goal) => {
+                let mut collector = BoundNamesCollector::new();
+                goal.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "{}<", qkind)?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", goal.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
+            }
+            CannotProve => write!(fmt, "CannotProve"),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let traits::ProgramClause { goal, hypotheses, .. } = self;
+        write!(fmt, "{}", goal)?;
+        if !hypotheses.is_empty() {
+            write!(fmt, " :- ")?;
+            for (index, condition) in hypotheses.iter().enumerate() {
+                if index > 0 {
+                    write!(fmt, ", ")?;
+                }
+                write!(fmt, "{}", condition)?;
+            }
+        }
+        write!(fmt, ".")
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Clause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::Clause::*;
+
+        match self {
+            Implies(clause) => write!(fmt, "{}", clause),
+            ForAll(clause) => {
+                let mut collector = BoundNamesCollector::new();
+                clause.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "forall<")?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", clause.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
+            }
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Lift implementations
 
@@ -348,6 +634,91 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
     }
 }
 
+EnumLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for traits::WhereClause<'a> {
+        type Lifted = traits::WhereClause<'tcx>;
+        (traits::WhereClause::Implemented)(trait_ref),
+        (traits::WhereClause::ProjectionEq)(projection),
+        (traits::WhereClause::TypeOutlives)(ty_outlives),
+        (traits::WhereClause::RegionOutlives)(region_outlives),
+    }
+}
+
+EnumLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for traits::WellFormed<'a> {
+        type Lifted = traits::WellFormed<'tcx>;
+        (traits::WellFormed::Trait)(trait_ref),
+        (traits::WellFormed::Ty)(ty),
+    }
+}
+
+EnumLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for traits::FromEnv<'a> {
+        type Lifted = traits::FromEnv<'tcx>;
+        (traits::FromEnv::Trait)(trait_ref),
+        (traits::FromEnv::Ty)(ty),
+    }
+}
+
+EnumLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
+        type Lifted = traits::DomainGoal<'tcx>;
+        (traits::DomainGoal::Holds)(wc),
+        (traits::DomainGoal::WellFormed)(wf),
+        (traits::DomainGoal::FromEnv)(from_env),
+        (traits::DomainGoal::Normalize)(projection),
+    }
+}
+
+EnumLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
+        type Lifted = traits::GoalKind<'tcx>;
+        (traits::GoalKind::Implies)(hypotheses, goal),
+        (traits::GoalKind::And)(goal1, goal2),
+        (traits::GoalKind::Not)(goal),
+        (traits::GoalKind::DomainGoal)(domain_goal),
+        (traits::GoalKind::Quantified)(kind, goal),
+        (traits::GoalKind::CannotProve),
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
+    type Lifted = traits::Environment<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.clauses).map(|clauses| {
+            traits::Environment {
+                clauses,
+            }
+        })
+    }
+}
+
+impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
+    type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.environment).and_then(|environment| {
+            tcx.lift(&self.goal).map(|goal| {
+                traits::InEnvironment {
+                    environment,
+                    goal,
+                }
+            })
+        })
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ExClauseLift<'tcx>,
+{
+    type Lifted = C::LiftedExClause;
+
+    fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ExClauseLift>::lift_ex_clause_to_tcx(self, tcx)
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 
@@ -436,123 +807,6 @@ impl<'tcx, T> TypeFoldable<'tcx> for Normalized<'tcx, T> {
     } where T: TypeFoldable<'tcx>
 }
 
-impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::WhereClause::*;
-
-        match self {
-            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
-            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
-            RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
-            TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::WellFormed::*;
-
-        match self {
-            Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
-            Ty(ty) => write!(fmt, "WellFormed({})", ty),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::FromEnv::*;
-
-        match self {
-            Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
-            Ty(ty) => write!(fmt, "FromEnv({})", ty),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::DomainGoal::*;
-
-        match self {
-            Holds(wc) => write!(fmt, "{}", wc),
-            WellFormed(wf) => write!(fmt, "{}", wf),
-            FromEnv(from_env) => write!(fmt, "{}", from_env),
-            Normalize(projection) => write!(fmt, "Normalize({})", projection),
-        }
-    }
-}
-
-impl fmt::Display for traits::QuantifierKind {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::QuantifierKind::*;
-
-        match self {
-            Universal => write!(fmt, "forall"),
-            Existential => write!(fmt, "exists"),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::Goal<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::GoalKind::*;
-
-        match self {
-            Implies(hypotheses, goal) => {
-                write!(fmt, "if (")?;
-                for (index, hyp) in hypotheses.iter().enumerate() {
-                    if index > 0 {
-                        write!(fmt, ", ")?;
-                    }
-                    write!(fmt, "{}", hyp)?;
-                }
-                write!(fmt, ") {{ {} }}", goal)
-            }
-            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
-            Not(goal) => write!(fmt, "not {{ {} }}", goal),
-            DomainGoal(goal) => write!(fmt, "{}", goal),
-            Quantified(qkind, goal) => {
-                // FIXME: appropriate binder names
-                write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
-            }
-            CannotProve => write!(fmt, "CannotProve"),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let traits::ProgramClause { goal, hypotheses, .. } = self;
-        write!(fmt, "{}", goal)?;
-        if !hypotheses.is_empty() {
-            write!(fmt, " :- ")?;
-            for (index, condition) in hypotheses.iter().enumerate() {
-                if index > 0 {
-                    write!(fmt, ", ")?;
-                }
-                write!(fmt, "{}", condition)?;
-            }
-        }
-        write!(fmt, ".")
-    }
-}
-
-impl<'tcx> fmt::Display for traits::Clause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use traits::Clause::*;
-
-        match self {
-            Implies(clause) => write!(fmt, "{}", clause),
-            ForAll(clause) => {
-                // FIXME: appropriate binder names
-                write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
-            }
-        }
-    }
-}
-
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for traits::WhereClause<'tcx> {
         (traits::WhereClause::Implemented)(trait_ref),
@@ -562,16 +816,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::WhereClause<'tcx> {
     }
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::WhereClause<'a> {
-        type Lifted = traits::WhereClause<'tcx>;
-        (traits::WhereClause::Implemented)(trait_ref),
-        (traits::WhereClause::ProjectionEq)(projection),
-        (traits::WhereClause::TypeOutlives)(ty_outlives),
-        (traits::WhereClause::RegionOutlives)(region_outlives),
-    }
-}
-
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for traits::WellFormed<'tcx> {
         (traits::WellFormed::Trait)(trait_ref),
@@ -579,14 +823,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::WellFormed<'tcx> {
     }
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::WellFormed<'a> {
-        type Lifted = traits::WellFormed<'tcx>;
-        (traits::WellFormed::Trait)(trait_ref),
-        (traits::WellFormed::Ty)(ty),
-    }
-}
-
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for traits::FromEnv<'tcx> {
         (traits::FromEnv::Trait)(trait_ref),
@@ -594,14 +830,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::FromEnv<'tcx> {
     }
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::FromEnv<'a> {
-        type Lifted = traits::FromEnv<'tcx>;
-        (traits::FromEnv::Trait)(trait_ref),
-        (traits::FromEnv::Ty)(ty),
-    }
-}
-
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
         (traits::DomainGoal::Holds)(wc),
@@ -611,16 +839,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
     }
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
-        type Lifted = traits::DomainGoal<'tcx>;
-        (traits::DomainGoal::Holds)(wc),
-        (traits::DomainGoal::WellFormed)(wf),
-        (traits::DomainGoal::FromEnv)(from_env),
-        (traits::DomainGoal::Normalize)(projection),
-    }
-}
-
 CloneTypeFoldableAndLiftImpls! {
     traits::QuantifierKind,
 }
@@ -636,18 +854,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::GoalKind<'tcx> {
     }
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
-        type Lifted = traits::GoalKind<'tcx>;
-        (traits::GoalKind::Implies)(hypotheses, goal),
-        (traits::GoalKind::And)(goal1, goal2),
-        (traits::GoalKind::Not)(goal),
-        (traits::GoalKind::DomainGoal)(domain_goal),
-        (traits::GoalKind::Quantified)(kind, goal),
-        (traits::GoalKind::CannotProve),
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter()
@@ -702,31 +908,6 @@ impl<'tcx, G> TypeFoldable<'tcx> for traits::InEnvironment<'tcx, G> {
     } where G: TypeFoldable<'tcx>
 }
 
-impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
-    type Lifted = traits::Environment<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.clauses).map(|clauses| {
-            traits::Environment {
-                clauses,
-            }
-        })
-    }
-}
-
-impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
-    type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.environment).and_then(|environment| {
-            tcx.lift(&self.goal).map(|goal| {
-                traits::InEnvironment {
-                    environment,
-                    goal,
-                }
-            })
-        })
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter()
@@ -761,18 +942,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ExClauseLift<'tcx>,
-{
-    type Lifted = C::LiftedExClause;
-
-    fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ExClauseLift>::lift_ex_clause_to_tcx(self, tcx)
-    }
-}
-
 EnumTypeFoldableImpl! {
     impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
         (chalk_engine::DelayedLiteral::CannotProve)(a),
index f78fad9f7aa9a432a5e0a6bc5f88ad453ae8e43d..cdfe8f53b854b96774f75a92b0c0bfcda80097e1 100644 (file)
@@ -45,7 +45,7 @@
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
 use ty::TyKind::*;
 use ty::GenericParamDefKind;
-use ty::layout::{LayoutDetails, TargetDataLayout};
+use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
 use ty::query;
 use ty::steal::Steal;
 use ty::BindingMode;
@@ -1003,7 +1003,7 @@ pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
     pub fn alloc_adt_def(self,
                          did: DefId,
                          kind: AdtKind,
-                         variants: Vec<ty::VariantDef>,
+                         variants: IndexVec<VariantIdx, ty::VariantDef>,
                          repr: ReprOptions)
                          -> &'gcx ty::AdtDef {
         let def = ty::AdtDef::new(self, did, kind, variants, repr);
index ffa4380a5d63c48fcb59687dfdb7af2df841de6f..a897afa0ca663ea1b8979c42045a6a9b3e6f3b35 100644 (file)
@@ -520,22 +520,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn replace_late_bound_regions<T, F>(
         self,
         value: &Binder<T>,
-        mut fld_r: F
+        fld_r: F
     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               T: TypeFoldable<'tcx>
     {
-        let mut map = BTreeMap::new();
-        let mut real_fldr = |br| {
-            *map.entry(br).or_insert_with(|| fld_r(br))
-        };
-
         // identity for bound types
-        let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
-
-        let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t);
-        let result = value.skip_binder().fold_with(&mut replacer);
-        (result, map)
+        let fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
+        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
     }
 
     /// Replace all escaping bound vars. The `fld_r` closure replaces escaping
@@ -545,17 +537,23 @@ pub fn replace_escaping_bound_vars<T, F, G>(
         value: &T,
         mut fld_r: F,
         mut fld_t: G
-    ) -> T
+    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
               T: TypeFoldable<'tcx>
     {
+        let mut map = BTreeMap::new();
+
         if !value.has_escaping_bound_vars() {
-            value.clone()
+            (value.clone(), map)
         } else {
-            let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t);
+            let mut real_fld_r = |br| {
+                *map.entry(br).or_insert_with(|| fld_r(br))
+            };
+
+            let mut replacer = BoundVarReplacer::new(self, &mut real_fld_r, &mut fld_t);
             let result = value.fold_with(&mut replacer);
-            result
+            (result, map)
         }
     }
 
@@ -567,7 +565,7 @@ pub fn replace_bound_vars<T, F, G>(
         value: &Binder<T>,
         fld_r: F,
         fld_t: G
-    ) -> T
+    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
               T: TypeFoldable<'tcx>
index 5aeba652f3228e9988abd367b72adc80440eb691..877bd5a82e6a045441dfc1b002ddc5c7495a5d24 100644 (file)
@@ -23,6 +23,7 @@
 use std::ops::Bound;
 
 use ich::StableHashingContext;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 
@@ -229,7 +230,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>)
             let b_offset = a.value.size(dl).abi_align(b.value.align(dl));
             let size = (b_offset + b.value.size(dl)).abi_align(align);
             LayoutDetails {
-                variants: Variants::Single { index: 0 },
+                variants: Variants::Single { index: VariantIdx::new(0) },
                 fields: FieldPlacement::Arbitrary {
                     offsets: vec![Size::ZERO, b_offset],
                     memory_index: vec![0, 1]
@@ -454,7 +455,7 @@ enum StructKind {
             }
 
             Ok(LayoutDetails {
-                variants: Variants::Single { index: 0 },
+                variants: Variants::Single { index: VariantIdx::new(0) },
                 fields: FieldPlacement::Arbitrary {
                     offsets,
                     memory_index
@@ -499,7 +500,7 @@ enum StructKind {
             // The never type.
             ty::Never => {
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Union(0),
                     abi: Abi::Uninhabited,
                     align: dl.i8_align,
@@ -555,7 +556,7 @@ enum StructKind {
                     .ok_or(LayoutError::SizeOverflow(ty))?;
 
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: element.size,
                         count
@@ -568,7 +569,7 @@ enum StructKind {
             ty::Slice(element) => {
                 let element = self.layout_of(element)?;
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: element.size,
                         count: 0
@@ -580,7 +581,7 @@ enum StructKind {
             }
             ty::Str => {
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: Size::from_bytes(1),
                         count: 0
@@ -650,7 +651,7 @@ enum StructKind {
                 let size = size.abi_align(align);
 
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Single { index: 0 },
+                    variants: Variants::Single { index: VariantIdx::new(0) },
                     fields: FieldPlacement::Array {
                         stride: element.size,
                         count
@@ -671,7 +672,7 @@ enum StructKind {
                     v.fields.iter().map(|field| {
                         self.layout_of(field.ty(tcx, substs))
                     }).collect::<Result<Vec<_>, _>>()
-                }).collect::<Result<Vec<_>, _>>()?;
+                }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
                 if def.is_union() {
                     let packed = def.repr.packed();
@@ -697,7 +698,8 @@ enum StructKind {
                     }
 
                     let mut size = Size::ZERO;
-                    for field in &variants[0] {
+                    let index = VariantIdx::new(0);
+                    for field in &variants[index] {
                         assert!(!field.is_unsized());
 
                         if packed {
@@ -710,8 +712,8 @@ enum StructKind {
                     }
 
                     return Ok(tcx.intern_layout(LayoutDetails {
-                        variants: Variants::Single { index: 0 },
-                        fields: FieldPlacement::Union(variants[0].len()),
+                        variants: Variants::Single { index },
+                        fields: FieldPlacement::Union(variants[index].len()),
                         abi: Abi::Aggregate { sized: true },
                         align,
                         size: size.abi_align(align)
@@ -729,8 +731,12 @@ enum StructKind {
                     uninhabited && is_zst
                 };
                 let (present_first, present_second) = {
-                    let mut present_variants = (0..variants.len()).filter(|&v| {
-                        !absent(&variants[v])
+                    let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| {
+                        if absent(v) {
+                            None
+                        } else {
+                            Some(i)
+                        }
                     });
                     (present_variants.next(), present_variants.next())
                 };
@@ -792,16 +798,16 @@ enum StructKind {
                 // The current code for niche-filling relies on variant indices
                 // instead of actual discriminants, so dataful enums with
                 // explicit discriminants (RFC #2363) would misbehave.
-                let no_explicit_discriminants = def.variants.iter().enumerate()
-                    .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
+                let no_explicit_discriminants = def.variants.iter_enumerated()
+                    .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32()));
 
                 // Niche-filling enum optimization.
                 if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
                     let mut dataful_variant = None;
-                    let mut niche_variants = usize::max_value()..=0;
+                    let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
 
                     // Find one non-ZST variant.
-                    'variants: for (v, fields) in variants.iter().enumerate() {
+                    'variants: for (v, fields) in variants.iter_enumerated() {
                         if absent(fields) {
                             continue 'variants;
                         }
@@ -824,7 +830,9 @@ enum StructKind {
                     }
 
                     if let Some(i) = dataful_variant {
-                        let count = (niche_variants.end() - niche_variants.start() + 1) as u128;
+                        let count = (
+                            niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1
+                        ) as u128;
                         for (field_index, &field) in variants[i].iter().enumerate() {
                             let niche = match self.find_niche(field)? {
                                 Some(niche) => niche,
@@ -836,7 +844,7 @@ enum StructKind {
                             };
 
                             let mut align = dl.aggregate_align;
-                            let st = variants.iter().enumerate().map(|(j, v)| {
+                            let st = variants.iter_enumerated().map(|(j, v)| {
                                 let mut st = univariant_uninterned(v,
                                     &def.repr, StructKind::AlwaysSized)?;
                                 st.variants = Variants::Single { index: j };
@@ -844,7 +852,7 @@ enum StructKind {
                                 align = align.max(st.align);
 
                                 Ok(st)
-                            }).collect::<Result<Vec<_>, _>>()?;
+                            }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
                             let offset = st[i].fields.offset(field_index) + niche.offset;
                             let size = st[i].size;
@@ -899,7 +907,7 @@ enum StructKind {
                 let (mut min, mut max) = (i128::max_value(), i128::min_value());
                 let discr_type = def.repr.discr_type();
                 let bits = Integer::from_attr(self, discr_type).size().bits();
-                for (i, discr) in def.discriminants(tcx).enumerate() {
+                for (i, discr) in def.discriminants(tcx) {
                     if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
                         continue;
                     }
@@ -941,7 +949,7 @@ enum StructKind {
                 }
 
                 // Create the set of structs that represent each variant.
-                let mut layout_variants = variants.iter().enumerate().map(|(i, field_layouts)| {
+                let mut layout_variants = variants.iter_enumerated().map(|(i, field_layouts)| {
                     let mut st = univariant_uninterned(&field_layouts,
                         &def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?;
                     st.variants = Variants::Single { index: i };
@@ -956,7 +964,7 @@ enum StructKind {
                     size = cmp::max(size, st.size);
                     align = align.max(st.align);
                     Ok(st)
-                }).collect::<Result<Vec<_>, _>>()?;
+                }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
 
                 // Align the maximum variant size to the largest alignment.
                 size = size.abi_align(align);
@@ -1259,7 +1267,7 @@ fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
                 debug!("print-type-size `{:#?}` adt general variants def {}",
                        layout.ty, adt_def.variants.len());
                 let variant_infos: Vec<_> =
-                    adt_def.variants.iter().enumerate().map(|(i, variant_def)| {
+                    adt_def.variants.iter_enumerated().map(|(i, variant_def)| {
                         let fields: Vec<_> =
                             variant_def.fields.iter().map(|f| f.ident.name).collect();
                         build_variant_info(Some(variant_def.name),
@@ -1339,7 +1347,8 @@ pub fn compute(ty: Ty<'tcx>,
                 }
 
                 // Get a zero-sized variant or a pointer newtype.
-                let zero_or_ptr_variant = |i: usize| {
+                let zero_or_ptr_variant = |i| {
+                    let i = VariantIdx::new(i);
                     let fields = def.variants[i].fields.iter().map(|field| {
                         SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
                     });
@@ -1562,7 +1571,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
     where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
           C::TyLayout: MaybeResult<TyLayout<'tcx>>
 {
-    fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: usize) -> TyLayout<'tcx> {
+    fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
         let details = match this.variants {
             Variants::Single { index } if index == variant_index => this.details,
 
@@ -1882,6 +1891,16 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for VariantIdx {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        self.as_u32().hash_stable(hcx, hasher)
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for Abi {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
index 979cc9b115b5a2e6307631e1dd035956553eab2f..8197136d189aec581ca0d286c1bdb0c66a24d7d3 100644 (file)
@@ -32,6 +32,7 @@
 use session::CrateDisambiguator;
 use traits::{self, Reveal};
 use ty;
+use ty::layout::VariantIdx;
 use ty::subst::{Subst, Substs};
 use ty::util::{IntTypeExt, Discr};
 use ty::walk::TypeWalker;
@@ -57,7 +58,7 @@
 use syntax_pos::{DUMMY_SP, Span};
 
 use smallvec;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
 
@@ -1789,7 +1790,7 @@ pub enum VariantDiscr {
     /// For efficiency reasons, the distance from the
     /// last `Explicit` discriminant is being stored,
     /// or `0` for the first variant, if it has none.
-    Relative(usize),
+    Relative(u32),
 }
 
 #[derive(Debug)]
@@ -1805,7 +1806,7 @@ pub struct FieldDef {
 /// table.
 pub struct AdtDef {
     pub did: DefId,
-    pub variants: Vec<VariantDef>,
+    pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
     flags: AdtFlags,
     pub repr: ReprOptions,
 }
@@ -2003,7 +2004,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     fn new(tcx: TyCtxt<'_, '_, '_>,
            did: DefId,
            kind: AdtKind,
-           variants: Vec<VariantDef>,
+           variants: IndexVec<VariantIdx, VariantDef>,
            repr: ReprOptions) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
@@ -2125,7 +2126,7 @@ pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(&self) -> &VariantDef {
         assert!(self.is_struct() || self.is_union());
-        &self.variants[0]
+        &self.variants[VariantIdx::new(0)]
     }
 
     #[inline]
@@ -2152,11 +2153,12 @@ pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
             .expect("variant_with_id: unknown variant")
     }
 
-    pub fn variant_index_with_id(&self, vid: DefId) -> usize {
+    pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
         self.variants
-            .iter()
-            .position(|v| v.did == vid)
+            .iter_enumerated()
+            .find(|(_, v)| v.did == vid)
             .expect("variant_index_with_id: unknown variant")
+            .0
     }
 
     pub fn variant_of_def(&self, def: Def) -> &VariantDef {
@@ -2220,11 +2222,11 @@ pub fn eval_explicit_discr(
     pub fn discriminants(
         &'a self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
+    ) -> impl Iterator<Item=(VariantIdx, Discr<'tcx>)> + Captures<'gcx> + 'a {
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx.global_tcx());
         let mut prev_discr = None::<Discr<'tcx>>;
-        self.variants.iter().map(move |v| {
+        self.variants.iter_enumerated().map(move |(i, v)| {
             let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
             if let VariantDiscr::Explicit(expr_did) = v.discr {
                 if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
@@ -2233,7 +2235,7 @@ pub fn discriminants(
             }
             prev_discr = Some(discr);
 
-            discr
+            (i, discr)
         })
     }
 
@@ -2244,7 +2246,7 @@ pub fn discriminants(
     /// assuming there are no constant-evaluation errors there.
     pub fn discriminant_for_variant(&self,
                                     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                    variant_index: usize)
+                                    variant_index: VariantIdx)
                                     -> Discr<'tcx> {
         let (val, offset) = self.discriminant_def_for_variant(variant_index);
         let explicit_value = val
@@ -2258,12 +2260,12 @@ pub fn discriminant_for_variant(&self,
     /// inferred discriminant directly
     pub fn discriminant_def_for_variant(
         &self,
-        variant_index: usize,
-    ) -> (Option<DefId>, usize) {
-        let mut explicit_index = variant_index;
+        variant_index: VariantIdx,
+    ) -> (Option<DefId>, u32) {
+        let mut explicit_index = variant_index.as_u32();
         let expr_did;
         loop {
-            match self.variants[explicit_index].discr {
+            match self.variants[VariantIdx::from_u32(explicit_index)].discr {
                 ty::VariantDiscr::Relative(0) => {
                     expr_did = None;
                     break;
@@ -2277,7 +2279,7 @@ pub fn discriminant_def_for_variant(
                 }
             }
         }
-        (expr_did, variant_index - explicit_index)
+        (expr_did, variant_index.as_u32() - explicit_index)
     }
 
     pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
index 27eafa7ab580f2b1c87c1d6f1df7ff044db88e6c..c82a44011db6c95d00b0323ad8734a8b97c94405 100644 (file)
         ) -> Clauses<'tcx>,
 
         // Get the chalk-style environment of the given item.
-        [] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
+        [] fn environment: Environment(DefId) -> ty::Binder<traits::Environment<'tcx>>,
     },
 
     Linking {
index 59a66513eef0558a274c023b34e3169eeb183bd0..e92f92dce63d06e3bd3df0c6850170110cc2a0cd 100644 (file)
@@ -33,6 +33,7 @@
     (),
     bool,
     usize,
+    ::ty::layout::VariantIdx,
     u64,
     ::middle::region::Scope,
     ::syntax::ast::FloatTy,
index b28e7c9fb199be7daaacce299e889784c7375078..b7f1731ba44e5355510d118cacf41667aab139a2 100644 (file)
@@ -179,6 +179,34 @@ pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
         })
     }
 
+    /// Creates a `Substs` that maps each generic parameter to a higher-ranked
+    /// var bound at index `0`. For types, we use a `BoundVar` index equal to
+    /// the type parameter index. For regions, we use the `BoundRegion::BrNamed`
+    /// variant (which has a def-id).
+    pub fn bound_vars_for_item(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        def_id: DefId
+    ) -> &'tcx Substs<'tcx> {
+        Substs::for_item(tcx, def_id, |param, _| {
+            match param.kind {
+                ty::GenericParamDefKind::Type { .. } => {
+                    tcx.mk_ty(ty::Bound(ty::BoundTy {
+                        index: ty::INNERMOST,
+                        var: ty::BoundVar::from(param.index),
+                        kind: ty::BoundTyKind::Param(param.name),
+                    })).into()
+                }
+
+                ty::GenericParamDefKind::Lifetime => {
+                    tcx.mk_region(ty::RegionKind::ReLateBound(
+                        ty::INNERMOST,
+                        ty::BoundRegion::BrNamed(param.def_id, param.name)
+                    )).into()
+                }
+            }
+        })
+    }
+
     /// Creates a `Substs` for generic parameter definitions,
     /// by calling closures to obtain each kind.
     /// The closures get to observe the `Substs` as they're
index 5ec4f55b142ebbfcac4c74ae4f0eb63de550c5dd..e44c0c05bb1a6c78fdc829f2f509cd002a5f3677 100644 (file)
@@ -1114,9 +1114,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     match bound_ty.kind {
                         ty::BoundTyKind::Anon => {
                             if bound_ty.index == ty::INNERMOST {
-                                write!(f, "?{}", bound_ty.var.index())
+                                write!(f, "^{}", bound_ty.var.index())
                             } else {
-                                write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index())
+                                write!(f, "^{}_{}", bound_ty.index.index(), bound_ty.var.index())
                             }
                         }
 
index 806025937cb110c75028094c56caee1e6fda7f1e..821b074cd68c6925f63f8bbb15cb8979cb1d67ac 100644 (file)
@@ -39,7 +39,7 @@
 use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder};
 use rustc::middle::cstore::{EncodedMetadata};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::middle::exported_symbols;
@@ -73,6 +73,7 @@
 use CrateInfo;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
 
 use std::any::Any;
 use std::cmp;
@@ -309,7 +310,7 @@ pub fn coerce_unsized_into(
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            for i in 0..def_a.variants[0].fields.len() {
+            for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
                 let src_f = src.project_field(bx, i);
                 let dst_f = dst.project_field(bx, i);
 
index 81d615b5ad70a3505ba53819730a29fa6d1227f6..d6fd069071548cf2b259479923d44417ba215893 100644 (file)
@@ -29,7 +29,7 @@
 use rustc::mir::mono::Stats;
 use rustc::session::config::{self, DebugInfo};
 use rustc::session::Session;
-use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout};
+use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout, VariantIdx};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::nodemap::FxHashMap;
 use rustc_target::spec::{HasTargetSpec, Target};
@@ -87,7 +87,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
     /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
     pub used_statics: RefCell<Vec<&'a Value>>,
 
-    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), &'a Type>>,
+    pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'a Type>>,
     pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'a Type>>,
     pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
     pub isize_ty: &'a Type,
index 38b3a1b9c1ab73fdaef222e193102e61ee6316f8..97a3ae9c9faf4e534956892826d4026d241bbed0 100644 (file)
@@ -1241,7 +1241,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
                     // This doesn't matter in this case.
                     NoDiscriminant
                 };
-                (0..variants.len()).map(|i| {
+                variants.iter_enumerated().map(|(i, _)| {
                     let variant = self.layout.for_variant(cx, i);
                     let (variant_type_metadata, member_desc_factory) =
                         describe_enum_variant(cx,
@@ -1341,7 +1341,7 @@ fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                         }
                     ]
                 } else {
-                    (0..variants.len()).map(|i| {
+                    variants.iter_enumerated().map(|(i, _)| {
                         let variant = self.layout.for_variant(cx, i);
                         let (variant_type_metadata, member_desc_factory) =
                             describe_enum_variant(cx,
@@ -1361,8 +1361,8 @@ fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                         let niche_value = if i == dataful_variant {
                             None
                         } else {
-                            let value = (i as u128)
-                                .wrapping_sub(*niche_variants.start() as u128)
+                            let value = (i.as_u32() as u128)
+                                .wrapping_sub(niche_variants.start().as_u32() as u128)
                                 .wrapping_add(niche_start);
                             let value = value & ((1u128 << niche.value.size(cx).bits()) - 1);
                             Some(value as u64)
@@ -1530,7 +1530,7 @@ fn prepare_enum_metadata(
         let def = enum_type.ty_adt_def().unwrap();
         let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
             .zip(&def.variants)
-            .map(|(discr, v)| {
+            .map(|((_, discr), v)| {
                 let name = SmallCStr::new(&v.name.as_str());
                 unsafe {
                     Some(llvm::LLVMRustDIBuilderCreateEnumerator(
index 062f7174680db92a470542e7a6e02877075e54ce..75ec5ead243f9a00bf4f70fbea73189d80358c74 100644 (file)
@@ -10,7 +10,7 @@
 
 use llvm::{self, LLVMConstInBoundsGEP};
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size, VariantIdx};
 use rustc::mir;
 use rustc::mir::tcx::PlaceTy;
 use base;
@@ -281,7 +281,7 @@ pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -
         match self.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = self.layout.ty.ty_adt_def().map_or(
-                    index as u128,
+                    index.as_u32() as u128,
                     |def| def.discriminant_for_variant(bx.cx.tcx, index).val);
                 return C_uint_big(cast_to, discr_val);
             }
@@ -320,16 +320,16 @@ pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -
                         C_uint_big(niche_llty, niche_start)
                     };
                     bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
-                        C_uint(cast_to, *niche_variants.start() as u64),
-                        C_uint(cast_to, dataful_variant as u64))
+                        C_uint(cast_to, niche_variants.start().as_u32() as u64),
+                        C_uint(cast_to, dataful_variant.as_u32() as u64))
                 } else {
                     // Rebase from niche values to discriminant values.
-                    let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
+                    let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
                     let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
-                    let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64);
+                    let lldiscr_max = C_uint(niche_llty, niche_variants.end().as_u32() as u64);
                     bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
                         bx.intcast(lldiscr, cast_to, false),
-                        C_uint(cast_to, dataful_variant as u64))
+                        C_uint(cast_to, dataful_variant.as_u32() as u64))
                 }
             }
         }
@@ -337,7 +337,7 @@ pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -
 
     /// Set the discriminant for a new value of the given case of the given
     /// representation.
-    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) {
+    pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx) {
         if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() {
             return;
         }
@@ -376,7 +376,8 @@ pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usiz
 
                     let niche = self.project_field(bx, 0);
                     let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
-                    let niche_value = ((variant_index - *niche_variants.start()) as u128)
+                    let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+                    let niche_value = (niche_value as u128)
                         .wrapping_add(niche_start);
                     // FIXME(eddyb) Check the actual primitive type here.
                     let niche_llval = if niche_value == 0 {
@@ -401,7 +402,7 @@ pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value)
         }
     }
 
-    pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize)
+    pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx)
                             -> PlaceRef<'ll, 'tcx> {
         let mut downcast = *self;
         downcast.layout = self.layout.for_variant(bx.cx, variant_index);
index f097095abe4e923431dd128cdcabfff373e4e5f3..fe197e3e2e28caf72d3a4c69e24d97c5cfd20a3d 100644 (file)
@@ -16,3 +16,4 @@ rustc_mir = { path = "../librustc_mir"}
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_data_structures = { path = "../librustc_data_structures" }
index 8c0e9bd11a173da5813c13157f8244af22204632..57cbecb5c67be31333e7582b493f26f580f42f5b 100644 (file)
@@ -40,6 +40,7 @@
 extern crate rustc_mir;
 extern crate rustc_target;
 extern crate syntax_pos;
+extern crate rustc_data_structures;
 
 use rustc::lint;
 use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray};
index 4ce87a9675a80d4f8f76740fc6eb58fc11170ed7..0e2d041b1ffdb72e1cc48bf9b4051db0bf0d1f2f 100644 (file)
@@ -13,7 +13,8 @@
 use rustc::hir::Node;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
-use rustc::ty::layout::{self, IntegerExt, LayoutOf};
+use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
+use rustc_data_structures::indexed_vec::Idx;
 use util::nodemap::FxHashSet;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
@@ -452,10 +453,13 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if def.variants.len() == 2 {
         let data_idx;
 
-        if def.variants[0].fields.is_empty() {
-            data_idx = 1;
-        } else if def.variants[1].fields.is_empty() {
-            data_idx = 0;
+        let zero = VariantIdx::new(0);
+        let one = VariantIdx::new(1);
+
+        if def.variants[zero].fields.is_empty() {
+            data_idx = one;
+        } else if def.variants[one].fields.is_empty() {
+            data_idx = zero;
         } else {
             return false;
         }
index 0854df5d1269f36679846fd387347d1c1c59128b..1c7e3c95d147058bbc8a0871ff1c1199eef05f3e 100644 (file)
@@ -601,7 +601,7 @@ pub fn get_adt_def(&self,
                 })
                 .collect()
         } else {
-            vec![self.get_variant(tcx, &item, item_id, kind)]
+            std::iter::once(self.get_variant(tcx, &item, item_id, kind)).collect()
         };
 
         tcx.alloc_adt_def(did, kind, variants, repr)
index c9df36c5e236aa1dce3d83cc7c7c248d088f5696..5421972a4adcbd528803a1e11dbb1bca44796f86 100644 (file)
@@ -27,6 +27,7 @@
 use rustc::traits::specialization_graph;
 use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
 use rustc::ty::codec::{self as ty_codec, TyEncoder};
+use rustc::ty::layout::VariantIdx;
 
 use rustc::session::config::{self, CrateType};
 use rustc::util::nodemap::FxHashMap;
@@ -580,7 +581,7 @@ fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
     /// the right to access any information in the adt-def (including,
     /// e.g., the length of the various vectors).
     fn encode_enum_variant_info(&mut self,
-                                (enum_did, Untracked(index)): (DefId, Untracked<usize>))
+                                (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>))
                                 -> Entry<'tcx> {
         let tcx = self.tcx;
         let def = tcx.adt_def(enum_did);
@@ -675,7 +676,7 @@ fn encode_info_for_mod(&mut self,
     /// vectors).
     fn encode_field(&mut self,
                     (adt_def_id, Untracked((variant_index, field_index))): (DefId,
-                                                                            Untracked<(usize,
+                                                                            Untracked<(VariantIdx,
                                                                                        usize)>))
                     -> Entry<'tcx> {
         let tcx = self.tcx;
@@ -1667,7 +1668,7 @@ fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
     fn encode_fields(&mut self, adt_def_id: DefId) {
         let def = self.tcx.adt_def(adt_def_id);
-        for (variant_index, variant) in def.variants.iter().enumerate() {
+        for (variant_index, variant) in def.variants.iter_enumerated() {
             for (field_index, field) in variant.fields.iter().enumerate() {
                 self.record(field.did,
                             IsolatedEncoder::encode_field,
@@ -1734,7 +1735,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 self.encode_fields(def_id);
 
                 let def = self.tcx.adt_def(def_id);
-                for (i, variant) in def.variants.iter().enumerate() {
+                for (i, variant) in def.variants.iter_enumerated() {
                     self.record(variant.did,
                                 IsolatedEncoder::encode_enum_variant_info,
                                 (def_id, Untracked(i)));
index ab4ee3a4ad0e51b15e2e866f2ebb1facf478d147..85ea39e538f785a6aee3b9969b4da7872d7bef1b 100644 (file)
@@ -62,7 +62,7 @@ pub(super) fn equate_inputs_and_outputs(
                     // "inside" the closure.
                     Some(
                         self.infcx
-                            .replace_late_bound_regions_with_fresh_var(
+                            .replace_bound_vars_with_fresh_vars(
                                 mir.span,
                                 LateBoundRegionConversionTime::FnCall,
                                 &poly_sig,
index a057f2f45c0105e8090de91b4e049d2f4a466523..2193dba9fcac8b9053d5b1ee004070308e5f9dcb 100644 (file)
@@ -47,7 +47,8 @@
 use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc::ty::layout::VariantIdx;
 use std::rc::Rc;
 use std::{fmt, iter};
 use syntax_pos::{Span, DUMMY_SP};
@@ -574,7 +575,7 @@ fn sanitize_projection(
             },
             ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
                 ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
-                    if index >= adt_def.variants.len() {
+                    if index.as_usize() >= adt_def.variants.len() {
                         PlaceTy::Ty {
                             ty: span_mirbug_and_err!(
                                 self,
@@ -654,7 +655,8 @@ fn field_ty(
                 variant_index,
             } => (&adt_def.variants[variant_index], substs),
             PlaceTy::Ty { ty } => match ty.sty {
-                ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs),
+                ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
+                    (&adt_def.variants[VariantIdx::new(0)], substs),
                 ty::Closure(def_id, substs) => {
                     return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
                         Some(ty) => Ok(ty),
@@ -1280,7 +1282,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                         );
                     }
                 };
-                if variant_index >= adt.variants.len() {
+                if variant_index.as_usize() >= adt.variants.len() {
                     span_bug!(
                         stmt.source_info.span,
                         "bad set discriminant ({:?} = {:?}): value of of range",
@@ -1404,7 +1406,7 @@ fn check_terminator(
                         return;
                     }
                 };
-                let (sig, map) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                let (sig, map) = self.infcx.replace_bound_vars_with_fresh_vars(
                     term.source_info.span,
                     LateBoundRegionConversionTime::FnCall,
                     &sig,
index b92f270255af4fa23bbe4a00bb1476cc3cb8b208..342aaf9039d1001f9b3b7c1291abeda82037933f 100644 (file)
@@ -22,6 +22,7 @@
 use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, Ty};
+use rustc::ty::layout::VariantIdx;
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::{Name, NodeId};
@@ -663,7 +664,7 @@ enum TestKind<'tcx> {
     // test the branches of enum
     Switch {
         adt_def: &'tcx ty::AdtDef,
-        variants: BitSet<usize>,
+        variants: BitSet<VariantIdx>,
     },
 
     // test the branches of enum
index 349d877d52474eec8ae1ec1dc37c781c68d4e260..cfea357334fa81eff56daff3fef8cc728e39db61 100644 (file)
@@ -123,7 +123,7 @@ fn simplify_match_pair<'pat>(&mut self,
             }
 
             PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
-                let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
+                let irrefutable = adt_def.variants.iter_enumerated().all(|(i, v)| {
                     i == variant_index || {
                         self.hir.tcx().features().never_type &&
                         self.hir.tcx().features().exhaustive_patterns &&
index 9e6f32909bdea00cb97abd1cae78e963e2d36726..177c71b80d1f5284065d159185fff13f63a7f9e9 100644 (file)
@@ -22,6 +22,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
+use rustc::ty::layout::VariantIdx;
 use rustc::mir::*;
 use rustc::hir::{RangeEnd, Mutability};
 use syntax_pos::Span;
@@ -152,7 +153,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
     pub fn add_variants_to_switch<'pat>(&mut self,
                                         test_place: &Place<'tcx>,
                                         candidate: &Candidate<'pat, 'tcx>,
-                                        variants: &mut BitSet<usize>)
+                                        variants: &mut BitSet<VariantIdx>)
                                         -> bool
     {
         let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
@@ -196,7 +197,7 @@ pub fn perform_test(&mut self,
                 let mut targets = Vec::with_capacity(used_variants + 1);
                 let mut values = Vec::with_capacity(used_variants);
                 let tcx = self.hir.tcx();
-                for (idx, discr) in adt_def.discriminants(tcx).enumerate() {
+                for (idx, discr) in adt_def.discriminants(tcx) {
                     target_blocks.push(if variants.contains(idx) {
                         values.push(discr.val);
                         targets.push(self.cfg.start_new_block());
@@ -512,7 +513,7 @@ pub fn sort_candidate<'pat>(&mut self,
                                                         variant_index,
                                                         subpatterns,
                                                         candidate);
-                resulting_candidates[variant_index].push(new_candidate);
+                resulting_candidates[variant_index.as_usize()].push(new_candidate);
                 true
             }
             (&TestKind::Switch { .. }, _) => false,
@@ -673,7 +674,7 @@ fn candidate_after_slice_test<'pat>(&mut self,
     fn candidate_after_variant_switch<'pat>(&mut self,
                                             match_pair_index: usize,
                                             adt_def: &'tcx ty::AdtDef,
-                                            variant_index: usize,
+                                            variant_index: VariantIdx,
                                             subpatterns: &'pat [FieldPattern<'tcx>],
                                             candidate: &Candidate<'pat, 'tcx>)
                                             -> Candidate<'pat, 'tcx> {
index cfd9100fc6ae7c8482b3a1667fd3a01f5d28b010..a87660db2d313b1dcb809433cc11d960778f1750 100644 (file)
@@ -13,6 +13,7 @@
 use hair::*;
 use rustc::mir::*;
 use std::u32;
+use std::convert::TryInto;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn field_match_pairs<'pat>(&mut self,
@@ -35,8 +36,7 @@ pub fn prefix_slice_suffix<'pat>(&mut self,
                                      opt_slice: Option<&'pat Pattern<'tcx>>,
                                      suffix: &'pat [Pattern<'tcx>]) {
         let min_length = prefix.len() + suffix.len();
-        assert!(min_length < u32::MAX as usize);
-        let min_length = min_length as u32;
+        let min_length = min_length.try_into().unwrap();
 
         match_pairs.extend(
             prefix.iter()
index 011887090eefe8002f3ffffc9b02f2ef415b718c..222920f1ad65ad374787c420a2cbc8b61f55ce09 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
 use rustc::mir;
 use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt};
-use rustc::ty::layout::{self, LayoutOf, TyLayout};
+use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx};
 use rustc::ty::subst::Subst;
 use rustc::traits::Reveal;
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -481,7 +481,7 @@ pub fn const_field<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     instance: ty::Instance<'tcx>,
-    variant: Option<usize>,
+    variant: Option<VariantIdx>,
     field: mir::Field,
     value: &'tcx ty::Const<'tcx>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
@@ -513,7 +513,7 @@ pub fn const_variant_index<'a, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     instance: ty::Instance<'tcx>,
     val: &'tcx ty::Const<'tcx>,
-) -> EvalResult<'tcx, usize> {
+) -> EvalResult<'tcx, VariantIdx> {
     trace!("const_variant_index: {:?}, {:?}", instance, val);
     let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let op = ecx.const_to_op(val)?;
index 48fcdd42ff5e0b3ecf4419aa18c171d5d58045f2..656a467fb4912827fb5f560e73afcacbbea622f3 100644 (file)
@@ -284,7 +284,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 Some((adt_def, adt_def.variant_index_with_id(variant_id)))
                             }
                             Def::StructCtor(_, CtorKind::Fn) |
-                            Def::SelfCtor(..) => Some((adt_def, 0)),
+                            Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
                             _ => None,
                         }
                     })
@@ -468,7 +468,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         AdtKind::Struct | AdtKind::Union => {
                             ExprKind::Adt {
                                 adt_def: adt,
-                                variant_index: 0,
+                                variant_index: VariantIdx::new(0),
                                 substs,
                                 user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
                                 fields: field_refs(cx, fields),
index 3a56d261111eee4ec0e46de7883944dc5358fde3..733580b3ce2fd4acfd8c7beb64807012651724e4 100644 (file)
@@ -25,6 +25,7 @@
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::layout::VariantIdx;
 use syntax::ast::{self, LitKind};
 use syntax::attr;
 use syntax::symbol::Symbol;
@@ -228,7 +229,7 @@ pub fn trait_method(&mut self,
         bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
-    pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: usize) -> Vec<Field> {
+    pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
         (0..adt_def.variants[variant_index].fields.len())
             .map(Field::new)
             .collect()
index 8a24851de8149f2bcb301b9772f76bf5c6e69d6a..460afba38d67427aa231f1c62d0ff92c17731a49 100644 (file)
@@ -19,6 +19,7 @@
 use rustc::middle::region;
 use rustc::ty::subst::Substs;
 use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
+use rustc::ty::layout::VariantIdx;
 use rustc::hir;
 use syntax::ast;
 use syntax_pos::Span;
@@ -264,7 +265,7 @@ pub enum ExprKind<'tcx> {
     },
     Adt {
         adt_def: &'tcx AdtDef,
-        variant_index: usize,
+        variant_index: VariantIdx,
         substs: &'tcx Substs<'tcx>,
 
         /// Optional user-given substs: for something like `let x =
index 69ca21c56242f954a76cca7bd849d21f593bd41c..08736330acbe72b46d23d1a0a5ae701b9d0ac610 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::hir::RangeEnd;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::layout::{Integer, IntegerExt};
+use rustc::ty::layout::{Integer, IntegerExt, VariantIdx};
 
 use rustc::mir::Field;
 use rustc::mir::interpret::ConstValue;
@@ -422,12 +422,12 @@ pub enum Constructor<'tcx> {
 }
 
 impl<'tcx> Constructor<'tcx> {
-    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize {
+    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx {
         match self {
             &Variant(vid) => adt.variant_index_with_id(vid),
             &Single => {
                 assert!(!adt.is_enum());
-                0
+                VariantIdx::new(0)
             }
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt)
         }
index 0acb4052fd73e04d2852d66cffbe7042560fc064..941744c0aab7cc285c1e8bfd5a8173fede1933f5 100644 (file)
@@ -25,6 +25,7 @@
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
 use rustc::ty::subst::{Substs, Kind};
+use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -111,7 +112,7 @@ pub(crate) fn leaf(&self, field: Field) -> Self {
 
     pub(crate) fn variant(&self,
                           adt_def: &'tcx AdtDef,
-                          variant_index: usize,
+                          variant_index: VariantIdx,
                           field: Field) -> Self {
         self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
     }
@@ -153,7 +154,7 @@ pub(crate) fn leaf(&self, field: Field) -> Self {
 
     pub(crate) fn variant(&self,
                           adt_def: &'tcx AdtDef,
-                          variant_index: usize,
+                          variant_index: VariantIdx,
                           field: Field) -> Self {
         let mut new = self.clone();
         new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
@@ -200,7 +201,7 @@ pub enum PatternKind<'tcx> {
     Variant {
         adt_def: &'tcx AdtDef,
         substs: &'tcx Substs<'tcx>,
-        variant_index: usize,
+        variant_index: VariantIdx,
         subpatterns: Vec<FieldPattern<'tcx>>,
     },
 
@@ -273,7 +274,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     }
                     _ => if let ty::Adt(adt, _) = self.ty.sty {
                         if !adt.is_enum() {
-                            Some(&adt.variants[0])
+                            Some(&adt.variants[VariantIdx::new(0)])
                         } else {
                             None
                         }
@@ -1160,7 +1161,7 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
             } => PatternKind::Variant {
                 adt_def: adt_def.fold_with(folder),
                 substs: substs.fold_with(folder),
-                variant_index: variant_index.fold_with(folder),
+                variant_index,
                 subpatterns: subpatterns.fold_with(folder)
             },
             PatternKind::Leaf {
index d43ec0bd349abd301dac2c96f8c4971eebc8d290..402632ef46a542ea4a5ff811af6845d3411f4fbd 100644 (file)
@@ -14,7 +14,7 @@
 use std::convert::TryInto;
 
 use rustc::{mir, ty};
-use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
+use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx};
 
 use rustc::mir::interpret::{
     GlobalId, AllocId,
@@ -417,7 +417,7 @@ pub fn operand_field(
     pub fn operand_downcast(
         &self,
         op: OpTy<'tcx, M::PointerTag>,
-        variant: usize,
+        variant: VariantIdx,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
         Ok(match op.try_as_mplace() {
@@ -596,13 +596,13 @@ pub(super) fn global_to_op(
     pub fn read_discriminant(
         &self,
         rval: OpTy<'tcx, M::PointerTag>,
-    ) -> EvalResult<'tcx, (u128, usize)> {
+    ) -> EvalResult<'tcx, (u128, VariantIdx)> {
         trace!("read_discriminant_value {:#?}", rval.layout);
 
         match rval.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = rval.layout.ty.ty_adt_def().map_or(
-                    index as u128,
+                    index.as_u32() as u128,
                     |def| def.discriminant_for_variant(*self.tcx, index).val);
                 return Ok((discr_val, index));
             }
@@ -645,9 +645,9 @@ pub fn read_discriminant(
                     .ty_adt_def()
                     .expect("tagged layout for non adt")
                     .discriminants(self.tcx.tcx)
-                    .position(|var| var.val == real_discr)
+                    .find(|(_, var)| var.val == real_discr)
                     .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
-                (real_discr, index)
+                (real_discr, index.0)
             },
             layout::Variants::NicheFilling {
                 dataful_variant,
@@ -655,33 +655,32 @@ pub fn read_discriminant(
                 niche_start,
                 ..
             } => {
-                let variants_start = *niche_variants.start() as u128;
-                let variants_end = *niche_variants.end() as u128;
-                let real_discr = match raw_discr {
+                let variants_start = niche_variants.start().as_u32() as u128;
+                let variants_end = niche_variants.end().as_u32() as u128;
+                match raw_discr {
                     Scalar::Ptr(_) => {
                         // The niche must be just 0 (which a pointer value never is)
                         assert!(niche_start == 0);
                         assert!(variants_start == variants_end);
-                        dataful_variant as u128
+                        (dataful_variant.as_u32() as u128, dataful_variant)
                     },
                     Scalar::Bits { bits: raw_discr, size } => {
                         assert_eq!(size as u64, discr_val.layout.size.bytes());
                         let discr = raw_discr.wrapping_sub(niche_start)
                             .wrapping_add(variants_start);
                         if variants_start <= discr && discr <= variants_end {
-                            discr
+                            let index = discr as usize;
+                            assert_eq!(index as u128, discr);
+                            assert!(index < rval.layout.ty
+                                .ty_adt_def()
+                                .expect("tagged layout for non adt")
+                                .variants.len());
+                            (discr, VariantIdx::from_usize(index))
                         } else {
-                            dataful_variant as u128
+                            (dataful_variant.as_u32() as u128, dataful_variant)
                         }
                     },
-                };
-                let index = real_discr as usize;
-                assert_eq!(index as u128, real_discr);
-                assert!(index < rval.layout.ty
-                    .ty_adt_def()
-                    .expect("tagged layout for non adt")
-                    .variants.len());
-                (real_discr, index)
+                }
             }
         })
     }
index 6f8bbf3c4a97de0475f2807c7b018a4c748b468d..c9ec83a7adb2789f538f8f51b2d11d5cf13c7513 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::hir;
 use rustc::mir;
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout};
+use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
 
 use rustc::mir::interpret::{
     GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
@@ -431,7 +431,7 @@ pub fn mplace_subslice(
     pub fn mplace_downcast(
         &self,
         base: MPlaceTy<'tcx, M::PointerTag>,
-        variant: usize,
+        variant: VariantIdx,
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // Downcasts only change the layout
         assert!(base.meta.is_none());
@@ -498,7 +498,7 @@ pub fn place_field(
     pub fn place_downcast(
         &self,
         base: PlaceTy<'tcx, M::PointerTag>,
-        variant: usize,
+        variant: VariantIdx,
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         // Downcast just changes the layout
         Ok(match base.place {
@@ -901,7 +901,7 @@ pub fn allocate(
 
     pub fn write_discriminant_index(
         &mut self,
-        variant_index: usize,
+        variant_index: VariantIdx,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
         match dest.layout.variants {
@@ -910,7 +910,7 @@ pub fn write_discriminant_index(
             }
             layout::Variants::Tagged { ref tag, .. } => {
                 let adt_def = dest.layout.ty.ty_adt_def().unwrap();
-                assert!(variant_index < adt_def.variants.len());
+                assert!(variant_index.as_usize() < adt_def.variants.len());
                 let discr_val = adt_def
                     .discriminant_for_variant(*self.tcx, variant_index)
                     .val;
@@ -931,11 +931,14 @@ pub fn write_discriminant_index(
                 niche_start,
                 ..
             } => {
-                assert!(variant_index < dest.layout.ty.ty_adt_def().unwrap().variants.len());
+                assert!(
+                    variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(),
+                );
                 if variant_index != dataful_variant {
                     let niche_dest =
                         self.place_field(dest, 0)?;
-                    let niche_value = ((variant_index - niche_variants.start()) as u128)
+                    let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
+                    let niche_value = (niche_value as u128)
                         .wrapping_add(niche_start);
                     self.write_scalar(
                         Scalar::from_uint(niche_value, niche_dest.layout.size),
index 84aa5b6756660ceb4f224c37324e1ec6fe7d3668..3d00dce8b0428f51d403e09b56d92b9e8b336598 100644 (file)
@@ -13,7 +13,7 @@
 use std::ops::RangeInclusive;
 
 use syntax_pos::symbol::Symbol;
-use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf};
+use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx};
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
@@ -74,6 +74,7 @@ macro_rules! try_validation {
 #[derive(Copy, Clone, Debug)]
 pub enum PathElem {
     Field(Symbol),
+    Variant(Symbol),
     ClosureVar(Symbol),
     ArrayElem(usize),
     TupleElem(usize),
@@ -107,6 +108,7 @@ fn path_format(path: &Vec<PathElem>) -> String {
     for elem in path.iter() {
         match elem {
             Field(name) => write!(out, ".{}", name),
+            Variant(name) => write!(out, ".<downcast-variant({})>", name),
             ClosureVar(name) => write!(out, ".<closure-var({})>", name),
             TupleElem(idx) => write!(out, ".{}", idx),
             ArrayElem(idx) => write!(out, "[{}]", idx),
@@ -165,12 +167,12 @@ struct ValidityVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir, M: Machine<'a
 }
 
 impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> {
-    fn push_aggregate_field_path_elem(
+    fn aggregate_field_path_elem(
         &mut self,
         layout: TyLayout<'tcx>,
         field: usize,
-    ) {
-        let elem = match layout.ty.sty {
+    ) -> PathElem {
+        match layout.ty.sty {
             // generators and closures.
             ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                 if let Some(upvar) = self.ecx.tcx.optimized_mir(def_id).upvar_decls.get(field) {
@@ -192,9 +194,7 @@ fn push_aggregate_field_path_elem(
                     layout::Variants::Single { index } =>
                         // Inside a variant
                         PathElem::Field(def.variants[index].fields[field].ident.name),
-                    _ =>
-                        // To a variant
-                        PathElem::Field(def.variants[field].name)
+                    _ => bug!(),
                 }
             }
 
@@ -209,8 +209,22 @@ fn push_aggregate_field_path_elem(
 
             // nothing else has an aggregate layout
             _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
-        };
+        }
+    }
+
+    fn visit_elem(
+        &mut self,
+        new_op: OpTy<'tcx, M::PointerTag>,
+        elem: PathElem,
+    ) -> EvalResult<'tcx> {
+        // Remember the old state
+        let path_len = self.path.len();
+        // Perform operation
         self.path.push(elem);
+        self.visit_value(new_op)?;
+        // Undo changes
+        self.path.truncate(path_len);
+        Ok(())
     }
 }
 
@@ -231,14 +245,19 @@ fn visit_field(
         field: usize,
         new_op: OpTy<'tcx, M::PointerTag>
     ) -> EvalResult<'tcx> {
-        // Remember the old state
-        let path_len = self.path.len();
-        // Perform operation
-        self.push_aggregate_field_path_elem(old_op.layout, field);
-        self.visit_value(new_op)?;
-        // Undo changes
-        self.path.truncate(path_len);
-        Ok(())
+        let elem = self.aggregate_field_path_elem(old_op.layout, field);
+        self.visit_elem(new_op, elem)
+    }
+
+    #[inline]
+    fn visit_variant(
+        &mut self,
+        old_op: OpTy<'tcx, M::PointerTag>,
+        variant_id: VariantIdx,
+        new_op: OpTy<'tcx, M::PointerTag>
+    ) -> EvalResult<'tcx> {
+        let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].name;
+        self.visit_elem(new_op, PathElem::Variant(name))
     }
 
     #[inline]
index 392e27918092f45ec2b4a2093b99a7de4542b51b..4a470456432533fb1a13f4835508fe07a709385c 100644 (file)
@@ -1,7 +1,7 @@
 //! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
 //! types until we arrive at the leaves, with custom handling for primitive types.
 
-use rustc::ty::layout::{self, TyLayout};
+use rustc::ty::layout::{self, TyLayout, VariantIdx};
 use rustc::ty;
 use rustc::mir::interpret::{
     EvalResult,
@@ -32,7 +32,7 @@ fn to_op(
     fn project_downcast(
         self,
         ecx: &EvalContext<'a, 'mir, 'tcx, M>,
-        variant: usize,
+        variant: VariantIdx,
     ) -> EvalResult<'tcx, Self>;
 
     /// Project to the n-th field.
@@ -70,7 +70,7 @@ fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
     fn project_downcast(
         self,
         ecx: &EvalContext<'a, 'mir, 'tcx, M>,
-        variant: usize,
+        variant: VariantIdx,
     ) -> EvalResult<'tcx, Self> {
         ecx.operand_downcast(self, variant)
     }
@@ -109,7 +109,7 @@ fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
     fn project_downcast(
         self,
         ecx: &EvalContext<'a, 'mir, 'tcx, M>,
-        variant: usize,
+        variant: VariantIdx,
     ) -> EvalResult<'tcx, Self> {
         ecx.mplace_downcast(self, variant)
     }
@@ -171,6 +171,16 @@ fn visit_field(
                 self.visit_value(new_val)
             }
 
+            #[inline(always)]
+            fn visit_variant(
+                &mut self,
+                _old_val: Self::V,
+                _variant: VariantIdx,
+                new_val: Self::V,
+            ) -> EvalResult<'tcx> {
+                self.visit_value(new_val)
+            }
+
             /// Called whenever we reach a value with uninhabited layout.
             /// Recursing to fields will *always* continue after this!  This is not meant to control
             /// whether and how we descend recursively/ into the scalar's fields if there are any,
@@ -221,7 +231,7 @@ fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
                         let inner = v.project_downcast(self.ecx(), idx)?;
                         trace!("walk_value: variant layout: {:#?}", inner.layout());
                         // recurse with the inner type
-                        return self.visit_field(v, idx, inner);
+                        return self.visit_variant(v, idx, inner);
                     }
                     layout::Variants::Single { .. } => {}
                 }
index 54983b8f4e026abd40026540e985dd2095a7cd80..e99af56c22c0088b6e1b3b8ecda7ed25b9430f3e 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::infer;
 use rustc::mir::*;
 use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
+use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::query::Providers;
 
@@ -291,7 +292,7 @@ fn field_subpath(&self, _path: Self::Path, _field: Field) -> Option<Self::Path>
     fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
         None
     }
-    fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> {
+    fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
         Some(())
     }
     fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> {
@@ -867,7 +868,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     let variant_no = if adt_def.is_enum() {
         adt_def.variant_index_with_id(def_id)
     } else {
-        0
+        VariantIdx::new(0)
     };
 
     // return = ADT(arg0, arg1, ...); return
index 5de289068b25509db5fd4e49de7e217b763fdde2..2b3fd552e0faa9cd119f3f021793e805fef37383 100644 (file)
@@ -16,6 +16,7 @@
 use dataflow::MoveDataParamEnv;
 use dataflow::{self, do_dataflow, DebugFormatted};
 use rustc::ty::{self, TyCtxt};
+use rustc::ty::layout::VariantIdx;
 use rustc::mir::*;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::bit_set::BitSet;
@@ -282,7 +283,7 @@ fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
         })
     }
 
-    fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path> {
+    fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> {
         dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection {
index 5889fabee9d6e25423db1b39348ebaeeee36bcef..9d633fa2b0b7c1d14ad5044ae1586c8f9854d503 100644 (file)
@@ -64,6 +64,7 @@
 use rustc::mir::*;
 use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty};
+use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::Substs;
 use util::dump_mir;
 use util::liveness::{self, IdentityMap};
@@ -158,7 +159,7 @@ struct TransformVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
     // Make a GeneratorState rvalue
-    fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> {
+    fn make_state(&self, idx: VariantIdx, val: Operand<'tcx>) -> Rvalue<'tcx> {
         let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None);
         Rvalue::Aggregate(box adt, vec![val])
     }
@@ -229,11 +230,11 @@ fn visit_basic_block_data(&mut self,
         });
 
         let ret_val = match data.terminator().kind {
-            TerminatorKind::Return => Some((1,
+            TerminatorKind::Return => Some((VariantIdx::new(1),
                 None,
                 Operand::Move(Place::Local(self.new_ret_local)),
                 None)),
-            TerminatorKind::Yield { ref value, resume, drop } => Some((0,
+            TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
                 Some(resume),
                 value.clone(),
                 drop)),
index d9a1e4a0fd63948d475b879340efced2c0918222..2c7f337b3b1c0a677595feb39f60ee73db5d5df6 100644 (file)
@@ -14,6 +14,7 @@
 use rustc::middle::lang_items;
 use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::layout::VariantIdx;
 use rustc::ty::subst::Substs;
 use rustc::ty::util::IntTypeExt;
 use rustc_data_structures::indexed_vec::Idx;
@@ -94,7 +95,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
 
     fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>;
     fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path>;
-    fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path>;
+    fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path>;
     fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path>;
 }
 
@@ -392,7 +393,7 @@ fn open_drop_for_adt_contents(&mut self, adt: &'tcx ty::AdtDef,
             let fields = self.move_paths_for_fields(
                 self.place,
                 self.path,
-                &adt.variants[0],
+                &adt.variants[VariantIdx::new(0)],
                 substs
             );
             self.drop_ladder(fields, succ, unwind)
@@ -416,7 +417,7 @@ fn open_drop_for_multivariant(&mut self, adt: &'tcx ty::AdtDef,
 
         let mut have_otherwise = false;
 
-        for (variant_index, discr) in adt.discriminants(self.tcx()).enumerate() {
+        for (variant_index, discr) in adt.discriminants(self.tcx()) {
             let subpath = self.elaborator.downcast_subpath(
                 self.path, variant_index);
             if let Some(variant_path) = subpath {
@@ -894,7 +895,7 @@ fn unelaborated_free_block<'a>(
         let tcx = self.tcx();
         let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
         let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
-        let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
+        let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
             let field = Field::new(i);
             let field_ty = f.ty(self.tcx(), substs);
             Operand::Move(self.place.clone().field(field, field_ty))
index 684ea4c78978cc2b9a79f5a45c448bf4508d8318..dfdd7f0ae58e5e0b810cdfc90ae1244c893d6b44 100644 (file)
@@ -12,4 +12,5 @@ crate-type = ["dylib"]
 bitflags = "1.0"
 log = "0.4"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
+rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
index 15f61a033447fffacc782b2b4bc011f71a1d65ce..88f22912fa6fc9d812fadc5d7f70a286faff2349 100644 (file)
@@ -16,6 +16,8 @@
 use std::{cmp, fmt};
 use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+
 pub mod call;
 
 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
@@ -825,11 +827,15 @@ pub fn is_uninhabited(&self) -> bool {
     }
 }
 
+newtype_index! {
+    pub struct VariantIdx { .. }
+}
+
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub enum Variants {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single {
-        index: usize
+        index: VariantIdx,
     },
 
     /// General-case enums: for each case there is a struct, and they all have
@@ -837,7 +843,7 @@ pub enum Variants {
     /// at a non-0 offset, after where the tag would go.
     Tagged {
         tag: Scalar,
-        variants: Vec<LayoutDetails>,
+        variants: IndexVec<VariantIdx, LayoutDetails>,
     },
 
     /// Multiple cases distinguished by a niche (values invalid for a type):
@@ -849,11 +855,11 @@ pub enum Variants {
     /// `None` has a null pointer for the second tuple field, and
     /// `Some` is the identity function (with a non-null reference).
     NicheFilling {
-        dataful_variant: usize,
-        niche_variants: RangeInclusive<usize>,
+        dataful_variant: VariantIdx,
+        niche_variants: RangeInclusive<VariantIdx>,
         niche: Scalar,
         niche_start: u128,
-        variants: Vec<LayoutDetails>,
+        variants: IndexVec<VariantIdx, LayoutDetails>,
     }
 }
 
@@ -871,7 +877,7 @@ pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
         LayoutDetails {
-            variants: Variants::Single { index: 0 },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldPlacement::Union(0),
             abi: Abi::Scalar(scalar),
             size,
@@ -908,12 +914,16 @@ pub trait LayoutOf {
 }
 
 pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
-    fn for_variant(this: TyLayout<'a, Self>, cx: &C, variant_index: usize) -> TyLayout<'a, Self>;
+    fn for_variant(
+        this: TyLayout<'a, Self>,
+        cx: &C,
+        variant_index: VariantIdx,
+    ) -> TyLayout<'a, Self>;
     fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout;
 }
 
 impl<'a, Ty> TyLayout<'a, Ty> {
-    pub fn for_variant<C>(self, cx: &C, variant_index: usize) -> Self
+    pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
     where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
         Ty::for_variant(self, cx, variant_index)
     }
index e60c9922d467a5193a43ab78977fb40d41cddf57..813b39de064131d6ff16e7ad1db65d4eb1c715b7 100644 (file)
@@ -23,7 +23,9 @@
 
 #![feature(box_syntax)]
 #![feature(nll)]
+#![feature(rustc_attrs)]
 #![feature(slice_patterns)]
+#![feature(step_trait)]
 
 #[macro_use]
 extern crate bitflags;
@@ -36,5 +38,8 @@
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
 
+#[macro_use]
+extern crate rustc_data_structures;
+
 pub mod abi;
 pub mod spec;
index 16f0f11757a1278661d0e67be407d28fd1eed9ca..f057cbb50334eb07fbc804f4b05cbea288b0fc00 100644 (file)
@@ -14,6 +14,7 @@ graphviz = { path = "../libgraphviz" }
 log = { version = "0.4" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 chalk-engine = { version = "0.8.0", default-features=false }
diff --git a/src/librustc_traits/chalk_context.rs b/src/librustc_traits/chalk_context.rs
deleted file mode 100644 (file)
index bf25205..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use chalk_engine::fallible::Fallible as ChalkEngineFallible;
-use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
-use rustc::infer::canonical::{
-    Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
-};
-use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc::traits::{
-    WellFormed,
-    FromEnv,
-    DomainGoal,
-    ExClauseFold,
-    ExClauseLift,
-    Goal,
-    GoalKind,
-    Clause,
-    ProgramClauseCategory,
-    QuantifierKind,
-    Environment,
-    InEnvironment,
-};
-use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use rustc::ty::subst::Kind;
-use rustc::ty::{self, TyCtxt};
-use rustc::hir::def_id::DefId;
-
-use std::fmt::{self, Debug};
-use std::marker::PhantomData;
-
-use syntax_pos::DUMMY_SP;
-
-#[derive(Copy, Clone, Debug)]
-crate struct ChalkArenas<'gcx> {
-    _phantom: PhantomData<&'gcx ()>,
-}
-
-#[derive(Copy, Clone)]
-crate struct ChalkContext<'cx, 'gcx: 'cx> {
-    _arenas: ChalkArenas<'gcx>,
-    _tcx: TyCtxt<'cx, 'gcx, 'gcx>,
-}
-
-#[derive(Copy, Clone)]
-crate struct ChalkInferenceContext<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
-    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-}
-
-#[derive(Copy, Clone, Debug)]
-crate struct UniverseMap;
-
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-crate struct ConstrainedSubst<'tcx> {
-    subst: CanonicalVarValues<'tcx>,
-    constraints: Vec<QueryRegionConstraint<'tcx>>,
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ConstrainedSubst<'tcx> {
-        subst, constraints
-    }
-}
-
-impl context::Context for ChalkArenas<'tcx> {
-    type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
-
-    type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
-
-    // u-canonicalization not yet implemented
-    type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
-
-    type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
-
-    // u-canonicalization not yet implemented
-    type UniverseMap = UniverseMap;
-
-    type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>;
-
-    type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
-
-    type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>;
-
-    type RegionConstraint = QueryRegionConstraint<'tcx>;
-
-    type Substitution = CanonicalVarValues<'tcx>;
-
-    type Environment = Environment<'tcx>;
-
-    type Goal = Goal<'tcx>;
-
-    type DomainGoal = DomainGoal<'tcx>;
-
-    type BindersGoal = ty::Binder<Goal<'tcx>>;
-
-    type Parameter = Kind<'tcx>;
-
-    type ProgramClause = Clause<'tcx>;
-
-    type ProgramClauses = Vec<Clause<'tcx>>;
-
-    type UnificationResult = InferOk<'tcx, ()>;
-
-    fn goal_in_environment(
-        env: &Environment<'tcx>,
-        goal: Goal<'tcx>,
-    ) -> InEnvironment<'tcx, Goal<'tcx>> {
-        env.with(goal)
-    }
-}
-
-impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
-    fn make_solution(
-        &self,
-        _root_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        _simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
-    ) -> Option<Canonical<'gcx, QueryResponse<'gcx, ()>>> {
-        unimplemented!()
-    }
-}
-
-impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
-    /// True if this is a coinductive goal -- e.g., proving an auto trait.
-    fn is_coinductive(
-        &self,
-        _goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
-    ) -> bool {
-        unimplemented!()
-    }
-
-    /// Create an inference table for processing a new goal and instantiate that goal
-    /// in that context, returning "all the pieces".
-    ///
-    /// More specifically: given a u-canonical goal `arg`, creates a
-    /// new inference table `T` and populates it with the universes
-    /// found in `arg`. Then, creates a substitution `S` that maps
-    /// each bound variable in `arg` to a fresh inference variable
-    /// from T. Returns:
-    ///
-    /// - the table `T`
-    /// - the substitution `S`
-    /// - the environment and goal found by substitution `S` into `arg`
-    fn instantiate_ucanonical_goal<R>(
-        &self,
-        _arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        _op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
-    ) -> R {
-        unimplemented!()
-    }
-
-    fn instantiate_ex_clause<R>(
-        &self,
-        _num_universes: usize,
-        _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
-        _op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
-    ) -> R {
-        unimplemented!()
-    }
-
-    /// True if this solution has no region constraints.
-    fn empty_constraints(ccs: &Canonical<'gcx, ConstrainedSubst<'gcx>>) -> bool {
-        ccs.value.constraints.is_empty()
-    }
-
-    fn inference_normalized_subst_from_ex_clause(
-        canon_ex_clause: &'a Canonical<'gcx, ChalkExClause<'gcx>>,
-    ) -> &'a CanonicalVarValues<'gcx> {
-        &canon_ex_clause.value.subst
-    }
-
-    fn inference_normalized_subst_from_subst(
-        canon_subst: &'a Canonical<'gcx, ConstrainedSubst<'gcx>>,
-    ) -> &'a CanonicalVarValues<'gcx> {
-        &canon_subst.value.subst
-    }
-
-    fn canonical(
-        u_canon: &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-    ) -> &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
-        u_canon
-    }
-
-    fn is_trivial_substitution(
-        _u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
-    ) -> bool {
-        unimplemented!()
-    }
-
-    fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
-        0 // FIXME
-    }
-
-    /// Convert a goal G *from* the canonical universes *into* our
-    /// local universes. This will yield a goal G' that is the same
-    /// but for the universes of universally quantified names.
-    fn map_goal_from_canonical(
-        _map: &UniverseMap,
-        value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-    ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
-        *value // FIXME universe maps not implemented yet
-    }
-
-    fn map_subst_from_canonical(
-        _map: &UniverseMap,
-        value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
-    ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
-        value.clone() // FIXME universe maps not implemented yet
-    }
-}
-
-//impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
-//    for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
-//{
-//    fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
-//        self
-//    }
-//
-//    fn is_trivial_substitution(
-//        &self,
-//        canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-//    ) -> bool {
-//        let subst = &canonical_subst.value.subst;
-//        assert_eq!(self.canonical.variables.len(), subst.var_values.len());
-//        subst
-//            .var_values
-//            .iter_enumerated()
-//            .all(|(cvar, kind)| match kind.unpack() {
-//                Kind::Lifetime(r) => match r {
-//                    ty::ReCanonical(cvar1) => cvar == cvar1,
-//                    _ => false,
-//                },
-//                Kind::Type(ty) => match ty.sty {
-//                    ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
-//                    _ => false,
-//                },
-//            })
-//    }
-//
-//    fn num_universes(&self) -> usize {
-//        0 // FIXME
-//    }
-//}
-
-impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
-    fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
-        self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
-    }
-
-    fn cannot_prove(&self) -> Goal<'tcx> {
-        self.infcx.tcx.mk_goal(GoalKind::CannotProve)
-    }
-
-    fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
-        match *goal {
-            GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
-            GoalKind::And(left, right) => HhGoal::And(left, right),
-            GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
-            GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
-            GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
-            GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
-            GoalKind::CannotProve => HhGoal::CannotProve,
-        }
-    }
-
-    fn add_clauses(
-        &mut self,
-        env: &Environment<'tcx>,
-        clauses: Vec<Clause<'tcx>>,
-    ) -> Environment<'tcx> {
-        Environment {
-            clauses: self.infcx.tcx.mk_clauses(
-                env.clauses.iter().cloned().chain(clauses.into_iter())
-            )
-        }
-    }
-}
-
-impl context::ResolventOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
-    fn resolvent_clause(
-        &mut self,
-        _environment: &Environment<'tcx>,
-        _goal: &DomainGoal<'tcx>,
-        _subst: &CanonicalVarValues<'tcx>,
-        _clause: &Clause<'tcx>,
-    ) -> chalk_engine::fallible::Fallible<Canonical<'gcx, ChalkExClause<'gcx>>> {
-        panic!()
-    }
-
-    fn apply_answer_subst(
-        &mut self,
-        _ex_clause: ChalkExClause<'tcx>,
-        _selected_goal: &InEnvironment<'tcx, Goal<'tcx>>,
-        _answer_table_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        _canonical_answer_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
-    ) -> chalk_engine::fallible::Fallible<ChalkExClause<'tcx>> {
-        panic!()
-    }
-}
-
-impl context::TruncateOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
-    fn truncate_goal(
-        &mut self,
-        subgoal: &InEnvironment<'tcx, Goal<'tcx>>,
-    ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
-        Some(*subgoal) // FIXME we should truncate at some point!
-    }
-
-    fn truncate_answer(
-        &mut self,
-        subst: &CanonicalVarValues<'tcx>,
-    ) -> Option<CanonicalVarValues<'tcx>> {
-        Some(subst.clone()) // FIXME we should truncate at some point!
-    }
-}
-
-impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
-    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
-{
-    fn program_clauses(
-        &self,
-        environment: &Environment<'tcx>,
-        goal: &DomainGoal<'tcx>,
-    ) -> Vec<Clause<'tcx>> {
-        use rustc::traits::WhereClause::*;
-
-        fn assemble_clauses_from_impls<'tcx>(
-            tcx: ty::TyCtxt<'_, '_, 'tcx>,
-            trait_def_id: DefId,
-            clauses: &mut Vec<Clause<'tcx>>
-        ) {
-            tcx.for_each_impl(trait_def_id, |impl_def_id| {
-                clauses.extend(
-                    tcx.program_clauses_for(impl_def_id)
-                        .into_iter()
-                        .cloned()
-                );
-            });
-        }
-
-        fn assemble_clauses_from_assoc_ty_values<'tcx>(
-            tcx: ty::TyCtxt<'_, '_, 'tcx>,
-            trait_def_id: DefId,
-            clauses: &mut Vec<Clause<'tcx>>
-        ) {
-            tcx.for_each_impl(trait_def_id, |impl_def_id| {
-                for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
-                    clauses.extend(
-                        tcx.program_clauses_for(*def_id)
-                            .into_iter()
-                            .cloned()
-                    );
-                }
-            });
-        }
-
-        let mut clauses = match goal {
-            DomainGoal::Holds(Implemented(trait_predicate)) => {
-                // These come from:
-                // * implementations of the trait itself (rule `Implemented-From-Impl`)
-                // * the trait decl (rule `Implemented-From-Env`)
-
-                let mut clauses = vec![];
-                assemble_clauses_from_impls(
-                    self.infcx.tcx,
-                    trait_predicate.def_id(),
-                    &mut clauses
-                );
-
-                // FIXME: we need to add special rules for builtin impls:
-                // * `Copy` / `Clone`
-                // * `Sized`
-                // * `Unsize`
-                // * `Generator`
-                // * `FnOnce` / `FnMut` / `Fn`
-                // * trait objects
-                // * auto traits
-
-                // Rule `Implemented-From-Env` will be computed from the environment.
-                clauses
-            }
-
-            DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
-                // These come from:
-                // * the assoc type definition (rule `ProjectionEq-Placeholder`)
-                // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                let clauses = self.infcx.tcx.program_clauses_for(
-                    projection_predicate.projection_ty.item_def_id
-                ).into_iter()
-
-                    // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
-                    .filter(|clause| clause.category() == ProgramClauseCategory::Other)
-
-                    .cloned()
-                    .collect::<Vec<_>>();
-
-                // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
-                // from the environment.
-                clauses
-            }
-
-            DomainGoal::Holds(RegionOutlives(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::Holds(TypeOutlives(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
-                // These come from -- the trait decl (rule `WellFormed-TraitRef`).
-                self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
-                    .into_iter()
-
-                    // only select `WellFormed-TraitRef`
-                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-
-                    .cloned()
-                    .collect()
-            }
-
-            DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
-                // These come from:
-                // * the associated type definition if `ty` refers to an unnormalized
-                //   associated type (rule `WellFormed-AssocTy`)
-                // * custom rules for built-in types
-                // * the type definition otherwise (rule `WellFormed-Type`)
-                let clauses = match ty.sty {
-                    ty::Projection(data) => {
-                        self.infcx.tcx.program_clauses_for(data.item_def_id)
-                    }
-
-                    // These types are always WF (recall that we do not check
-                    // for parameters to be WF)
-                    ty::Bool |
-                    ty::Char |
-                    ty::Int(..) |
-                    ty::Uint(..) |
-                    ty::Float(..) |
-                    ty::Str |
-                    ty::RawPtr(..) |
-                    ty::FnPtr(..) |
-                    ty::Param(..) |
-                    ty::Never => {
-                        ty::List::empty()
-                    }
-
-                    // WF if inner type is `Sized`
-                    ty::Slice(..) |
-                    ty::Array(..) => {
-                        ty::List::empty()
-                    }
-
-                    ty::Tuple(..) => {
-                        ty::List::empty()
-                    }
-
-                    // WF if `sub_ty` outlives `region`
-                    ty::Ref(..) => {
-                        ty::List::empty()
-                    }
-
-                    ty::Dynamic(..) => {
-                        // FIXME: no rules yet for trait objects
-                        ty::List::empty()
-                    }
-
-                    ty::Adt(def, ..) => {
-                        self.infcx.tcx.program_clauses_for(def.did)
-                    }
-
-                    ty::Foreign(def_id) |
-                    ty::FnDef(def_id, ..) |
-                    ty::Closure(def_id, ..) |
-                    ty::Generator(def_id, ..) |
-                    ty::Opaque(def_id, ..) => {
-                        self.infcx.tcx.program_clauses_for(def_id)
-                    }
-
-                    ty::GeneratorWitness(..) |
-                    ty::UnnormalizedProjection(..) |
-                    ty::Infer(..) |
-                    ty::Bound(..) |
-                    ty::Error => {
-                        bug!("unexpected type {:?}", ty)
-                    }
-                };
-
-                clauses.into_iter()
-                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-                    .cloned()
-                    .collect()
-            }
-
-            DomainGoal::FromEnv(FromEnv::Trait(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-                // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
-                //   `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::FromEnv(FromEnv::Ty(..)) => {
-                // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
-                // comes from the environment).
-                vec![]
-            }
-
-            DomainGoal::Normalize(projection_predicate) => {
-                // These come from -- assoc ty values (rule `Normalize-From-Impl`).
-                let mut clauses = vec![];
-
-                assemble_clauses_from_assoc_ty_values(
-                    self.infcx.tcx,
-                    projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
-                    &mut clauses
-                );
-
-                clauses
-            }
-        };
-
-        let environment = self.infcx.tcx.lift_to_global(environment)
-            .expect("environment is not global");
-        clauses.extend(
-            self.infcx.tcx.program_clauses_for_env(environment)
-                .into_iter()
-                .cloned()
-        );
-        clauses
-    }
-
-    fn instantiate_binders_universally(
-        &mut self,
-        _arg: &ty::Binder<Goal<'tcx>>,
-    ) -> Goal<'tcx> {
-        panic!("FIXME -- universal instantiation needs sgrif's branch")
-    }
-
-    fn instantiate_binders_existentially(
-        &mut self,
-        arg: &ty::Binder<Goal<'tcx>>,
-    ) -> Goal<'tcx> {
-        let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var(
-            DUMMY_SP,
-            LateBoundRegionConversionTime::HigherRankedType,
-            arg,
-        );
-        value
-    }
-
-    fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
-        let string = format!("{:?}", self.infcx.resolve_type_vars_if_possible(value));
-        Box::new(string)
-    }
-
-    fn canonicalize_goal(
-        &mut self,
-        value: &InEnvironment<'tcx, Goal<'tcx>>,
-    ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
-        let mut _orig_values = OriginalQueryValues::default();
-        self.infcx.canonicalize_query(value, &mut _orig_values)
-    }
-
-    fn canonicalize_ex_clause(
-        &mut self,
-        value: &ChalkExClause<'tcx>,
-    ) -> Canonical<'gcx, ChalkExClause<'gcx>> {
-        self.infcx.canonicalize_response(value)
-    }
-
-    fn canonicalize_constrained_subst(
-        &mut self,
-        subst: CanonicalVarValues<'tcx>,
-        constraints: Vec<QueryRegionConstraint<'tcx>>,
-    ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
-        self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints })
-    }
-
-    fn u_canonicalize_goal(
-        &mut self,
-        value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-    ) -> (
-        Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        UniverseMap,
-    ) {
-        (value.clone(), UniverseMap)
-    }
-
-    fn invert_goal(
-        &mut self,
-        _value: &InEnvironment<'tcx, Goal<'tcx>>,
-    ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
-        panic!("goal inversion not yet implemented")
-    }
-
-    fn unify_parameters(
-        &mut self,
-        _environment: &Environment<'tcx>,
-        _a: &Kind<'tcx>,
-        _b: &Kind<'tcx>,
-    ) -> ChalkEngineFallible<InferOk<'tcx, ()>> {
-        panic!()
-    }
-
-    fn sink_answer_subset(
-        &self,
-        value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
-    ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
-        value.clone()
-    }
-
-    fn lift_delayed_literal(
-        &self,
-        _value: DelayedLiteral<ChalkArenas<'tcx>>,
-    ) -> DelayedLiteral<ChalkArenas<'gcx>> {
-        panic!("lift")
-    }
-
-    fn into_ex_clause(&mut self, _result: InferOk<'tcx, ()>, _ex_clause: &mut ChalkExClause<'tcx>) {
-        panic!("TBD")
-    }
-}
-
-type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>;
-
-type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>;
-
-impl Debug for ChalkContext<'cx, 'gcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ChalkContext")
-    }
-}
-
-impl Debug for ChalkInferenceContext<'cx, 'gcx, 'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ChalkInferenceContext")
-    }
-}
-
-impl ExClauseLift<'gcx> for ChalkArenas<'a> {
-    type LiftedExClause = ChalkExClause<'gcx>;
-
-    fn lift_ex_clause_to_tcx(
-        _ex_clause: &ChalkExClause<'a>,
-        _tcx: TyCtxt<'_, '_, 'tcx>,
-    ) -> Option<Self::LiftedExClause> {
-        panic!()
-    }
-}
-
-impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
-    fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(
-        ex_clause: &ChalkExClause<'tcx>,
-        folder: &mut F,
-    ) -> ChalkExClause<'tcx> {
-        ExClause {
-            subst: ex_clause.subst.fold_with(folder),
-            delayed_literals: ex_clause.delayed_literals.fold_with(folder),
-            constraints: ex_clause.constraints.fold_with(folder),
-            subgoals: ex_clause.subgoals.fold_with(folder),
-        }
-    }
-
-    fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>(
-        ex_clause: &ExClause<Self>,
-        visitor: &mut V,
-    ) -> bool {
-        let ExClause {
-            subst,
-            delayed_literals,
-            constraints,
-            subgoals,
-        } = ex_clause;
-        subst.visit_with(visitor)
-            && delayed_literals.visit_with(visitor)
-            && constraints.visit_with(visitor)
-            && subgoals.visit_with(visitor)
-    }
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ConstrainedSubst<'a> {
-        type Lifted = ConstrainedSubst<'tcx>;
-
-        subst, constraints
-    }
-}
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
new file mode 100644 (file)
index 0000000..0fd9f60
--- /dev/null
@@ -0,0 +1,493 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod program_clauses;
+
+use chalk_engine::fallible::Fallible as ChalkEngineFallible;
+use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
+use rustc::infer::canonical::{
+    Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
+};
+use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use rustc::traits::{
+    DomainGoal,
+    ExClauseFold,
+    ExClauseLift,
+    Goal,
+    GoalKind,
+    Clause,
+    QuantifierKind,
+    Environment,
+    InEnvironment,
+};
+use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use rustc::ty::subst::Kind;
+use rustc::ty::{self, TyCtxt};
+
+use std::fmt::{self, Debug};
+use std::marker::PhantomData;
+
+use syntax_pos::DUMMY_SP;
+
+#[derive(Copy, Clone, Debug)]
+crate struct ChalkArenas<'gcx> {
+    _phantom: PhantomData<&'gcx ()>,
+}
+
+#[derive(Copy, Clone)]
+crate struct ChalkContext<'cx, 'gcx: 'cx> {
+    _arenas: ChalkArenas<'gcx>,
+    _tcx: TyCtxt<'cx, 'gcx, 'gcx>,
+}
+
+#[derive(Copy, Clone)]
+crate struct ChalkInferenceContext<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+}
+
+#[derive(Copy, Clone, Debug)]
+crate struct UniverseMap;
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+crate struct ConstrainedSubst<'tcx> {
+    subst: CanonicalVarValues<'tcx>,
+    constraints: Vec<QueryRegionConstraint<'tcx>>,
+}
+
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for ConstrainedSubst<'tcx> {
+        subst, constraints
+    }
+}
+
+impl context::Context for ChalkArenas<'tcx> {
+    type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
+
+    type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
+
+    // u-canonicalization not yet implemented
+    type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
+
+    type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
+
+    // u-canonicalization not yet implemented
+    type UniverseMap = UniverseMap;
+
+    type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>;
+
+    type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
+
+    type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>;
+
+    type RegionConstraint = QueryRegionConstraint<'tcx>;
+
+    type Substitution = CanonicalVarValues<'tcx>;
+
+    type Environment = Environment<'tcx>;
+
+    type Goal = Goal<'tcx>;
+
+    type DomainGoal = DomainGoal<'tcx>;
+
+    type BindersGoal = ty::Binder<Goal<'tcx>>;
+
+    type Parameter = Kind<'tcx>;
+
+    type ProgramClause = Clause<'tcx>;
+
+    type ProgramClauses = Vec<Clause<'tcx>>;
+
+    type UnificationResult = InferOk<'tcx, ()>;
+
+    fn goal_in_environment(
+        env: &Environment<'tcx>,
+        goal: Goal<'tcx>,
+    ) -> InEnvironment<'tcx, Goal<'tcx>> {
+        env.with(goal)
+    }
+}
+
+impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
+    fn make_solution(
+        &self,
+        _root_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        _simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
+    ) -> Option<Canonical<'gcx, QueryResponse<'gcx, ()>>> {
+        unimplemented!()
+    }
+}
+
+impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
+    /// True if this is a coinductive goal -- e.g., proving an auto trait.
+    fn is_coinductive(
+        &self,
+        _goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
+    ) -> bool {
+        unimplemented!()
+    }
+
+    /// Create an inference table for processing a new goal and instantiate that goal
+    /// in that context, returning "all the pieces".
+    ///
+    /// More specifically: given a u-canonical goal `arg`, creates a
+    /// new inference table `T` and populates it with the universes
+    /// found in `arg`. Then, creates a substitution `S` that maps
+    /// each bound variable in `arg` to a fresh inference variable
+    /// from T. Returns:
+    ///
+    /// - the table `T`
+    /// - the substitution `S`
+    /// - the environment and goal found by substitution `S` into `arg`
+    fn instantiate_ucanonical_goal<R>(
+        &self,
+        _arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        _op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
+    ) -> R {
+        unimplemented!()
+    }
+
+    fn instantiate_ex_clause<R>(
+        &self,
+        _num_universes: usize,
+        _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
+        _op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
+    ) -> R {
+        unimplemented!()
+    }
+
+    /// True if this solution has no region constraints.
+    fn empty_constraints(ccs: &Canonical<'gcx, ConstrainedSubst<'gcx>>) -> bool {
+        ccs.value.constraints.is_empty()
+    }
+
+    fn inference_normalized_subst_from_ex_clause(
+        canon_ex_clause: &'a Canonical<'gcx, ChalkExClause<'gcx>>,
+    ) -> &'a CanonicalVarValues<'gcx> {
+        &canon_ex_clause.value.subst
+    }
+
+    fn inference_normalized_subst_from_subst(
+        canon_subst: &'a Canonical<'gcx, ConstrainedSubst<'gcx>>,
+    ) -> &'a CanonicalVarValues<'gcx> {
+        &canon_subst.value.subst
+    }
+
+    fn canonical(
+        u_canon: &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+    ) -> &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
+        u_canon
+    }
+
+    fn is_trivial_substitution(
+        _u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+    ) -> bool {
+        unimplemented!()
+    }
+
+    fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
+        0 // FIXME
+    }
+
+    /// Convert a goal G *from* the canonical universes *into* our
+    /// local universes. This will yield a goal G' that is the same
+    /// but for the universes of universally quantified names.
+    fn map_goal_from_canonical(
+        _map: &UniverseMap,
+        value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+    ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
+        *value // FIXME universe maps not implemented yet
+    }
+
+    fn map_subst_from_canonical(
+        _map: &UniverseMap,
+        value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+    ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
+        value.clone() // FIXME universe maps not implemented yet
+    }
+}
+
+//impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
+//    for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
+//{
+//    fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
+//        self
+//    }
+//
+//    fn is_trivial_substitution(
+//        &self,
+//        canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
+//    ) -> bool {
+//        let subst = &canonical_subst.value.subst;
+//        assert_eq!(self.canonical.variables.len(), subst.var_values.len());
+//        subst
+//            .var_values
+//            .iter_enumerated()
+//            .all(|(cvar, kind)| match kind.unpack() {
+//                Kind::Lifetime(r) => match r {
+//                    ty::ReCanonical(cvar1) => cvar == cvar1,
+//                    _ => false,
+//                },
+//                Kind::Type(ty) => match ty.sty {
+//                    ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
+//                    _ => false,
+//                },
+//            })
+//    }
+//
+//    fn num_universes(&self) -> usize {
+//        0 // FIXME
+//    }
+//}
+
+impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+    fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> {
+        self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+    }
+
+    fn cannot_prove(&self) -> Goal<'tcx> {
+        self.infcx.tcx.mk_goal(GoalKind::CannotProve)
+    }
+
+    fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
+        match *goal {
+            GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
+            GoalKind::And(left, right) => HhGoal::And(left, right),
+            GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
+            GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
+            GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder),
+            GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder),
+            GoalKind::CannotProve => HhGoal::CannotProve,
+        }
+    }
+
+    fn add_clauses(
+        &mut self,
+        env: &Environment<'tcx>,
+        clauses: Vec<Clause<'tcx>>,
+    ) -> Environment<'tcx> {
+        Environment {
+            clauses: self.infcx.tcx.mk_clauses(
+                env.clauses.iter().cloned().chain(clauses.into_iter())
+            )
+        }
+    }
+}
+
+impl context::ResolventOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+    fn resolvent_clause(
+        &mut self,
+        _environment: &Environment<'tcx>,
+        _goal: &DomainGoal<'tcx>,
+        _subst: &CanonicalVarValues<'tcx>,
+        _clause: &Clause<'tcx>,
+    ) -> chalk_engine::fallible::Fallible<Canonical<'gcx, ChalkExClause<'gcx>>> {
+        panic!()
+    }
+
+    fn apply_answer_subst(
+        &mut self,
+        _ex_clause: ChalkExClause<'tcx>,
+        _selected_goal: &InEnvironment<'tcx, Goal<'tcx>>,
+        _answer_table_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        _canonical_answer_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+    ) -> chalk_engine::fallible::Fallible<ChalkExClause<'tcx>> {
+        panic!()
+    }
+}
+
+impl context::TruncateOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+    fn truncate_goal(
+        &mut self,
+        subgoal: &InEnvironment<'tcx, Goal<'tcx>>,
+    ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
+        Some(*subgoal) // FIXME we should truncate at some point!
+    }
+
+    fn truncate_answer(
+        &mut self,
+        subst: &CanonicalVarValues<'tcx>,
+    ) -> Option<CanonicalVarValues<'tcx>> {
+        Some(subst.clone()) // FIXME we should truncate at some point!
+    }
+}
+
+impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
+    for ChalkInferenceContext<'cx, 'gcx, 'tcx>
+{
+    fn program_clauses(
+        &self,
+        environment: &Environment<'tcx>,
+        goal: &DomainGoal<'tcx>,
+    ) -> Vec<Clause<'tcx>> {
+        self.program_clauses_impl(environment, goal)
+    }
+
+    fn instantiate_binders_universally(
+        &mut self,
+        _arg: &ty::Binder<Goal<'tcx>>,
+    ) -> Goal<'tcx> {
+        panic!("FIXME -- universal instantiation needs sgrif's branch")
+    }
+
+    fn instantiate_binders_existentially(
+        &mut self,
+        arg: &ty::Binder<Goal<'tcx>>,
+    ) -> Goal<'tcx> {
+        self.infcx.replace_bound_vars_with_fresh_vars(
+            DUMMY_SP,
+            LateBoundRegionConversionTime::HigherRankedType,
+            arg
+        ).0
+    }
+
+    fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
+        let string = format!("{:?}", self.infcx.resolve_type_vars_if_possible(value));
+        Box::new(string)
+    }
+
+    fn canonicalize_goal(
+        &mut self,
+        value: &InEnvironment<'tcx, Goal<'tcx>>,
+    ) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
+        let mut _orig_values = OriginalQueryValues::default();
+        self.infcx.canonicalize_query(value, &mut _orig_values)
+    }
+
+    fn canonicalize_ex_clause(
+        &mut self,
+        value: &ChalkExClause<'tcx>,
+    ) -> Canonical<'gcx, ChalkExClause<'gcx>> {
+        self.infcx.canonicalize_response(value)
+    }
+
+    fn canonicalize_constrained_subst(
+        &mut self,
+        subst: CanonicalVarValues<'tcx>,
+        constraints: Vec<QueryRegionConstraint<'tcx>>,
+    ) -> Canonical<'gcx, ConstrainedSubst<'gcx>> {
+        self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints })
+    }
+
+    fn u_canonicalize_goal(
+        &mut self,
+        value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+    ) -> (
+        Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        UniverseMap,
+    ) {
+        (value.clone(), UniverseMap)
+    }
+
+    fn invert_goal(
+        &mut self,
+        _value: &InEnvironment<'tcx, Goal<'tcx>>,
+    ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
+        panic!("goal inversion not yet implemented")
+    }
+
+    fn unify_parameters(
+        &mut self,
+        _environment: &Environment<'tcx>,
+        _a: &Kind<'tcx>,
+        _b: &Kind<'tcx>,
+    ) -> ChalkEngineFallible<InferOk<'tcx, ()>> {
+        panic!()
+    }
+
+    fn sink_answer_subset(
+        &self,
+        value: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+    ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> {
+        value.clone()
+    }
+
+    fn lift_delayed_literal(
+        &self,
+        _value: DelayedLiteral<ChalkArenas<'tcx>>,
+    ) -> DelayedLiteral<ChalkArenas<'gcx>> {
+        panic!("lift")
+    }
+
+    fn into_ex_clause(&mut self, _result: InferOk<'tcx, ()>, _ex_clause: &mut ChalkExClause<'tcx>) {
+        panic!("TBD")
+    }
+}
+
+type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>;
+
+type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>;
+
+impl Debug for ChalkContext<'cx, 'gcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ChalkContext")
+    }
+}
+
+impl Debug for ChalkInferenceContext<'cx, 'gcx, 'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "ChalkInferenceContext")
+    }
+}
+
+impl ExClauseLift<'gcx> for ChalkArenas<'a> {
+    type LiftedExClause = ChalkExClause<'gcx>;
+
+    fn lift_ex_clause_to_tcx(
+        _ex_clause: &ChalkExClause<'a>,
+        _tcx: TyCtxt<'_, '_, 'tcx>,
+    ) -> Option<Self::LiftedExClause> {
+        panic!()
+    }
+}
+
+impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
+    fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(
+        ex_clause: &ChalkExClause<'tcx>,
+        folder: &mut F,
+    ) -> ChalkExClause<'tcx> {
+        ExClause {
+            subst: ex_clause.subst.fold_with(folder),
+            delayed_literals: ex_clause.delayed_literals.fold_with(folder),
+            constraints: ex_clause.constraints.fold_with(folder),
+            subgoals: ex_clause.subgoals.fold_with(folder),
+        }
+    }
+
+    fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>(
+        ex_clause: &ExClause<Self>,
+        visitor: &mut V,
+    ) -> bool {
+        let ExClause {
+            subst,
+            delayed_literals,
+            constraints,
+            subgoals,
+        } = ex_clause;
+        subst.visit_with(visitor)
+            && delayed_literals.visit_with(visitor)
+            && constraints.visit_with(visitor)
+            && subgoals.visit_with(visitor)
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for ConstrainedSubst<'a> {
+        type Lifted = ConstrainedSubst<'tcx>;
+
+        subst, constraints
+    }
+}
diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs
new file mode 100644 (file)
index 0000000..31f97b7
--- /dev/null
@@ -0,0 +1,476 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::traits::{
+    WellFormed,
+    FromEnv,
+    DomainGoal,
+    GoalKind,
+    Clause,
+    Clauses,
+    ProgramClause,
+    ProgramClauseCategory,
+    Environment,
+};
+use rustc::ty;
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc_target::spec::abi;
+use super::ChalkInferenceContext;
+use crate::lowering::Lower;
+use std::iter;
+
+fn assemble_clauses_from_impls<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    trait_def_id: DefId,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    tcx.for_each_impl(trait_def_id, |impl_def_id| {
+        clauses.extend(
+            tcx.program_clauses_for(impl_def_id)
+                .into_iter()
+                .cloned()
+        );
+    });
+}
+
+fn assemble_clauses_from_assoc_ty_values<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    trait_def_id: DefId,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    tcx.for_each_impl(trait_def_id, |impl_def_id| {
+        for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
+            clauses.extend(
+                tcx.program_clauses_for(*def_id)
+                    .into_iter()
+                    .cloned()
+            );
+        }
+    });
+}
+
+fn program_clauses_for_raw_ptr<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+    let ty = ty::Bound(
+        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+    );
+    let ty = tcx.mk_ty(ty);
+
+    let ptr_ty = tcx.mk_ptr(ty::TypeAndMut {
+        ty,
+        mutbl: hir::Mutability::MutImmutable,
+    });
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
+        hypotheses: ty::List::empty(),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<T> { WellFormed(*const T). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_fn_ptr<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    arity_and_output: usize,
+    variadic: bool,
+    unsafety: hir::Unsafety,
+    abi: abi::Abi
+) -> Clauses<'tcx> {
+    let inputs_and_output = tcx.mk_type_list(
+        (0..arity_and_output).into_iter()
+            // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
+            .map(|i| ty::BoundTy::new(ty::DebruijnIndex::from(1usize), ty::BoundVar::from(i)))
+            .map(|t| tcx.mk_ty(ty::Bound(t)))
+    );
+
+    let fn_sig = ty::Binder::bind(ty::FnSig {
+        inputs_and_output,
+        variadic,
+        unsafety,
+        abi,
+    });
+    let fn_ptr = tcx.mk_fn_ptr(fn_sig);
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
+        hypotheses: ty::List::empty(),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
+    // where `n + 1` == `arity_and_output`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+    let ty = ty::Bound(
+        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+    );
+    let ty = tcx.mk_ty(ty);
+
+    let slice_ty = tcx.mk_slice(ty);
+
+    let sized_trait = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => return ty::List::empty(),
+    };
+    let sized_implemented = ty::TraitRef {
+        def_id: sized_trait,
+        substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+    };
+    let sized_implemented: DomainGoal = ty::TraitPredicate {
+        trait_ref: sized_implemented
+    }.lower();
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
+        hypotheses: tcx.mk_goals(
+            iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_array<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    length: &'tcx ty::Const<'tcx>
+) -> Clauses<'tcx> {
+    let ty = ty::Bound(
+        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+    );
+    let ty = tcx.mk_ty(ty);
+
+    let array_ty = tcx.mk_ty(ty::Array(ty, length));
+
+    let sized_trait = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => return ty::List::empty(),
+    };
+    let sized_implemented = ty::TraitRef {
+        def_id: sized_trait,
+        substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+    };
+    let sized_implemented: DomainGoal = ty::TraitPredicate {
+        trait_ref: sized_implemented
+    }.lower();
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
+        hypotheses: tcx.mk_goals(
+            iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_tuple<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    arity: usize
+) -> Clauses<'tcx> {
+    let type_list = tcx.mk_type_list(
+        (0..arity).into_iter()
+            .map(|i| ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from(i)))
+            .map(|t| tcx.mk_ty(ty::Bound(t)))
+    );
+
+    let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
+
+    let sized_trait = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => return ty::List::empty(),
+    };
+    let sized_implemented = type_list[0..arity - 1].iter()
+        .map(|ty| ty::TraitRef {
+            def_id: sized_trait,
+            substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
+        })
+        .map(|trait_ref| ty::TraitPredicate { trait_ref })
+        .map(|predicate| predicate.lower());
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
+        hypotheses: tcx.mk_goals(
+            sized_implemented.map(|domain_goal| {
+                tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+            })
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // ```
+    // forall<T1, ..., Tn-1, Tn> {
+    //     WellFormed((T1, ..., Tn)) :-
+    //         Implemented(T1: Sized),
+    //         ...
+    //         Implemented(Tn-1: Sized).
+    // }
+    // ```
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+fn program_clauses_for_ref<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+    let region = tcx.mk_region(
+        ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
+    );
+    let ty = tcx.mk_ty(
+        ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
+    );
+
+    let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
+        ty,
+        mutbl: hir::Mutability::MutImmutable,
+    });
+
+    let outlives: DomainGoal = ty::OutlivesPredicate(ty, region).lower();
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
+        hypotheses: tcx.mk_goals(
+            iter::once(tcx.mk_goal(outlives.into_goal()))
+        ),
+        category: ProgramClauseCategory::ImpliedBound,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
+    pub(super) fn program_clauses_impl(
+        &self,
+        environment: &Environment<'tcx>,
+        goal: &DomainGoal<'tcx>,
+    ) -> Vec<Clause<'tcx>> {
+        use rustc::traits::WhereClause::*;
+
+        let mut clauses = match goal {
+            DomainGoal::Holds(Implemented(trait_predicate)) => {
+                // These come from:
+                // * implementations of the trait itself (rule `Implemented-From-Impl`)
+                // * the trait decl (rule `Implemented-From-Env`)
+
+                let mut clauses = vec![];
+                assemble_clauses_from_impls(
+                    self.infcx.tcx,
+                    trait_predicate.def_id(),
+                    &mut clauses
+                );
+
+                // FIXME: we need to add special rules for builtin impls:
+                // * `Copy` / `Clone`
+                // * `Sized`
+                // * `Unsize`
+                // * `Generator`
+                // * `FnOnce` / `FnMut` / `Fn`
+                // * trait objects
+                // * auto traits
+
+                // Rule `Implemented-From-Env` will be computed from the environment.
+                clauses
+            }
+
+            DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
+                // These come from:
+                // * the assoc type definition (rule `ProjectionEq-Placeholder`)
+                // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
+                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+                let clauses = self.infcx.tcx.program_clauses_for(
+                    projection_predicate.projection_ty.item_def_id
+                ).into_iter()
+
+                    // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
+                    .filter(|clause| clause.category() == ProgramClauseCategory::Other)
+
+                    .cloned()
+                    .collect::<Vec<_>>();
+
+                // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
+                // from the environment.
+                clauses
+            }
+
+            DomainGoal::Holds(RegionOutlives(..)) => {
+                // These come from:
+                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+                // All of these rules are computed in the environment.
+                vec![]
+            }
+
+            DomainGoal::Holds(TypeOutlives(..)) => {
+                // These come from:
+                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+                // All of these rules are computed in the environment.
+                vec![]
+            }
+
+            DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
+                // These come from -- the trait decl (rule `WellFormed-TraitRef`).
+                self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
+                    .into_iter()
+
+                    // only select `WellFormed-TraitRef`
+                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+
+                    .cloned()
+                    .collect()
+            }
+
+            DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
+                // These come from:
+                // * the associated type definition if `ty` refers to an unnormalized
+                //   associated type (rule `WellFormed-AssocTy`)
+                // * custom rules for built-in types
+                // * the type definition otherwise (rule `WellFormed-Type`)
+                let clauses = match ty.sty {
+                    ty::Projection(data) => {
+                        self.infcx.tcx.program_clauses_for(data.item_def_id)
+                    }
+
+                    // These types are always WF and non-parametric.
+                    ty::Bool |
+                    ty::Char |
+                    ty::Int(..) |
+                    ty::Uint(..) |
+                    ty::Float(..) |
+                    ty::Str |
+                    ty::Never => {
+                        let wf_clause = ProgramClause {
+                            goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
+                            hypotheses: ty::List::empty(),
+                            category: ProgramClauseCategory::WellFormed,
+                        };
+                        let wf_clause = Clause::ForAll(ty::Binder::dummy(wf_clause));
+
+                        self.infcx.tcx.mk_clauses(iter::once(wf_clause))
+                    }
+
+                    // Always WF (recall that we do not check for parameters to be WF).
+                    ty::RawPtr(..) => program_clauses_for_raw_ptr(self.infcx.tcx),
+
+                    // Always WF (recall that we do not check for parameters to be WF).
+                    ty::FnPtr(fn_ptr) => {
+                        let fn_ptr = fn_ptr.skip_binder();
+                        program_clauses_for_fn_ptr(
+                            self.infcx.tcx,
+                            fn_ptr.inputs_and_output.len(),
+                            fn_ptr.variadic,
+                            fn_ptr.unsafety,
+                            fn_ptr.abi
+                        )
+                    }
+
+                    // WF if inner type is `Sized`.
+                    ty::Slice(..) => program_clauses_for_slice(self.infcx.tcx),
+
+                    // WF if inner type is `Sized`.
+                    ty::Array(_, length) => program_clauses_for_array(self.infcx.tcx, length),
+
+                    // WF if all types but the last one are `Sized`.
+                    ty::Tuple(types) => program_clauses_for_tuple(
+                        self.infcx.tcx,
+                        types.len()
+                    ),
+
+                    // WF if `sub_ty` outlives `region`.
+                    ty::Ref(..) => program_clauses_for_ref(self.infcx.tcx),
+
+                    ty::Dynamic(..) => {
+                        // FIXME: no rules yet for trait objects
+                        ty::List::empty()
+                    }
+
+                    ty::Adt(def, ..) => {
+                        self.infcx.tcx.program_clauses_for(def.did)
+                    }
+
+                    ty::Foreign(def_id) |
+                    ty::FnDef(def_id, ..) |
+                    ty::Closure(def_id, ..) |
+                    ty::Generator(def_id, ..) |
+                    ty::Opaque(def_id, ..) => {
+                        self.infcx.tcx.program_clauses_for(def_id)
+                    }
+
+                    ty::GeneratorWitness(..) |
+                    ty::UnnormalizedProjection(..) |
+                    ty::Infer(..) |
+                    ty::Bound(..) |
+                    ty::Param(..) |
+                    ty::Error => {
+                        bug!("unexpected type {:?}", ty)
+                    }
+                };
+
+                clauses.into_iter()
+                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+                    .cloned()
+                    .collect()
+            }
+
+            DomainGoal::FromEnv(FromEnv::Trait(..)) => {
+                // These come from:
+                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+                // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
+                //   `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
+
+                // All of these rules are computed in the environment.
+                vec![]
+            }
+
+            DomainGoal::FromEnv(FromEnv::Ty(..)) => {
+                // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
+                // comes from the environment).
+                vec![]
+            }
+
+            DomainGoal::Normalize(projection_predicate) => {
+                // These come from -- assoc ty values (rule `Normalize-From-Impl`).
+                let mut clauses = vec![];
+
+                assemble_clauses_from_assoc_ty_values(
+                    self.infcx.tcx,
+                    projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
+                    &mut clauses
+                );
+
+                clauses
+            }
+        };
+
+        let environment = self.infcx.tcx.lift_to_global(environment)
+            .expect("environment is not global");
+        clauses.extend(
+            self.infcx.tcx.program_clauses_for_env(environment)
+                .into_iter()
+                .cloned()
+        );
+        clauses
+    }
+}
index 733804fb9b052c50a908969c3042c76498ae5aa7..4a3806d6cb68074a23998da7cb9bf26025a08a4f 100644 (file)
@@ -23,6 +23,7 @@
 #[macro_use]
 extern crate rustc;
 extern crate rustc_data_structures;
+extern crate rustc_target;
 extern crate syntax;
 extern crate syntax_pos;
 extern crate smallvec;
index 052ca37b313717fa7123762068df759a37a3558c..54f0c6e8da78a5e984bc8e986bc48ae6dd71f960 100644 (file)
@@ -20,6 +20,8 @@
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::hir::def_id::DefId;
 use rustc_data_structures::fx::FxHashSet;
+use super::Lower;
+use std::iter;
 
 struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -45,9 +47,32 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
                 );
             }
 
-            // forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
-            ty::Ref(_region, _sub_ty, ..) => {
-                // FIXME: we'd need bound tys in order to properly write the above rule
+            // forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` }
+            ty::Ref(..) => {
+                use rustc::hir;
+
+                let region = self.tcx.mk_region(
+                    ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
+                );
+                let ty = self.tcx.mk_ty(
+                    ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
+                );
+
+                let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
+                    ty,
+                    mutbl: hir::Mutability::MutImmutable,
+                });
+                let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty));
+
+                let clause = ProgramClause {
+                    goal: ty::OutlivesPredicate(ty, region).lower(),
+                    hypotheses: self.tcx.mk_goals(
+                        iter::once(self.tcx.mk_goal(from_env.into_goal()))
+                    ),
+                    category: ProgramClauseCategory::ImpliedBound,
+                };
+                let clause = Clause::ForAll(ty::Binder::bind(clause));
+                self.round.insert(clause);
             }
 
             ty::Dynamic(..) => {
@@ -88,12 +113,12 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
             ty::FnPtr(..) |
             ty::Tuple(..) |
             ty::Never |
-            ty::Param(..) => (),
+            ty::Infer(..) |
+            ty::Bound(..) => (),
 
             ty::GeneratorWitness(..) |
             ty::UnnormalizedProjection(..) |
-            ty::Infer(..) |
-            ty::Bound(..) |
+            ty::Param(..) |
             ty::Error => {
                 bug!("unexpected type {:?}", ty);
             }
@@ -173,21 +198,28 @@ fn visit_clause(&mut self, clause: Clause<'tcx>) {
     );
 }
 
-crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Environment<'tcx> {
+crate fn environment<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId
+) -> ty::Binder<Environment<'tcx>> {
     use super::{Lower, IntoFromEnvGoal};
     use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
+    use rustc::ty::subst::{Subst, Substs};
 
     // 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);
     }
 
+    let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
     // Compute the bounds on `Self` and the type parameters.
-    let ty::InstantiatedPredicates { predicates } =
-        tcx.predicates_of(def_id).instantiate_identity(tcx);
+    let ty::InstantiatedPredicates { predicates } = tcx.predicates_of(def_id)
+        .instantiate_identity(tcx);
 
     let clauses = predicates.into_iter()
         .map(|predicate| predicate.lower())
+        .map(|predicate| predicate.subst(tcx, bound_vars))
         .map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
         .map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
 
@@ -228,33 +260,43 @@ fn visit_clause(&mut self, clause: Clause<'tcx>) {
 
     let mut input_tys = FxHashSet::default();
 
-    // In an impl, we assume that the receiver type and all its constituents
+    // In an impl, we assume that the header trait ref and all its constituents
     // are well-formed.
     if is_impl {
-        let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
-        input_tys.extend(trait_ref.self_ty().walk());
+        let trait_ref = tcx.impl_trait_ref(def_id)
+            .expect("not an impl")
+            .subst(tcx, bound_vars);
+
+        input_tys.extend(
+            trait_ref.substs.types().flat_map(|ty| ty.walk())
+        );
     }
 
     // In an fn, we assume that the arguments and all their constituents are
     // well-formed.
     if is_fn {
-        let fn_sig = tcx.fn_sig(def_id);
+        // `skip_binder` because we move region parameters to the root binder,
+        // restored in the return type of this query
+        let fn_sig = tcx.fn_sig(def_id).skip_binder().subst(tcx, bound_vars);
+
         input_tys.extend(
-            // FIXME: `skip_binder` seems ok for now? In a real setting,
-            // the late bound regions would next be instantiated with things
-            // in the inference table.
-            fn_sig.skip_binder().inputs().iter().flat_map(|ty| ty.walk())
+            fn_sig.inputs().iter().flat_map(|ty| ty.walk())
         );
     }
 
     let clauses = clauses.chain(
         input_tys.into_iter()
+            // Filter out type parameters
+            .filter(|ty| match ty.sty {
+                ty::Bound(..) => false,
+                _ => true,
+            })
             .map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
             .map(|domain_goal| domain_goal.into_program_clause())
             .map(Clause::Implies)
     );
 
-    Environment {
+    ty::Binder::bind(Environment {
         clauses: tcx.mk_clauses(clauses),
-    }
+    })
 }
index 46581397aee2db08f6fe2d21d8b93020f291ffad..471c0e7abbca6711a8144ca0531debd6b4d849cf 100644 (file)
@@ -28,6 +28,7 @@
 };
 use rustc::ty::query::Providers;
 use rustc::ty::{self, List, TyCtxt};
+use rustc::ty::subst::{Subst, Substs};
 use syntax::ast;
 
 use std::iter;
@@ -112,13 +113,14 @@ fn lower(&self) -> PolyDomainGoal<'tcx> {
             Predicate::RegionOutlives(predicate) => predicate.lower(),
             Predicate::TypeOutlives(predicate) => predicate.lower(),
             Predicate::Projection(predicate) => predicate.lower(),
-            Predicate::WellFormed(ty) => {
-                ty::Binder::dummy(DomainGoal::WellFormed(WellFormed::Ty(*ty)))
+
+            Predicate::WellFormed(..) |
+            Predicate::ObjectSafe(..) |
+            Predicate::ClosureKind(..) |
+            Predicate::Subtype(..) |
+            Predicate::ConstEvaluatable(..) => {
+                bug!("unexpected predicate {}", self)
             }
-            Predicate::ObjectSafe(..)
-            | Predicate::ClosureKind(..)
-            | Predicate::Subtype(..)
-            | Predicate::ConstEvaluatable(..) => unimplemented!(),
         }
     }
 }
@@ -189,9 +191,14 @@ fn program_clauses_for_trait<'a, 'tcx>(
     // }
     // ```
 
+    let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
     // `Self: Trait<P1..Pn>`
     let trait_pred = ty::TraitPredicate {
-        trait_ref: ty::TraitRef::identity(tcx, def_id),
+        trait_ref: ty::TraitRef {
+            def_id,
+            substs: bound_vars,
+        },
     };
 
     // `Implemented(Self: Trait<P1..Pn>)`
@@ -208,11 +215,12 @@ fn program_clauses_for_trait<'a, 'tcx>(
         category: ProgramClauseCategory::ImpliedBound,
     };
 
-    let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
+    let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env));
 
     let where_clauses = &tcx.predicates_defined_on(def_id).predicates
         .into_iter()
         .map(|(wc, _)| wc.lower())
+        .map(|wc| wc.subst(tcx, bound_vars))
         .collect::<Vec<_>>();
 
     // Rule Implied-Bound-From-Trait
@@ -230,11 +238,22 @@ fn program_clauses_for_trait<'a, 'tcx>(
         .cloned()
 
         // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
-        .map(|wc| wc.map_bound(|goal| ProgramClause {
-            goal: goal.into_from_env_goal(),
-            hypotheses,
-            category: ProgramClauseCategory::ImpliedBound,
-        }))
+        .map(|wc| {
+            // we move binders to the left
+            wc.map_bound(|goal| ProgramClause {
+                goal: goal.into_from_env_goal(),
+
+                // FIXME: As where clauses can only bind lifetimes for now,
+                // and that named bound regions have a def-id, it is safe
+                // to just inject `hypotheses` (which contains named vars bound at index `0`)
+                // into this binding level. This may change if we ever allow where clauses
+                // to bind types (e.g. for GATs things), because bound types only use a `BoundVar`
+                // index (no def-id).
+                hypotheses,
+
+                category: ProgramClauseCategory::ImpliedBound,
+            })
+        })
         .map(Clause::ForAll);
 
     // Rule WellFormed-TraitRef
@@ -246,28 +265,27 @@ fn program_clauses_for_trait<'a, 'tcx>(
     // }
     // ```
 
-    // `Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
-    let wf_conditions = iter::once(ty::Binder::dummy(trait_pred.lower()))
-        .chain(
-            where_clauses
-                .into_iter()
-                .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()))
-        );
+    // `WellFormed(WC)`
+    let wf_conditions = where_clauses
+        .into_iter()
+        .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()));
 
     // `WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
     let wf_clause = ProgramClause {
         goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)),
         hypotheses: tcx.mk_goals(
-            wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
+            iter::once(tcx.mk_goal(GoalKind::DomainGoal(impl_trait))).chain(
+                wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx)))
+            )
         ),
         category: ProgramClauseCategory::WellFormed,
     };
-    let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause)));
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
 
     tcx.mk_clauses(
-        clauses
+        iter::once(implemented_from_env)
             .chain(implied_bound_clauses)
-            .chain(wf_clause)
+            .chain(iter::once(wf_clause))
     )
 }
 
@@ -286,7 +304,11 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
     // }
     // ```
 
-    let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+    let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
+    let trait_ref = tcx.impl_trait_ref(def_id)
+        .expect("not an impl")
+        .subst(tcx, bound_vars);
 
     // `Implemented(A0: Trait<A1..An>)`
     let trait_pred = ty::TraitPredicate { trait_ref }.lower();
@@ -294,7 +316,8 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
     // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates
         .into_iter()
-        .map(|(wc, _)| wc.lower());
+        .map(|(wc, _)| wc.lower())
+        .map(|wc| wc.subst(tcx, bound_vars));
 
     // `Implemented(A0: Trait<A1..An>) :- WC`
     let clause = ProgramClause {
@@ -305,7 +328,7 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
         ),
         category: ProgramClauseCategory::Other,
     };
-    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
+    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::bind(clause))))
 }
 
 pub fn program_clauses_for_type_def<'a, 'tcx>(
@@ -322,17 +345,20 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
     // }
     // ```
 
+    let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
+
     // `Ty<...>`
-    let ty = tcx.type_of(def_id);
+    let ty = tcx.type_of(def_id).subst(tcx, bound_vars);
 
     // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates
         .into_iter()
         .map(|(wc, _)| wc.lower())
+        .map(|wc| wc.subst(tcx, bound_vars))
         .collect::<Vec<_>>();
 
     // `WellFormed(Ty<...>) :- WC1, ..., WCm`
-    let well_formed = ProgramClause {
+    let well_formed_clause = ProgramClause {
         goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
         hypotheses: tcx.mk_goals(
             where_clauses
@@ -342,10 +368,9 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
         ),
         category: ProgramClauseCategory::WellFormed,
     };
+    let well_formed_clause = Clause::ForAll(ty::Binder::bind(well_formed_clause));
 
-    let well_formed_clause = iter::once(Clause::ForAll(ty::Binder::dummy(well_formed)));
-
-    // Rule FromEnv-Type
+    // Rule Implied-Bound-From-Type
     //
     // For each where clause `WC`:
     // ```
@@ -363,22 +388,30 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
         .into_iter()
 
         // `FromEnv(WC) :- FromEnv(Ty<...>)`
-        .map(|wc| wc.map_bound(|goal| ProgramClause {
-            goal: goal.into_from_env_goal(),
-            hypotheses,
-            category: ProgramClauseCategory::ImpliedBound,
-        }))
+        .map(|wc| {
+            // move the binders to the left
+            wc.map_bound(|goal| ProgramClause {
+                goal: goal.into_from_env_goal(),
+
+                // FIXME: we inject `hypotheses` into this binding level,
+                // which may be incorrect in the future: see the FIXME in
+                // `program_clauses_for_trait`
+                hypotheses,
+
+                category: ProgramClauseCategory::ImpliedBound,
+            })
+        })
 
         .map(Clause::ForAll);
 
-    tcx.mk_clauses(well_formed_clause.chain(from_env_clauses))
+    tcx.mk_clauses(iter::once(well_formed_clause).chain(from_env_clauses))
 }
 
 pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     item_id: DefId,
 ) -> Clauses<'tcx> {
-    // Rule ProjectionEq-Skolemize
+    // Rule ProjectionEq-Placeholder
     //
     // ```
     // trait Trait<P1..Pn> {
@@ -403,7 +436,12 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
         ty::AssociatedItemContainer::TraitContainer(trait_id) => trait_id,
         _ => bug!("not an trait container"),
     };
-    let trait_ref = ty::TraitRef::identity(tcx, trait_id);
+
+    let trait_bound_vars = Substs::bound_vars_for_item(tcx, trait_id);
+    let trait_ref = ty::TraitRef {
+        def_id: trait_id,
+        substs: trait_bound_vars,
+    };
 
     let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
     let placeholder_ty = tcx.mk_ty(ty::UnnormalizedProjection(projection_ty));
@@ -417,6 +455,7 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
         hypotheses: ty::List::empty(),
         category: ProgramClauseCategory::Other,
     };
+    let projection_eq_clause = Clause::ForAll(ty::Binder::bind(projection_eq_clause));
 
     // Rule WellFormed-AssocTy
     // ```
@@ -430,11 +469,13 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
     let hypothesis = tcx.mk_goal(
         DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
     );
+
     let wf_clause = ProgramClause {
         goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
         hypotheses: tcx.mk_goals(iter::once(hypothesis)),
         category: ProgramClauseCategory::WellFormed,
     };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
 
     // Rule Implied-Trait-From-AssocTy
     // ```
@@ -447,16 +488,17 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
     let hypothesis = tcx.mk_goal(
         DomainGoal::FromEnv(FromEnv::Ty(placeholder_ty)).into_goal()
     );
+
     let from_env_clause = ProgramClause {
         goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)),
         hypotheses: tcx.mk_goals(iter::once(hypothesis)),
         category: ProgramClauseCategory::ImpliedBound,
     };
+    let from_env_clause = Clause::ForAll(ty::Binder::bind(from_env_clause));
 
     let clauses = iter::once(projection_eq_clause)
         .chain(iter::once(wf_clause))
         .chain(iter::once(from_env_clause));
-    let clauses = clauses.map(|clause| Clause::ForAll(ty::Binder::dummy(clause)));
     tcx.mk_clauses(clauses)
 }
 
@@ -490,17 +532,18 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
         _ => bug!("not an impl container"),
     };
 
+    let impl_bound_vars = Substs::bound_vars_for_item(tcx, impl_id);
+
     // `A0 as Trait<A1..An>`
-    let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
+    let trait_ref = tcx.impl_trait_ref(impl_id)
+        .unwrap()
+        .subst(tcx, impl_bound_vars);
 
     // `T`
     let ty = tcx.type_of(item_id);
 
     // `Implemented(A0: Trait<A1..An>)`
-    let trait_implemented = ty::Binder::dummy(ty::TraitPredicate { trait_ref }.lower());
-
-    // `Implemented(A0: Trait<A1..An>)`
-    let hypotheses = vec![trait_implemented];
+    let trait_implemented: DomainGoal = ty::TraitPredicate { trait_ref }.lower();
 
     // `<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm>`
     let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident);
@@ -509,16 +552,16 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
     let normalize_goal = DomainGoal::Normalize(ty::ProjectionPredicate { projection_ty, ty });
 
     // `Normalize(... -> T) :- ...`
-    let clause = ProgramClause {
+    let normalize_clause = ProgramClause {
         goal: normalize_goal,
         hypotheses: tcx.mk_goals(
-            hypotheses
-                .into_iter()
-                .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
+            iter::once(tcx.mk_goal(GoalKind::DomainGoal(trait_implemented)))
         ),
         category: ProgramClauseCategory::Other,
     };
-    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
+    let normalize_clause = Clause::ForAll(ty::Binder::bind(normalize_clause));
+
+    tcx.mk_clauses(iter::once(normalize_clause))
 }
 
 pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -548,7 +591,7 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
 
             if attr.check_name("rustc_dump_env_program_clauses") {
                 let environment = self.tcx.environment(def_id);
-                clauses = Some(self.tcx.program_clauses_for_env(environment));
+                clauses = Some(self.tcx.program_clauses_for_env(*environment.skip_binder()));
             }
 
             if let Some(clauses) = clauses {
@@ -559,14 +602,7 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
 
                 let mut strings: Vec<_> = clauses
                     .iter()
-                    .map(|clause| {
-                        // Skip the top-level binder for a less verbose output
-                        let program_clause = match clause {
-                            Clause::Implies(program_clause) => program_clause,
-                            Clause::ForAll(program_clause) => program_clause.skip_binder(),
-                        };
-                        program_clause.to_string()
-                    })
+                    .map(|clause| clause.to_string())
                     .collect();
 
                 strings.sort();
index de4293aaaeac79ef676869c4f1da015c0c8b291c..411583b36b9e36aa280210bdb15a0516c1e9caa4 100644 (file)
@@ -110,10 +110,11 @@ fn try_overloaded_call_step(&self,
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id, substs).is_none() {
                     let closure_ty = self.closure_sig(def_id, substs);
-                    let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                                   infer::FnCall,
-                                                                   &closure_ty)
-                        .0;
+                    let fn_sig = self.replace_bound_vars_with_fresh_vars(
+                        call_expr.span,
+                        infer::FnCall,
+                        &closure_ty
+                    ).0;
                     let adjustments = autoderef.adjust_steps(Needs::None);
                     self.record_deferred_call_resolution(def_id, DeferredCallResolution {
                         call_expr,
@@ -284,7 +285,7 @@ fn confirm_builtin_call(&self,
         // previously appeared within a `Binder<>` and hence would not
         // have been normalized before.
         let fn_sig =
-            self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
+            self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig)
                 .0;
         let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
 
index 010561d1001e5ad61cc4cf0af5da187681e0a8a6..10ac2448d007b01c73d65dd33f2bcdce8dbac6fe 100644 (file)
@@ -564,7 +564,7 @@ fn check_supplied_sig_against_expectation(
             // `liberated_sig` is E'.
             {
                 // Instantiate (this part of..) S to S', i.e., with fresh variables.
-                let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
                     hir_ty.span,
                     LateBoundRegionConversionTime::FnCall,
                     &ty::Binder::bind(supplied_ty),
@@ -605,7 +605,7 @@ fn check_supplied_sig_against_expectation(
                 );
             }
 
-            let (supplied_output_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+            let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
                 decl.output.span(),
                 LateBoundRegionConversionTime::FnCall,
                 &supplied_sig.output(),
index 45c5457c9e14016a62a39ed72c7842313481e646..e30ebe07e54185a26a704dc0a289d6b7c838f376 100644 (file)
@@ -233,7 +233,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut selcx = traits::SelectionContext::new(&infcx);
 
         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
-        let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(
+        let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
             impl_m_span,
             infer::HigherRankedType,
             &ty::Binder::bind(impl_m_own_bounds.predicates)
@@ -262,10 +262,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Compute placeholder form of impl and trait method tys.
         let tcx = infcx.tcx;
 
-        let (impl_sig, _) =
-            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
-                                                            infer::HigherRankedType,
-                                                            &tcx.fn_sig(impl_m.def_id));
+        let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
+            impl_m_span,
+            infer::HigherRankedType,
+            &tcx.fn_sig(impl_m.def_id)
+        );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span,
                                               impl_m_node_id,
index 75f5bf74c6aef32e40019bf29f57f2f75ea754a7..5144f3e41d4a9ad4a7c8fc32955fcd21354510d9 100644 (file)
@@ -245,7 +245,7 @@ fn fresh_receiver_substs(&mut self,
                     let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty);
                     let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id);
                     let upcast_trait_ref =
-                        this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
+                        this.replace_bound_vars_with_fresh_vars(&upcast_poly_trait_ref);
                     debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
                            original_poly_trait_ref,
                            upcast_trait_ref,
@@ -268,7 +268,7 @@ fn fresh_receiver_substs(&mut self,
             probe::WhereClausePick(ref poly_trait_ref) => {
                 // Where clauses can have bound regions in them. We need to instantiate
                 // those to convert from a poly-trait-ref to a trait-ref.
-                self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs
+                self.replace_bound_vars_with_fresh_vars(&poly_trait_ref).substs
             }
         }
     }
@@ -398,7 +398,7 @@ fn instantiate_method_sig(&mut self,
         // NB: Instantiate late-bound regions first so that
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
-        let method_sig = self.replace_late_bound_regions_with_fresh_var(&sig);
+        let method_sig = self.replace_bound_vars_with_fresh_vars(&sig);
         debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
                method_sig);
 
@@ -633,11 +633,9 @@ fn upcast(&mut self,
         upcast_trait_refs.into_iter().next().unwrap()
     }
 
-    fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
+    fn replace_bound_vars_with_fresh_vars<T>(&self, value: &ty::Binder<T>) -> T
         where T: TypeFoldable<'tcx>
     {
-        self.fcx
-            .replace_late_bound_regions_with_fresh_var(self.span, infer::FnCall, value)
-            .0
+        self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value).0
     }
 }
index 637f3eaae9a6ac91e0f3e5874cd420354699f697..ac338ba667865204cf25deb0658583934cb2b835 100644 (file)
@@ -311,9 +311,11 @@ pub fn lookup_method_in_trait(&self,
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
         let fn_sig = tcx.fn_sig(def_id);
-        let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
-                                                                    infer::FnCall,
-                                                                    &fn_sig).0;
+        let fn_sig = self.replace_bound_vars_with_fresh_vars(
+            span,
+            infer::FnCall,
+            &fn_sig
+        ).0;
         let fn_sig = fn_sig.subst(self.tcx, substs);
         let fn_sig = match self.normalize_associated_types_in_as_infer_ok(span, &fn_sig) {
             InferOk { value, obligations: o } => {
index 305efd0d75af6ed89b0fc26cbb2cac3d10733c48..4c06cae1d0752391595ad13a18595749b7e1a810 100644 (file)
@@ -755,8 +755,11 @@ pub fn matches_return_type(&self,
                 self.probe(|_| {
                     let substs = self.fresh_substs_for_item(self.span, method.def_id);
                     let fty = fty.subst(self.tcx, substs);
-                    let (fty, _) = self.replace_late_bound_regions_with_fresh_var(
-                        self.span, infer::FnCall, &fty);
+                    let (fty, _) = self.replace_bound_vars_with_fresh_vars(
+                        self.span,
+                        infer::FnCall,
+                        &fty
+                    );
 
                     if let Some(self_ty) = self_ty {
                         if self.at(&ObligationCause::dummy(), self.param_env)
index 091af449095aab80ef0876465dba968cdc1ab423..e3a6f92d79e5b74ed9002313c656e86a09a54225 100644 (file)
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::query::Providers;
 use rustc::ty::util::{Representability, IntTypeExt, Discr};
+use rustc::ty::layout::VariantIdx;
+use rustc_data_structures::indexed_vec::Idx;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 
 use require_c_abi_if_variadic;
@@ -1837,10 +1839,11 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len());
-    for (discr, v) in def.discriminants(tcx).zip(vs) {
+    for ((_, discr), v) in def.discriminants(tcx).zip(vs) {
         // Check for duplicate discriminant values
         if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
-            let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap();
+            let variant_did = def.variants[VariantIdx::new(i)].did;
+            let variant_i_node_id = tcx.hir.as_local_node_id(variant_did).unwrap();
             let variant_i = tcx.hir.expect_variant(variant_i_node_id);
             let i_span = match variant_i.node.disr_expr {
                 Some(ref expr) => tcx.hir.span(expr.id),
@@ -1918,11 +1921,11 @@ fn projected_ty_from_poly_trait_ref(&self,
                                         poly_trait_ref: ty::PolyTraitRef<'tcx>)
                                         -> Ty<'tcx>
     {
-        let (trait_ref, _) =
-            self.replace_late_bound_regions_with_fresh_var(
-                span,
-                infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
-                &poly_trait_ref);
+        let (trait_ref, _) = self.replace_bound_vars_with_fresh_vars(
+            span,
+            infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
+            &poly_trait_ref
+        );
 
         self.tcx().mk_projection(item_def_id, trait_ref.substs)
     }
index d5f5cbb562e78514581bea80c91fc6e1237add51..d2dc226aca2501fd9e14da18b08cd795770e1365 100644 (file)
@@ -651,7 +651,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
             };
             (
                 AdtKind::Struct,
-                vec![convert_variant(
+                std::iter::once(convert_variant(
                     tcx,
                     ctor_id.unwrap_or(def_id),
                     item.name,
@@ -659,12 +659,12 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
                     def,
                     AdtKind::Struct,
                     def_id
-                )],
+                )).collect(),
             )
         }
         ItemKind::Union(ref def, _) => (
             AdtKind::Union,
-            vec![convert_variant(
+            std::iter::once(convert_variant(
                 tcx,
                 def_id,
                 item.name,
@@ -672,7 +672,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
                 def,
                 AdtKind::Union,
                 def_id
-            )],
+            )).collect(),
         ),
         _ => bug!(),
     };
@@ -1857,8 +1857,9 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
             &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
                 let ty = icx.to_ty(&bound_pred.bounded_ty);
 
-                // Keep the type around in a WF predicate, in case of no bounds.
-                // That way, `where Ty:` is not a complete noop (see #53696).
+                // Keep the type around in a dummy predicate, in case of no bounds.
+                // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
+                // is still checked for WF.
                 if bound_pred.bounds.is_empty() {
                     if let ty::Param(_) = ty.sty {
                         // This is a `where T:`, which can be in the HIR from the
@@ -1869,7 +1870,10 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                         // compiler/tooling bugs from not handling WF predicates.
                     } else {
                         let span = bound_pred.bounded_ty.span;
-                        predicates.push((ty::Predicate::WellFormed(ty), span));
+                        let predicate = ty::OutlivesPredicate(ty, tcx.mk_region(ty::ReEmpty));
+                        predicates.push(
+                            (ty::Predicate::TypeOutlives(ty::Binder::dummy(predicate)), span)
+                        );
                     }
                 }
 
index 5a020749f3577d4b2eaaf351d13ced1a26bb612d..931ba21f6e4bd8ef66182e089e81b7bbc2c91a41 100644 (file)
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
+use rustc::ty::layout::VariantIdx;
 use rustc::middle::stability;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_typeck::hir_ty_to_ty;
 use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
 use std::collections::hash_map::Entry;
 use std::fmt;
@@ -98,6 +100,12 @@ fn clean(&self, cx: &DocContext) -> Vec<U> {
     }
 }
 
+impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
+    fn clean(&self, cx: &DocContext) -> IndexVec<V, U> {
+        self.iter().map(|x| x.clean(cx)).collect()
+    }
+}
+
 impl<T: Clean<U>, U> Clean<U> for P<T> {
     fn clean(&self, cx: &DocContext) -> U {
         (**self).clean(cx)
@@ -1317,15 +1325,10 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
             Predicate::Projection(ref pred) => pred.clean(cx),
-            Predicate::WellFormed(ty) => {
-                // This comes from `where Ty:` (i.e. no bounds) (see #53696).
-                WherePredicate::BoundPredicate {
-                    ty: ty.clean(cx),
-                    bounds: vec![],
-                }
-            }
-            Predicate::ObjectSafe(_) => panic!("not user writable"),
-            Predicate::ClosureKind(..) => panic!("not user writable"),
+
+            Predicate::WellFormed(..) |
+            Predicate::ObjectSafe(..) |
+            Predicate::ClosureKind(..) |
             Predicate::ConstEvaluatable(..) => panic!("not user writable"),
         }
     }
@@ -2886,7 +2889,7 @@ fn clean(&self, cx: &DocContext) -> VariantStruct {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Enum {
-    pub variants: Vec<Item>,
+    pub variants: IndexVec<VariantIdx, Item>,
     pub generics: Generics,
     pub variants_stripped: bool,
 }
@@ -2902,7 +2905,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             stability: self.stab.clean(cx),
             deprecation: self.depr.clean(cx),
             inner: EnumItem(Enum {
-                variants: self.variants.clean(cx),
+                variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
                 generics: self.generics.clean(cx),
                 variants_stripped: false,
             }),
diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs
new file mode 100644 (file)
index 0000000..f6ba7c7
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![feature(optin_builtin_traits)]
+
+// @has issue_55321/struct.A.html
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Send for A"
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Sync for A"
+pub struct A();
+
+impl !Send for A {}
+impl !Sync for A {}
+
+// @has issue_55321/struct.B.html
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \
+// B<T>"
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Sync for \
+// B<T>"
+pub struct B<T: ?Sized>(A, Box<T>);
index fc20ad0e08b2a40afd3419c964831d965ba29fea..b772db5ca5523f21f3b2400158cc1161886843d5 100644 (file)
@@ -17,7 +17,7 @@ trait Foo { }
 trait Bar where Self: Foo { }
 
 #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<T: Bar>() {
+fn bar<T: Bar + ?Sized>() {
 }
 
 fn main() {
index 3aa04cfeb67d40c4e02e9c24b3a9f32770536674..4aa40bae3193231210f05d596eb19eb7942b2915 100644 (file)
@@ -4,9 +4,9 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
-   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
+   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). }
 
 error: program clause dump
   --> $DIR/lower_env1.rs:19:1
@@ -14,10 +14,9 @@ error: program clause dump
 LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
-   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
-   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
 
 error: aborting due to 2 previous errors
 
index 0b50dbfdf95c6714b8c9c9c87940b86c25543c31..2328db5b4f687cf833f256c2b41fecd7ab90967d 100644 (file)
 trait Foo { }
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct S<'a, T> where T: Foo {
+struct S<'a, T: ?Sized> where T: Foo {
     data: &'a T,
 }
 
 #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<'a, T: Foo>(x: S<T>) {
+fn bar<T: Foo>(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound
 }
 
 fn main() {
index 3b88ac1f22bea6d24d18c4ab02d7bd26441450dc..74833ef064f9d24039d0c37f56ccec536a10c64f 100644 (file)
@@ -4,10 +4,9 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(T: Foo) :- FromEnv(S<'a, T>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(S<'a, T>).
-   = note: TypeOutlives(T : 'a) :- FromEnv(S<'a, T>).
-   = note: WellFormed(S<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(T: Foo), TypeOutlives(T : 'a).
+   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { WellFormed(S<'a, T>) :- Implemented(T: Foo), TypeOutlives(T: 'a). }
 
 error: program clause dump
   --> $DIR/lower_env2.rs:21:1
@@ -15,11 +14,10 @@ error: program clause dump
 LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(T: Foo) :- FromEnv(S<'a, T>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(S<'a, T>).
-   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
-   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
-   = note: TypeOutlives(T : 'a) :- FromEnv(S<'a, T>).
+   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
+   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
 
 error: aborting due to 2 previous errors
 
index ac0f8e34cd437db975fefe0d7e43dd627da38f52..eef6405f8f805e916217566dcb4152e1c8febc61 100644 (file)
@@ -4,7 +4,8 @@ error: program clause dump
 LL |     #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
+   = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
 
 error: program clause dump
   --> $DIR/lower_env3.rs:20:5
@@ -12,9 +13,10 @@ error: program clause dump
 LL |     #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone).
-   = note: Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone).
-   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+   = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
+   = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
+   = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
+   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
 
 error: aborting due to 2 previous errors
 
index c497d76f8d4f964e9bcaed31ca1808e1bc4cd194..92a209f673d5c1143ab52f9d6765cf33ccf6e5b9 100644 (file)
@@ -4,7 +4,7 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
+   = note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). }
 
 error: program clause dump
   --> $DIR/lower_impl.rs:23:5
@@ -12,7 +12,7 @@ error: program clause dump
 LL |     #[rustc_dump_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
+   = note: forall<T> { Normalize(<T as Bar>::Assoc -> std::vec::Vec<T>) :- Implemented(T: Bar). }
 
 error: aborting due to 2 previous errors
 
index 9287555a0568410a9262bc41a5e6ec09337781ec..9b4bba67112ea82df67855cdf71adebbea28f23c 100644 (file)
@@ -11,8 +11,8 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct Foo<T> where Box<T>: Clone {
-    _x: std::marker::PhantomData<T>,
+struct Foo<'a, T> where Box<T>: Clone {
+    _x: std::marker::PhantomData<&'a T>,
 }
 
 fn main() { }
index d6cc9c8e9a401d5c93a8d0459fc2fec5e9c1c623..a0dd9369700af63d3d81de46f7376261a0d54594 100644 (file)
@@ -4,9 +4,10 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Foo<T>).
-   = note: FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<T>).
-   = note: WellFormed(Foo<T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone).
+   = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
 
 error: aborting due to previous error
 
index dc2375277e7342d713049d371ae759707c5fdd1f..6a3f7aa63765f20f16a0d23f822d36484c34f7c8 100644 (file)
@@ -4,10 +4,10 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>).
-   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>).
-   = note: Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>).
-   = note: WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar).
+   = note: forall<Self, S, T> { FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar). }
 
 error: program clause dump
   --> $DIR/lower_trait.rs:17:5
@@ -15,9 +15,9 @@ error: program clause dump
 LL |     #[rustc_dump_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)).
-   = note: ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)).
-   = note: WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>).
+   = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+   = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+   = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>). }
 
 error: aborting due to 2 previous errors
 
index 7fc48cfd56ddcc3b0ffda6253f3fd8ce9c0674ad..c0e1d8fc4c828ef54c61957998be39894c682c70 100644 (file)
@@ -11,9 +11,8 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
+trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
 {
-    fn s(_: F) -> F;
 }
 
 fn main() {
index afb2cd4b563329aa8e07f57de163ac70aeb9aa34..6d3e0ec55b276f966be12bbfe4f57427207ff253 100644 (file)
@@ -4,11 +4,10 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
-   = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
-   = note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
-   = note: ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
-   = note: WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }.
+   = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). }
+   = note: forall<'a, Self, F> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). }
+   = note: forall<Self, F> { Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). }
+   = note: forall<Self, F> { WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }. }
 
 error: aborting due to previous error
 
index 5305591b8434547402ee4ca0e918403cf9b08e01..ac58c0bf2fe37778e477db7d5b954bd8c22d0377 100644 (file)
 
 #![feature(rustc_attrs)]
 
-use std::fmt::{Debug, Display};
 use std::borrow::Borrow;
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<'a, 'b, S, T, U>
+trait Foo<'a, 'b, T, U>
 where
-    S: Debug,
-    T: Borrow<U>,
-    U: ?Sized,
+    T: Borrow<U> + ?Sized,
+    U: ?Sized + 'b,
     'a: 'b,
-    U: 'b,
-    Vec<T>:, // NOTE(#53696) this checks an empty list of bounds.
+    Box<T>:, // NOTE(#53696) this checks an empty list of bounds.
 {
-    fn s(_: S) -> S;
-    fn t(_: T) -> T;
-    fn u(_: U) -> U;
 }
 
 fn main() {
index ad3546da1a25b4e93432af8be214dcce119757c7..fcd516c89ba3326ede1278e5a9ee42259bd6c7d9 100644 (file)
@@ -1,18 +1,15 @@
 error: program clause dump
-  --> $DIR/lower_trait_where_clause.rs:16:1
+  --> $DIR/lower_trait_where_clause.rs:15:1
    |
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b), WellFormed(std::vec::Vec<T>).
-   = note: WellFormed(std::vec::Vec<T>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(std::boxed::Box<T>: '<empty>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow<U>), TypeOutlives(U: 'b), RegionOutlives('a: 'b), TypeOutlives(std::boxed::Box<T>: '<empty>). }
 
 error: aborting due to previous error
 
index 804c9643d8ae30f93dc42fae1187258f12a57bda..d36e96b08174a125cfb6f30bcca976d39587ef58 100644 (file)
@@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:61:1
    |
 LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .Some.0.1, but expected something less or equal to 1114111
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .<downcast-variant(Some)>.0.1, but expected something less or equal to 1114111
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
 
index 7f726d13a33ed4a53e1846c027c007379bb6a35f..ef5fb8eadc355284e9ed7d2295b0a7a2459e800d 100644 (file)
@@ -39,7 +39,7 @@ fn main() {
     // Here: we only want the `T` to be given, the rest should be variables.
     //
     // (`T` refers to the declaration of `Bazoom`)
-    let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
+    let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
     x(&22, 44, 66);
 
     // Here: all are given
@@ -51,7 +51,7 @@ fn main() {
     //
     // (`U` refers to the declaration of `Bazoom`)
     let y = 22_u32;
-    y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
+    y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
 
     // Here: nothing is given, so we don't have any annotation.
     let y = 22_u32;
index 3beb994a4e8a5731636422713a23c31d5959541a..359423d0cfbea4b31a8254da8c0233709427e57f 100644 (file)
@@ -4,10 +4,10 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs
 LL |     let x = foo::<u32>; //~ ERROR [u32]
    |             ^^^^^^^^^^
 
-error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [?0, u32, ?1], user_self_ty: None } }
+error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
   --> $DIR/dump-fn-method.rs:42:13
    |
-LL |     let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [?0, u32, ?1]
+LL |     let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } }
@@ -16,10 +16,10 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs
 LL |     let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [?0, ?1, u32], user_self_ty: None } }
+error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
   --> $DIR/dump-fn-method.rs:54:5
    |
-LL |     y.method::<u32>(44, 66); //~ ERROR [?0, ?1, u32]
+LL |     y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors