]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #51081 - kornelski:examplestr, r=steveklabnik
authorbors <bors@rust-lang.org>
Tue, 19 Jun 2018 13:09:04 +0000 (13:09 +0000)
committerbors <bors@rust-lang.org>
Tue, 19 Jun 2018 13:09:04 +0000 (13:09 +0000)
Use String, not &str in some collection examples

Discussed in #46966

Overuse of borrowed values in data structures is a common mistake I see in Rust user forums. Users who copy&paste such examples end up fighting with the borrow checker as soon as they replace string literals with some real values.

This changes a couple of examples to use `String`, and it adds opportunity to demonstrate use of `Borrow`.

103 files changed:
src/doc/book
src/doc/nomicon
src/doc/reference
src/doc/rust-by-example
src/librustc/hir/def.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/hir_id_validator.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/infer/anon_types/mod.rs
src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/traits/query/normalize.rs
src/librustc/ty/context.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/item_path.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/lib.rs
src/librustc_codegen_llvm/common.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/sync.rs
src/librustc_driver/driver.rs
src/librustc_driver/test.rs
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/save.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check/nll/constraint_generation.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs [deleted file]
src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/nll/type_check/input_output.rs
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/mod.rs
src/librustdoc/visit_ast.rs
src/libstd/path.rs
src/libsyntax/parse/parser.rs
src/libsyntax_ext/deriving/custom.rs
src/libsyntax_pos/hygiene.rs
src/test/incremental/hashes/function_interfaces.rs
src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/mod_dir_simple/compiletest-ignore-dir [new file with mode: 0644]
src/test/run-pass-fulldeps/mod_dir_simple/test.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-union.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/derive-union.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/auxiliary/xcrate.rs
src/test/run-pass/impl-trait/bounds_regression.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/example-calendar.rs
src/test/run-pass/impl-trait/existential-minimal.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/nesting.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/xcrate_simple.rs [new file with mode: 0644]
src/test/ui/impl-trait/auto-trait-leak.rs
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/auto-trait-leak2.rs [new file with mode: 0644]
src/test/ui/impl-trait/auto-trait-leak2.stderr [new file with mode: 0644]
src/test/ui/impl-trait/equality.rs
src/test/ui/impl-trait/equality.stderr
src/test/ui/impl-trait/equality2.rs [new file with mode: 0644]
src/test/ui/impl-trait/equality2.stderr [new file with mode: 0644]
src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
src/test/ui/nll/closure-requirements/escape-argument.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr

index 36d65d00164d1750f6fa7f8b0f52dabc3fea500b..f475da63a18d50217459a601cbef69a4bcac5e71 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 36d65d00164d1750f6fa7f8b0f52dabc3fea500b
+Subproject commit f475da63a18d50217459a601cbef69a4bcac5e71
index 748a5e6742db4a21c4c630a58087f818828e8a0a..13e3745ca399118df05e8261e12e3ada6e616b48 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 748a5e6742db4a21c4c630a58087f818828e8a0a
+Subproject commit 13e3745ca399118df05e8261e12e3ada6e616b48
index 134f419ee62714590b04712fe6072253bc2a7822..0f63519ea10c028f48b2dbf7d0a2454203b68b0b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 134f419ee62714590b04712fe6072253bc2a7822
+Subproject commit 0f63519ea10c028f48b2dbf7d0a2454203b68b0b
index eebda16e4b45f2eed4310cf7b9872cc752278163..d2a64395a5210a61d3512a3a5c615f5c47699443 160000 (submodule)
@@ -1 +1 @@
-Subproject commit eebda16e4b45f2eed4310cf7b9872cc752278163
+Subproject commit d2a64395a5210a61d3512a3a5c615f5c47699443
index fd14be592be303fe0749b57b9f3e41cd600c2da0..7c10292061f75dd885ce69674f48c1b51b3cf3c3 100644 (file)
@@ -37,6 +37,7 @@ pub enum Def {
     Enum(DefId),
     Variant(DefId),
     Trait(DefId),
+    Existential(DefId),
     TyAlias(DefId),
     TyForeign(DefId),
     TraitAlias(DefId),
@@ -234,6 +235,7 @@ pub fn def_id(&self) -> DefId {
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
             Def::AssociatedConst(id) | Def::Macro(id, ..) |
+            Def::Existential(id) |
             Def::GlobalAsm(id) | Def::TyForeign(id) => {
                 id
             }
@@ -260,6 +262,7 @@ pub fn kind_name(&self) -> &'static str {
             Def::VariantCtor(.., CtorKind::Const) => "unit variant",
             Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
             Def::Enum(..) => "enum",
+            Def::Existential(..) => "existential type",
             Def::TyAlias(..) => "type alias",
             Def::TraitAlias(..) => "trait alias",
             Def::AssociatedTy(..) => "associated type",
index 5471568d0af04622b4b61740abe7107d91f31841..12ccb329e06ff2cd541b0ae6b3c6c325f4cde16f 100644 (file)
@@ -502,6 +502,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
         }
+        ItemExistential(ExistTy {ref generics, ref bounds, impl_trait_fn}) => {
+            visitor.visit_id(item.id);
+            walk_generics(visitor, generics);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            if let Some(impl_trait_fn) = impl_trait_fn {
+                visitor.visit_def_mention(Def::Fn(impl_trait_fn))
+            }
+        }
         ItemEnum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters);
             // visit_enum_def() takes care of visiting the Item's NodeId
@@ -596,10 +604,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             }
             visitor.visit_lifetime(lifetime);
         }
-        TyImplTraitExistential(ref existty, ref lifetimes) => {
-            let ExistTy { ref generics, ref bounds } = *existty;
-            walk_generics(visitor, generics);
-            walk_list!(visitor, visit_ty_param_bound, bounds);
+        TyImplTraitExistential(item_id, def_id, ref lifetimes) => {
+            visitor.visit_def_mention(Def::Existential(def_id));
+            visitor.visit_nested_item(item_id);
             walk_list!(visitor, visit_lifetime, lifetimes);
         }
         TyTypeof(ref expression) => {
index f31af7785a55bb4678acfcb778f3bf6b9259111d..dd12edb73027a39e72cb727e362207c0cb128754 100644 (file)
@@ -182,7 +182,9 @@ enum ImplTraitContext {
     /// Treat `impl Trait` as shorthand for a new universal existential parameter.
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
     /// equivalent to a fresh existential parameter like `abstract type T; fn foo() -> T`.
-    Existential,
+    ///
+    /// We store a DefId here so we can look up necessary information later
+    Existential(DefId),
 
     /// `impl Trait` is not accepted in this position.
     Disallowed,
@@ -238,6 +240,7 @@ enum ParamMode {
     Optional,
 }
 
+#[derive(Debug)]
 struct LoweredNodeId {
     node_id: NodeId,
     hir_id: hir::HirId,
@@ -488,16 +491,16 @@ fn lower_node_id_generic<F>(&mut self, ast_node_id: NodeId, alloc_hir_id: F) ->
         }
     }
 
-    fn with_hir_id_owner<F>(&mut self, owner: NodeId, f: F)
+    fn with_hir_id_owner<F, T>(&mut self, owner: NodeId, f: F) -> T
     where
-        F: FnOnce(&mut Self),
+        F: FnOnce(&mut Self) -> T,
     {
         let counter = self.item_local_id_counters
             .insert(owner, HIR_ID_COUNTER_LOCKED)
             .unwrap();
         let def_index = self.resolver.definitions().opt_def_index(owner).unwrap();
         self.current_hir_id_owner.push((def_index, counter));
-        f(self);
+        let ret = f(self);
         let (new_def_index, new_counter) = self.current_hir_id_owner.pop().unwrap();
 
         debug_assert!(def_index == new_def_index);
@@ -507,6 +510,7 @@ fn with_hir_id_owner<F>(&mut self, owner: NodeId, f: F)
             .insert(owner, new_counter)
             .unwrap();
         debug_assert!(prev == HIR_ID_COUNTER_LOCKED);
+        ret
     }
 
     /// This method allocates a new HirId for the given NodeId and stores it in
@@ -530,7 +534,10 @@ fn lower_node_id(&mut self, ast_node_id: NodeId) -> LoweredNodeId {
 
     fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> LoweredNodeId {
         self.lower_node_id_generic(ast_node_id, |this| {
-            let local_id_counter = this.item_local_id_counters.get_mut(&owner).unwrap();
+            let local_id_counter = this
+                .item_local_id_counters
+                .get_mut(&owner)
+                .expect("called lower_node_id_with_owner before allocate_hir_id_counter");
             let local_id = *local_id_counter;
 
             // We want to be sure not to modify the counter in the map while it
@@ -539,7 +546,12 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> Lo
             debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
 
             *local_id_counter += 1;
-            let def_index = this.resolver.definitions().opt_def_index(owner).unwrap();
+            let def_index = this
+                .resolver
+                .definitions()
+                .opt_def_index(owner)
+                .expect("You forgot to call `create_def_with_parent` or are lowering node ids \
+                         that do not belong to the current owner");
 
             hir::HirId {
                 owner: def_index,
@@ -1120,26 +1132,93 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
             TyKind::ImplTrait(ref bounds) => {
                 let span = t.span;
                 match itctx {
-                    ImplTraitContext::Existential => {
-                        let def_index = self.resolver.definitions().opt_def_index(t.id).unwrap();
-                        let hir_bounds = self.lower_bounds(bounds, itctx);
-                        let (lifetimes, lifetime_defs) =
-                            self.lifetimes_from_impl_trait_bounds(def_index, &hir_bounds);
+                    ImplTraitContext::Existential(fn_def_id) => {
+
+                        // We need to manually repeat the code of `next_id` because the lowering
+                        // needs to happen while the owner_id is pointing to the item itself,
+                        // because items are their own owners
+                        let exist_ty_node_id = self.sess.next_node_id();
+
+                        // Make sure we know that some funky desugaring has been going on here.
+                        // This is a first: there is code in other places like for loop
+                        // desugaring that explicitly states that we don't want to track that.
+                        // Not tracking it makes lints in rustc and clippy very fragile as
+                        // frequently opened issues show.
+                        let exist_ty_span = self.allow_internal_unstable(
+                            CompilerDesugaringKind::ExistentialReturnType,
+                            t.span,
+                        );
 
-                        hir::TyImplTraitExistential(
-                            hir::ExistTy {
+                        // Pull a new definition from the ether
+                        let exist_ty_def_index = self
+                            .resolver
+                            .definitions()
+                            .create_def_with_parent(
+                            fn_def_id.index,
+                            exist_ty_node_id,
+                            DefPathData::ExistentialImplTrait,
+                            DefIndexAddressSpace::High,
+                            Mark::root(),
+                            exist_ty_span,
+                        );
+
+                        // the `t` is just for printing debug messages
+                        self.allocate_hir_id_counter(exist_ty_node_id, t);
+
+                        let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, |lctx| {
+                            lctx.lower_bounds(bounds, itctx)
+                        });
+
+                        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
+                            exist_ty_node_id,
+                            exist_ty_def_index,
+                            &hir_bounds,
+                        );
+
+                        self.with_hir_id_owner(exist_ty_node_id, |lctx| {
+                            let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy {
                                 generics: hir::Generics {
                                     params: lifetime_defs,
                                     where_clause: hir::WhereClause {
-                                        id: self.next_id().node_id,
+                                        id: lctx.next_id().node_id,
                                         predicates: Vec::new().into(),
                                     },
                                     span,
                                 },
                                 bounds: hir_bounds,
-                            },
-                            lifetimes,
-                        )
+                                impl_trait_fn: Some(fn_def_id),
+                            });
+                            let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
+                            // Generate an `existential type Foo: Trait;` declaration
+                            trace!("creating existential type with id {:#?}", exist_ty_id);
+                            // Set the name to `impl Bound1 + Bound2`
+                            let exist_ty_name = Symbol::intern(&pprust::ty_to_string(t));
+
+                            trace!("exist ty def index: {:#?}", exist_ty_def_index);
+                            let exist_ty_item = hir::Item {
+                                id: exist_ty_id.node_id,
+                                hir_id: exist_ty_id.hir_id,
+                                name: exist_ty_name,
+                                attrs: Default::default(),
+                                node: exist_ty_item_kind,
+                                vis: hir::Visibility::Inherited,
+                                span: exist_ty_span,
+                            };
+
+                            // Insert the item into the global list. This usually happens
+                            // automatically for all AST items. But this existential type item
+                            // does not actually exist in the AST.
+                            lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
+
+                            // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
+                            hir::TyImplTraitExistential(
+                                hir::ItemId {
+                                    id: exist_ty_id.node_id
+                                },
+                                DefId::local(exist_ty_def_index),
+                                lifetimes,
+                            )
+                        })
                     }
                     ImplTraitContext::Universal(def_id) => {
                         let def_node_id = self.next_id().node_id;
@@ -1148,7 +1227,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                         let def_index = self.resolver.definitions().create_def_with_parent(
                             def_id.index,
                             def_node_id,
-                            DefPathData::ImplTrait,
+                            DefPathData::UniversalImplTrait,
                             DefIndexAddressSpace::High,
                             Mark::root(),
                             span,
@@ -1203,6 +1282,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
 
     fn lifetimes_from_impl_trait_bounds(
         &mut self,
+        exist_ty_id: NodeId,
         parent_index: DefIndex,
         bounds: &hir::TyParamBounds,
     ) -> (HirVec<hir::Lifetime>, HirVec<hir::GenericParam>) {
@@ -1212,6 +1292,7 @@ fn lifetimes_from_impl_trait_bounds(
         struct ImplTraitLifetimeCollector<'r, 'a: 'r> {
             context: &'r mut LoweringContext<'a>,
             parent: DefIndex,
+            exist_ty_id: NodeId,
             collect_elided_lifetimes: bool,
             currently_bound_lifetimes: Vec<hir::LifetimeName>,
             already_defined_lifetimes: HashSet<hir::LifetimeName>,
@@ -1306,7 +1387,11 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                         name,
                     });
 
-                    let def_node_id = self.context.next_id().node_id;
+                    // We need to manually create the ids here, because the
+                    // definitions will go into the explicit `existential type`
+                    // declaration and thus need to have their owner set to that item
+                    let def_node_id = self.context.sess.next_node_id();
+                    let _ = self.context.lower_node_id_with_owner(def_node_id, self.exist_ty_id);
                     self.context.resolver.definitions().create_def_with_parent(
                         self.parent,
                         def_node_id,
@@ -1318,7 +1403,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
                     let def_lifetime = hir::Lifetime {
                         id: def_node_id,
                         span: lifetime.span,
-                        name: name,
+                        name,
                     };
                     self.output_lifetime_params
                         .push(hir::GenericParam::Lifetime(hir::LifetimeDef {
@@ -1334,6 +1419,7 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
         let mut lifetime_collector = ImplTraitLifetimeCollector {
             context: self,
             parent: parent_index,
+            exist_ty_id,
             collect_elided_lifetimes: true,
             currently_bound_lifetimes: Vec::new(),
             already_defined_lifetimes: HashSet::new(),
@@ -1772,8 +1858,8 @@ fn lower_fn_decl(
                 .collect(),
             output: match decl.output {
                 FunctionRetTy::Ty(ref ty) => match fn_def_id {
-                    Some(_) if impl_trait_return_allow => {
-                        hir::Return(self.lower_ty(ty, ImplTraitContext::Existential))
+                    Some(def_id) if impl_trait_return_allow => {
+                        hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id)))
                     }
                     _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
                 },
index 03b6dc1676fb33d63fb89cdb743fa72eb740f6d4..48d959b4f8e4199552ebef77831731fbc39830f0 100644 (file)
@@ -88,7 +88,7 @@ fn visit_item(&mut self, i: &'a Item) {
         debug!("visit_item: {:?}", i);
 
         // Pick the def data. This need not be unique, but the more
-        // information we encapsulate into
+        // information we encapsulate into, the better
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
             ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_interned_str()),
@@ -256,9 +256,6 @@ fn visit_expr(&mut self, expr: &'a Expr) {
     fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.node {
             TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
-            TyKind::ImplTrait(..) => {
-                self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span);
-            }
             _ => {}
         }
         visit::walk_ty(self, ty);
index 838be076a0b62c397ec9be7ad8bc2fc2dc57c2dd..99023a168674179cf37721c05f9362cbea53307f 100644 (file)
@@ -210,30 +210,9 @@ fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash {
         } = self.disambiguated_data;
 
         ::std::mem::discriminant(data).hash(&mut hasher);
-        match *data {
-            DefPathData::TypeNs(name) |
-            DefPathData::Trait(name) |
-            DefPathData::AssocTypeInTrait(name) |
-            DefPathData::AssocTypeInImpl(name) |
-            DefPathData::ValueNs(name) |
-            DefPathData::Module(name) |
-            DefPathData::MacroDef(name) |
-            DefPathData::TypeParam(name) |
-            DefPathData::LifetimeDef(name) |
-            DefPathData::EnumVariant(name) |
-            DefPathData::Field(name) |
-            DefPathData::GlobalMetaData(name) => {
-                name.hash(&mut hasher);
-            }
-
-            DefPathData::Impl |
-            DefPathData::CrateRoot |
-            DefPathData::Misc |
-            DefPathData::ClosureExpr |
-            DefPathData::StructCtor |
-            DefPathData::AnonConst |
-            DefPathData::ImplTrait => {}
-        };
+        if let Some(name) = data.get_opt_name() {
+            name.hash(&mut hasher);
+        }
 
         disambiguator.hash(&mut hasher);
 
@@ -390,8 +369,10 @@ pub enum DefPathData {
     StructCtor,
     /// A constant expression (see {ast,hir}::AnonConst).
     AnonConst,
-    /// An `impl Trait` type node.
-    ImplTrait,
+    /// An `impl Trait` type node in argument position.
+    UniversalImplTrait,
+    /// An `impl Trait` type node in return position.
+    ExistentialImplTrait,
 
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
@@ -655,7 +636,8 @@ pub fn get_opt_name(&self) -> Option<InternedString> {
             ClosureExpr |
             StructCtor |
             AnonConst |
-            ImplTrait => None
+            ExistentialImplTrait |
+            UniversalImplTrait => None
         }
     }
 
@@ -685,7 +667,8 @@ pub fn as_interned_str(&self) -> InternedString {
             ClosureExpr => "{{closure}}",
             StructCtor => "{{constructor}}",
             AnonConst => "{{constant}}",
-            ImplTrait => "{{impl-Trait}}",
+            ExistentialImplTrait => "{{exist-impl-Trait}}",
+            UniversalImplTrait => "{{univ-impl-Trait}}",
         };
 
         Symbol::intern(s).as_interned_str()
index a4c931115833240b3da4ed53b891c3523c337202..b90bca84ed602ebeda7487631af2b4ea247673ea 100644 (file)
@@ -96,7 +96,7 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
                       .keys()
                       .map(|local_id| local_id.as_usize())
                       .max()
-                      .unwrap();
+                      .expect("owning item has no entry");
 
         if max != self.hir_ids_seen.len() - 1 {
             // Collect the missing ItemLocalIds
@@ -113,6 +113,8 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
                     local_id: ItemLocalId(local_id as u32),
                 };
 
+                trace!("missing hir id {:#?}", hir_id);
+
                 // We are already in ICE mode here, so doing a linear search
                 // should be fine.
                 let (node_id, _) = self.hir_map
@@ -121,7 +123,7 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
                                        .iter()
                                        .enumerate()
                                        .find(|&(_, &entry)| hir_id == entry)
-                                       .unwrap();
+                                       .expect("no node_to_hir_id entry");
                 let node_id = NodeId::new(node_id);
                 missing_items.push(format!("[local_id: {}, node:{}]",
                                            local_id,
@@ -146,7 +148,7 @@ fn nested_visit_map<'this>(&'this mut self)
     }
 
     fn visit_id(&mut self, node_id: NodeId) {
-        let owner = self.owner_def_index.unwrap();
+        let owner = self.owner_def_index.expect("no owner_def_index");
         let stable_id = self.hir_map.definitions().node_to_hir_id[node_id];
 
         if stable_id == hir::DUMMY_HIR_ID {
index d6de2f57e9295f150fb1bedc20e883a5a8298912..9df55e52061634962c67b5e5dcd338cf497f1fea 100644 (file)
@@ -398,6 +398,7 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                     ItemFn(..) => Some(Def::Fn(def_id())),
                     ItemMod(..) => Some(Def::Mod(def_id())),
                     ItemGlobalAsm(..) => Some(Def::GlobalAsm(def_id())),
+                    ItemExistential(..) => Some(Def::Existential(def_id())),
                     ItemTy(..) => Some(Def::TyAlias(def_id())),
                     ItemEnum(..) => Some(Def::Enum(def_id())),
                     ItemStruct(..) => Some(Def::Struct(def_id())),
@@ -767,7 +768,7 @@ pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
 
     /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
     /// parent item is in this map. The "parent item" is the closest parent node
-    /// in the AST which is recorded by the map and is an item, either an item
+    /// in the HIR which is recorded by the map and is an item, either an item
     /// in a module, trait, or impl.
     pub fn get_parent(&self, id: NodeId) -> NodeId {
         match self.walk_parent_nodes(id, |node| match *node {
@@ -1250,6 +1251,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemForeignMod(..) => "foreign mod",
                 ItemGlobalAsm(..) => "global asm",
                 ItemTy(..) => "ty",
+                ItemExistential(..) => "existential",
                 ItemEnum(..) => "enum",
                 ItemStruct(..) => "struct",
                 ItemUnion(..) => "union",
index a0952720945e870ae2cffcf4b95c61ba3ca92ffb..833090c3ee092342a836cad6eafdc9a059a9fd83 100644 (file)
@@ -1693,6 +1693,7 @@ pub struct BareFnTy {
 pub struct ExistTy {
     pub generics: Generics,
     pub bounds: TyParamBounds,
+    pub impl_trait_fn: Option<DefId>,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1723,15 +1724,15 @@ pub enum Ty_ {
     /// An existentially quantified (there exists a type satisfying) `impl
     /// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
     ///
-    /// The `ExistTy` structure emulates an
-    /// `abstract type Foo<'a, 'b>: MyTrait<'a, 'b>;`.
+    /// The `Item` is the generated
+    /// `existential type Foo<'a, 'b>: MyTrait<'a, 'b>;`.
     ///
     /// The `HirVec<Lifetime>` is the list of lifetimes applied as parameters
     /// to the `abstract type`, e.g. the `'c` and `'d` in `-> Foo<'c, 'd>`.
     /// This list is only a list of lifetimes and not type parameters
     /// because all in-scope type parameters are captured by `impl Trait`,
     /// so they are resolved directly through the parent `Generics`.
-    TyImplTraitExistential(ExistTy, HirVec<Lifetime>),
+    TyImplTraitExistential(ItemId, DefId, HirVec<Lifetime>),
     /// Unused for now
     TyTypeof(AnonConst),
     /// TyInfer means the type should be inferred instead of it having been
@@ -2091,6 +2092,8 @@ pub enum Item_ {
     ItemGlobalAsm(P<GlobalAsm>),
     /// A type alias, e.g. `type Foo = Bar<u8>`
     ItemTy(P<Ty>, Generics),
+    /// A type alias, e.g. `type Foo = Bar<u8>`
+    ItemExistential(ExistTy),
     /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
     ItemEnum(EnumDef, Generics),
     /// A struct definition, e.g. `struct Foo<A> {x: A}`
@@ -2124,6 +2127,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemForeignMod(..) => "foreign module",
             ItemGlobalAsm(..) => "global asm",
             ItemTy(..) => "type alias",
+            ItemExistential(..) => "existential type",
             ItemEnum(..) => "enum",
             ItemStruct(..) => "struct",
             ItemUnion(..) => "union",
index 2cf627fdc162f556e409b4b6e2110829780aa3fa..1beef3f715e22098c8a50c33f131f590846a434a 100644 (file)
@@ -58,6 +58,9 @@ fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
     fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
         Ok(())
     }
+    fn try_fetch_item(&self, _: ast::NodeId) -> Option<&hir::Item> {
+        None
+    }
 }
 
 pub struct NoAnn;
@@ -65,6 +68,9 @@ impl PpAnn for NoAnn {}
 pub const NO_ANN: &'static dyn PpAnn = &NoAnn;
 
 impl PpAnn for hir::Crate {
+    fn try_fetch_item(&self, item: ast::NodeId) -> Option<&hir::Item> {
+        Some(self.item(item))
+    }
     fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> {
         match nested {
             Nested::Item(id) => state.print_item(self.item(id.id)),
@@ -413,8 +419,14 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
                     self.print_lifetime(lifetime)?;
                 }
             }
-            hir::TyImplTraitExistential(ref existty, ref _lifetimes) => {
-                self.print_bounds("impl", &existty.bounds[..])?;
+            hir::TyImplTraitExistential(hir_id, _def_id, ref _lifetimes) => {
+                match self.ann.try_fetch_item(hir_id.id).map(|it| &it.node) {
+                    None => self.word_space("impl {{Trait}}")?,
+                    Some(&hir::ItemExistential(ref exist_ty)) => {
+                        self.print_bounds("impl", &exist_ty.bounds)?;
+                    },
+                    other => bug!("impl Trait pointed to {:#?}", other),
+                }
             }
             hir::TyArray(ref ty, ref length) => {
                 self.s.word("[")?;
@@ -636,6 +648,31 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.s.word(";")?;
                 self.end()?; // end the outer ibox
             }
+            hir::ItemExistential(ref exist) => {
+                self.ibox(indent_unit)?;
+                self.ibox(0)?;
+                self.word_nbsp(&visibility_qualified(&item.vis, "existential type"))?;
+                self.print_name(item.name)?;
+                self.print_generic_params(&exist.generics.params)?;
+                self.end()?; // end the inner ibox
+
+                self.print_where_clause(&exist.generics.where_clause)?;
+                self.s.space()?;
+                self.word_space(":")?;
+                let mut real_bounds = Vec::with_capacity(exist.bounds.len());
+                for b in exist.bounds.iter() {
+                    if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
+                        self.s.space()?;
+                        self.word_space("for ?")?;
+                        self.print_trait_ref(&ptr.trait_ref)?;
+                    } else {
+                        real_bounds.push(b.clone());
+                    }
+                }
+                self.print_bounds(":", &real_bounds[..])?;
+                self.s.word(";")?;
+                self.end()?; // end the outer ibox
+            }
             hir::ItemEnum(ref enum_definition, ref params) => {
                 self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?;
             }
index a781fc7240ab3882394c651dcadbda484e0d94c7..ed259b2854511bd8c34eb994b0cc6a39ce990a4a 100644 (file)
@@ -310,6 +310,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(struct hir::ExistTy {
     generics,
+    impl_trait_fn,
     bounds
 });
 
@@ -323,7 +324,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     TyTup(ts),
     TyPath(qpath),
     TyTraitObject(trait_refs, lifetime),
-    TyImplTraitExistential(existty, lifetimes),
+    TyImplTraitExistential(existty, def_id, lifetimes),
     TyTypeof(body_id),
     TyErr,
     TyInfer
@@ -889,6 +890,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     ItemForeignMod(foreign_mod),
     ItemGlobalAsm(global_asm),
     ItemTy(ty, generics),
+    ItemExistential(exist),
     ItemEnum(enum_def, generics),
     ItemStruct(variant_data, generics),
     ItemUnion(variant_data, generics),
@@ -1046,6 +1048,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     Struct(def_id),
     Union(def_id),
     Enum(def_id),
+    Existential(def_id),
     Variant(def_id),
     Trait(def_id),
     TyAlias(def_id),
index 3a37c1c18c8d9fcd976e55d5bfe5958712f99cd3..7b14831cf95c0d2c1e4920e165b1a6a074746735 100644 (file)
@@ -411,6 +411,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
     DotFill,
     QuestionMark,
+    ExistentialReturnType,
     Catch
 });
 
index a7879025eeae4e5b35c84fa3578919299ba04abc..f068a54ce44479f27a49ce8a1e49d9416f1da2e1 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
+use hir;
 use infer::{self, InferCtxt, InferOk, TypeVariableOrigin};
 use infer::outlives::free_region_map::FreeRegionRelations;
 use rustc_data_structures::fx::FxHashMap;
@@ -689,8 +690,16 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
                     // }
                     // ```
                     if let Some(anon_node_id) = tcx.hir.as_local_node_id(def_id) {
-                        let anon_parent_node_id = tcx.hir.get_parent(anon_node_id);
-                        let anon_parent_def_id = tcx.hir.local_def_id(anon_parent_node_id);
+                        let anon_parent_def_id = match tcx.hir.expect_item(anon_node_id).node {
+                            hir::ItemExistential(hir::ExistTy {
+                                impl_trait_fn: Some(parent),
+                                ..
+                            }) => parent,
+                            _ => {
+                                let anon_parent_node_id = tcx.hir.get_parent(anon_node_id);
+                                tcx.hir.local_def_id(anon_parent_node_id)
+                            },
+                        };
                         if self.parent_def_id == anon_parent_def_id {
                             return self.fold_anon_ty(ty, def_id, substs);
                         }
index 13c849ec0b764d72823eae0d824859d30e30fcdd..b148a7401f8baa16a3ccab8c5621e7779cf370a2 100644 (file)
@@ -77,7 +77,7 @@ fn find_component_for_bound_region(
             tcx: self.tcx,
             bound_region: *br,
             found_type: None,
-            current_index: ty::DebruijnIndex::INNERMOST,
+            current_index: ty::INNERMOST,
         };
         nested_visitor.visit_ty(arg);
         nested_visitor.found_type
index cd73da9adc8adcb7a5fa2dc8f397eaa8366d6f7f..680d445a1bcfcc6b169d405998178bc598df5250 100644 (file)
@@ -417,8 +417,7 @@ fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
         {
             for (a_br, a_r) in a_map {
                 if *a_r == r {
-                    return infcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::INNERMOST,
-                                                               *a_br));
+                    return infcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, *a_br));
                 }
             }
             span_bug!(
@@ -735,7 +734,7 @@ pub fn plug_leaks<T>(&self,
                     // trait checking, and all of the skolemized regions
                     // appear inside predicates, which always have
                     // binders, so this assert is satisfied.
-                    assert!(current_depth > ty::DebruijnIndex::INNERMOST);
+                    assert!(current_depth > ty::INNERMOST);
 
                     // since leak-check passed, this skolemized region
                     // should only have incoming edges from variables
index 99d7b4eaf7d68b3b468934ba2c404f2b3c8023c1..296808cea2bd733fb58b3f171937cc0c9f98652e 100644 (file)
@@ -69,6 +69,10 @@ pub struct RegionConstraintCollector<'tcx> {
     /// would wind up with a fresh stream of region variables that
     /// have been equated but appear distinct.
     unification_table: ut::UnificationTable<ut::InPlace<ty::RegionVid>>,
+
+    /// a flag set to true when we perform any unifications; this is used
+    /// to micro-optimize `take_and_reset_data`
+    any_unifications: bool,
 }
 
 pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
@@ -234,6 +238,7 @@ pub struct RegionVariableInfo {
 pub struct RegionSnapshot {
     length: usize,
     region_snapshot: ut::Snapshot<ut::InPlace<ty::RegionVid>>,
+    any_unifications: bool,
 }
 
 /// When working with skolemized regions, we often wish to find all of
@@ -280,6 +285,7 @@ pub fn new() -> RegionConstraintCollector<'tcx> {
             bound_count: 0,
             undo_log: Vec::new(),
             unification_table: ut::UnificationTable::new(),
+            any_unifications: false,
         }
     }
 
@@ -325,6 +331,7 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
             bound_count: _,
             undo_log: _,
             unification_table,
+            any_unifications,
         } = self;
 
         // Clear the tables of (lubs, glbs), so that we will create
@@ -338,7 +345,10 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
         // un-unified" state. Note that when we unify `a` and `b`, we
         // also insert `a <= b` and a `b <= a` edges, so the
         // `RegionConstraintData` contains the relationship here.
-        unification_table.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
+        if *any_unifications {
+            unification_table.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
+            *any_unifications = false;
+        }
 
         mem::replace(data, RegionConstraintData::default())
     }
@@ -358,6 +368,7 @@ pub fn start_snapshot(&mut self) -> RegionSnapshot {
         RegionSnapshot {
             length,
             region_snapshot: self.unification_table.snapshot(),
+            any_unifications: self.any_unifications,
         }
     }
 
@@ -385,6 +396,7 @@ pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
         let c = self.undo_log.pop().unwrap();
         assert!(c == OpenSnapshot);
         self.unification_table.rollback_to(snapshot.region_snapshot);
+        self.any_unifications = snapshot.any_unifications;
     }
 
     fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) {
@@ -623,6 +635,7 @@ pub fn make_eqregion(
 
             if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
                 self.unification_table.union(sub, sup);
+                self.any_unifications = true;
             }
         }
     }
index 6b47a90079a6e711518ae378bb97174d8ac67156..40cf78edaecaebef9dd958c2f3bba0083c9bb510 100644 (file)
@@ -267,6 +267,7 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     // inherently and their children are already in the
                     // worklist, as determined by the privacy pass
                     hir::ItemExternCrate(_) | hir::ItemUse(..) |
+                    hir::ItemExistential(..) |
                     hir::ItemTy(..) | hir::ItemStatic(..) |
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
index 781d48e2123938d2e57608242cf2f94c8d523135..f251a3d5f38380ab42226b9041aff44cc228cce7 100644 (file)
@@ -98,7 +98,7 @@ fn early(
     }
 
     fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
-        let depth = ty::DebruijnIndex::INNERMOST;
+        let depth = ty::INNERMOST;
         let def_id = hir_map.local_def_id(def.lifetime.id);
         let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
         debug!(
@@ -114,7 +114,7 @@ fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
     fn late_anon(index: &Cell<u32>) -> Region {
         let i = index.get();
         index.set(i + 1);
-        let depth = ty::DebruijnIndex::INNERMOST;
+        let depth = ty::INNERMOST;
         Region::LateBoundAnon(depth, i)
     }
 
@@ -499,7 +499,13 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 };
                 self.with(scope, |_, this| intravisit::walk_item(this, item));
             }
+            hir::ItemExistential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => {
+                // currently existential type declarations are just generated from impl Trait
+                // items. doing anything on this node is irrelevant, as we currently don't need
+                // it.
+            }
             hir::ItemTy(_, ref generics)
+            | hir::ItemExistential(hir::ExistTy { impl_trait_fn: None, ref generics, .. })
             | hir::ItemEnum(_, ref generics)
             | hir::ItemStruct(_, ref generics)
             | hir::ItemUnion(_, ref generics)
@@ -613,7 +619,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                 };
                 self.with(scope, |_, this| this.visit_ty(&mt.ty));
             }
-            hir::TyImplTraitExistential(ref exist_ty, ref lifetimes) => {
+            hir::TyImplTraitExistential(item_id, _, ref lifetimes) => {
                 // Resolve the lifetimes that are applied to the existential type.
                 // These are resolved in the current scope.
                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
@@ -655,10 +661,13 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                 // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
                 //                          ^            ^ this gets resolved in the scope of
                 //                                         the exist_ty generics
-                let hir::ExistTy {
-                    ref generics,
-                    ref bounds,
-                } = *exist_ty;
+                let (generics, bounds) = match self.tcx.hir.expect_item(item_id.id).node {
+                    hir::ItemExistential(hir::ExistTy{ ref generics, ref bounds, .. }) => (
+                        generics,
+                        bounds,
+                    ),
+                    ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
+                };
 
                 // We want to start our early-bound indices at the end of the parent scope,
                 // not including any parent `impl Trait`s.
@@ -1861,7 +1870,7 @@ fn visit_fn_like_elision(
             .map(|(i, input)| {
                 let mut gather = GatherLifetimes {
                     map: self.map,
-                    outer_index: ty::DebruijnIndex::INNERMOST,
+                    outer_index: ty::INNERMOST,
                     have_bound_regions: false,
                     lifetimes: FxHashSet(),
                 };
index f08b95f59fa3da963a522eb4855047828a906fad..d0ae0bdac8c095327f5d6b621f4115bdeb1e528e 100644 (file)
@@ -123,6 +123,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         let generic_ty = self.tcx().type_of(def_id);
                         let concrete_ty = generic_ty.subst(self.tcx(), substs);
                         self.anon_depth += 1;
+                        if concrete_ty == ty {
+                            println!("generic_ty: {:#?}", generic_ty);
+                            println!("substs {:#?}", substs);
+                        }
+                        assert_ne!(concrete_ty, ty, "infinite recursion");
                         let folded_ty = self.fold_ty(concrete_ty);
                         self.anon_depth -= 1;
                         folded_ty
index 4fb5602971ce993263198bbdc0a18b09e5af9bd8..6cbf4fad02cb9e6a9fe97f0a2234bca6373537a7 100644 (file)
@@ -427,6 +427,10 @@ pub struct TypeckTables<'tcx> {
     /// its where clauses and parameter types. These are then
     /// read-again by borrowck.
     pub free_region_map: FreeRegionMap<'tcx>,
+
+    /// All the existential types that are restricted to concrete types
+    /// by this function
+    pub concrete_existential_types: FxHashMap<DefId, Ty<'tcx>>,
 }
 
 impl<'tcx> TypeckTables<'tcx> {
@@ -449,6 +453,7 @@ pub fn empty(local_id_root: Option<DefId>) -> TypeckTables<'tcx> {
             used_trait_imports: Lrc::new(DefIdSet()),
             tainted_by_errors: false,
             free_region_map: FreeRegionMap::new(),
+            concrete_existential_types: FxHashMap(),
         }
     }
 
@@ -746,6 +751,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             ref used_trait_imports,
             tainted_by_errors,
             ref free_region_map,
+            ref concrete_existential_types,
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
@@ -786,6 +792,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             used_trait_imports.hash_stable(hcx, hasher);
             tainted_by_errors.hash_stable(hcx, hasher);
             free_region_map.hash_stable(hcx, hasher);
+            concrete_existential_types.hash_stable(hcx, hasher);
         })
     }
 }
index ebbdc928b5dda858366847bbf4acd3787407cd41..e3fbadc271206e1cbb1a2224441f32c6203a0cf1 100644 (file)
@@ -24,7 +24,7 @@ impl FlagComputation {
     fn new() -> FlagComputation {
         FlagComputation {
             flags: TypeFlags::empty(),
-            outer_exclusive_binder: ty::DebruijnIndex::INNERMOST,
+            outer_exclusive_binder: ty::INNERMOST,
         }
     }
 
@@ -60,7 +60,7 @@ fn add_bound_computation(&mut self, computation: &FlagComputation) {
         // a region binder, so subtract one from the region depth
         // within when adding the depth to `self`.
         let outer_exclusive_binder = computation.outer_exclusive_binder;
-        if outer_exclusive_binder > ty::DebruijnIndex::INNERMOST {
+        if outer_exclusive_binder > ty::INNERMOST {
             self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
         } else {
             // otherwise, this binder captures nothing
index dea33ca6947fa4a18581697edadd82e798b8e21d..d459a6de0d69e3293b5fbff0562662201c47d1ca 100644 (file)
@@ -65,7 +65,7 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 
     /// True if `self` has any late-bound regions that are either
     /// bound by `binder` or bound by some binder outside of `binder`.
-    /// If `binder` is `ty::DebruijnIndex::INNERMOST`, this indicates whether
+    /// If `binder` is `ty::INNERMOST`, this indicates whether
     /// there are any late-bound regions that appear free.
     fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
         self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder })
@@ -78,7 +78,7 @@ fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
     }
 
     fn has_escaping_regions(&self) -> bool {
-        self.has_regions_bound_at_or_above(ty::DebruijnIndex::INNERMOST)
+        self.has_regions_bound_at_or_above(ty::INNERMOST)
     }
 
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
@@ -246,7 +246,7 @@ pub fn for_each_free_region<T,F>(self,
               T: TypeFoldable<'tcx>,
     {
         value.visit_with(&mut RegionVisitor {
-            outer_index: ty::DebruijnIndex::INNERMOST,
+            outer_index: ty::INNERMOST,
             callback
         });
 
@@ -260,7 +260,7 @@ struct RegionVisitor<F> {
             /// ^          ^          ^     ^
             /// |          |          |     | here, would be shifted in 1
             /// |          |          | here, would be shifted in 2
-            /// |          | here, would be INNTERMOST shifted in by 1
+            /// |          | here, would be INNERMOST shifted in by 1
             /// | here, initially, binder would be INNERMOST
             /// ```
             ///
@@ -333,7 +333,7 @@ pub fn new(
         RegionFolder {
             tcx,
             skipped_regions,
-            current_index: ty::DebruijnIndex::INNERMOST,
+            current_index: ty::INNERMOST,
             fold_region_fn,
         }
     }
@@ -495,7 +495,7 @@ pub fn anonymize_late_bound_regions<T>(self, sig: &Binder<T>) -> Binder<T>
         let mut counter = 0;
         Binder::bind(self.replace_late_bound_regions(sig, |_| {
             counter += 1;
-            self.mk_region(ty::ReLateBound(ty::DebruijnIndex::INNERMOST, ty::BrAnon(counter)))
+            self.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(counter)))
         }).0)
     }
 }
@@ -507,7 +507,7 @@ fn new<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fld_r: &'a mut F)
     {
         RegionReplacer {
             tcx,
-            current_index: ty::DebruijnIndex::INNERMOST,
+            current_index: ty::INNERMOST,
             fld_r,
             map: BTreeMap::default()
         }
@@ -542,7 +542,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                     // that region should always use the INNERMOST
                     // debruijn index. Then we adjust it to the
                     // correct depth.
-                    assert_eq!(debruijn1, ty::DebruijnIndex::INNERMOST);
+                    assert_eq!(debruijn1, ty::INNERMOST);
                     self.tcx.mk_region(ty::ReLateBound(debruijn, br))
                 } else {
                     region
@@ -701,7 +701,7 @@ struct LateBoundRegionsCollector {
 impl LateBoundRegionsCollector {
     fn new(just_constrained: bool) -> Self {
         LateBoundRegionsCollector {
-            current_index: ty::DebruijnIndex::INNERMOST,
+            current_index: ty::INNERMOST,
             regions: FxHashSet(),
             just_constrained,
         }
index 87ace45a905d194865bbb5d604c1c0380274b380..d858ba7acf7863bf1da169566d194b99404db518 100644 (file)
@@ -221,7 +221,8 @@ pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId)
             data @ DefPathData::AnonConst |
             data @ DefPathData::MacroDef(..) |
             data @ DefPathData::ClosureExpr |
-            data @ DefPathData::ImplTrait |
+            data @ DefPathData::ExistentialImplTrait |
+            data @ DefPathData::UniversalImplTrait |
             data @ DefPathData::GlobalMetaData(..) => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
index 2758503c60c9a3b98324521a146a7fe941da8594..4f5f0c9d740cc8c0429b43d1861af779f5a1ec5d 100644 (file)
@@ -44,7 +44,7 @@
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::ops::Deref;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
 use std::slice;
 use std::vec::IntoIter;
 use std::mem;
@@ -60,7 +60,7 @@
 
 use hir;
 
-pub use self::sty::{Binder, CanonicalVar, DebruijnIndex};
+pub use self::sty::{Binder, CanonicalVar, DebruijnIndex, INNERMOST};
 pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
@@ -2436,6 +2436,12 @@ pub fn body_owners(
                 .map(move |&body_id| self.hir.body_owner_def_id(body_id))
     }
 
+    pub fn par_body_owners<F: Fn(DefId) + sync::Sync + sync::Send>(self, f: F) {
+        par_iter(&self.hir.krate().body_ids).for_each(|&body_id| {
+            f(self.hir.body_owner_def_id(body_id))
+        });
+    }
+
     pub fn expr_span(self, id: NodeId) -> Span {
         match self.hir.find(id) {
             Some(hir_map::NodeExpr(e)) => {
@@ -2857,6 +2863,12 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
 fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        def_id: DefId)
                        -> ParamEnv<'tcx> {
+
+    // The param_env of an existential type is its parent's param_env
+    if let Some(Def::Existential(_)) = tcx.describe_def(def_id) {
+        let parent = tcx.parent_def_id(def_id).expect("impl trait item w/o a parent");
+        return param_env(tcx, parent);
+    }
     // Compute the bounds on Self and the type parameters.
 
     let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
index 8afa96bf2dfe39f3ec38e8d82d13d926be23f71d..4a69fbdacc476a006051365189d339bcedc0b329 100644 (file)
@@ -1023,12 +1023,11 @@ pub fn is_self(&self) -> bool {
 /// is the outer fn.
 ///
 /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy, PartialOrd, Ord)]
-pub struct DebruijnIndex {
-    /// We maintain the invariant that this is never 0. So 1 indicates
-    /// the innermost binder.
-    index: u32,
-}
+newtype_index!(DebruijnIndex
+    {
+        DEBUG_FORMAT = "DebruijnIndex({})",
+        const INNERMOST = 0,
+    });
 
 pub type Region<'tcx> = &'tcx RegionKind;
 
@@ -1261,8 +1260,6 @@ pub fn item_def_id(&self) -> DefId {
 }
 
 impl DebruijnIndex {
-    pub const INNERMOST: DebruijnIndex = DebruijnIndex { index: 0 };
-
     /// Returns the resulting index when this value is moved into
     /// `amount` number of new binders. So e.g. if you had
     ///
@@ -1275,7 +1272,7 @@ impl DebruijnIndex {
     /// you would need to shift the index for `'a` into 1 new binder.
     #[must_use]
     pub const fn shifted_in(self, amount: u32) -> DebruijnIndex {
-        DebruijnIndex { index: self.index + amount }
+        DebruijnIndex(self.0 + amount)
     }
 
     /// Update this index in place by shifting it "in" through
@@ -1288,7 +1285,7 @@ pub fn shift_in(&mut self, amount: u32) {
     /// `amount` number of new binders.
     #[must_use]
     pub const fn shifted_out(self, amount: u32) -> DebruijnIndex {
-        DebruijnIndex { index: self.index - amount }
+        DebruijnIndex(self.0 - amount)
     }
 
     /// Update in place by shifting out from `amount` binders.
@@ -1317,13 +1314,11 @@ pub fn shift_out(&mut self, amount: u32) {
     /// bound by one of the binders we are shifting out of, that is an
     /// error (and should fail an assertion failure).
     pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self {
-        self.shifted_out(to_binder.index - Self::INNERMOST.index)
+        self.shifted_out((to_binder.0 - INNERMOST.0) as u32)
     }
 }
 
-impl_stable_hash_for!(struct DebruijnIndex {
-    index
-});
+impl_stable_hash_for!(tuple_struct DebruijnIndex { index });
 
 /// Region utilities
 impl RegionKind {
index 20ebd6206259660c2fa3d90ebb3212ed369240fc..024885420f619f01ceff91ed9e6bfb8efedfc418 100644 (file)
@@ -555,7 +555,7 @@ pub fn closure_env_ty(self,
                           -> Option<ty::Binder<Ty<'tcx>>>
     {
         let closure_ty = self.mk_closure(closure_def_id, closure_substs);
-        let env_region = ty::ReLateBound(ty::DebruijnIndex::INNERMOST, ty::BrEnv);
+        let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
         let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self);
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
         let env_ty = match closure_kind {
index 4e7df0cac128b8215249f82d1d1234abb68936b8..883882dfe6837f22be689cc3c2aa5499fd7ee386 100644 (file)
@@ -291,7 +291,8 @@ fn parameterized<F: fmt::Write>(&mut self,
                     DefPathData::Field(_) |
                     DefPathData::StructCtor |
                     DefPathData::AnonConst |
-                    DefPathData::ImplTrait |
+                    DefPathData::ExistentialImplTrait |
+                    DefPathData::UniversalImplTrait |
                     DefPathData::GlobalMetaData(_) => {
                         // if we're making a symbol for something, there ought
                         // to be a value or type-def or something in there
@@ -526,7 +527,7 @@ fn name_by_region_index(index: usize) -> InternedString {
                     ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID), name)
                 }
             };
-            tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::INNERMOST, br))
+            tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
         }).0;
         start_or_continue(f, "", "> ")?;
 
index 11d35def007747f5493adfcab2b22b0f006f79d0..684fd10c8c652df33fa0f9069c59e05249d52027 100644 (file)
@@ -67,9 +67,9 @@
 pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    for body_owner_def_id in tcx.body_owners() {
+    tcx.par_body_owners(|body_owner_def_id| {
         tcx.borrowck(body_owner_def_id);
-    }
+    });
 }
 
 pub fn provide(providers: &mut Providers) {
index 52a357e1a1d3173c4d7a64327e3efd06af818eef..a5a20af0e4e4ae880558ce2a5bbd653984987c65 100644 (file)
@@ -17,6 +17,8 @@
 #![feature(from_ref)]
 #![feature(quote)]
 
+#![recursion_limit="256"]
+
 #[macro_use] extern crate log;
 extern crate syntax;
 extern crate syntax_pos;
index ab99d1f0f30229d7ba1d181f73c7cfed0115f9d8..7e55642814bbae137443c37989e008cdb0669a8f 100644 (file)
@@ -425,7 +425,7 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             let tcx = cx.tcx;
             let sig = substs.poly_sig(def_id, cx.tcx);
 
-            let env_region = ty::ReLateBound(ty::DebruijnIndex::INNERMOST, ty::BrEnv);
+            let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
             let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
 
             sig.map_bound(|sig| {
index 1fb63afc72fa758ae882ae0905f17aa2c0b27711..ad3710e9536f1af1c401821992c3fec0e23476c0 100644 (file)
@@ -367,6 +367,11 @@ pub fn new() -> Self {
         IndexVec { raw: Vec::new(), _marker: PhantomData }
     }
 
+    #[inline]
+    pub fn from_raw(raw: Vec<T>) -> Self {
+        IndexVec { raw, _marker: PhantomData }
+    }
+
     #[inline]
     pub fn with_capacity(capacity: usize) -> Self {
         IndexVec { raw: Vec::with_capacity(capacity), _marker: PhantomData }
index 33f6eda2a8753696658b61c3951cb5682df09d03..b82fe3ec60c3b6fcc09bb7c72129072dfcafc413 100644 (file)
@@ -26,6 +26,8 @@
 //!
 //! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false.
 //!
+//! `MTRef` is a immutable refernce if cfg!(parallel_queries), and an mutable reference otherwise.
+//!
 //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync
 //! depending on the value of cfg!(parallel_queries).
 
@@ -126,6 +128,8 @@ fn deref(&self) -> &T {
             }
         }
 
+        pub type MTRef<'a, T> = &'a mut T;
+
         #[derive(Debug)]
         pub struct MTLock<T>(T);
 
@@ -151,13 +155,8 @@ pub fn lock(&self) -> &T {
             }
 
             #[inline(always)]
-            pub fn borrow(&self) -> &T {
-                &self.0
-            }
-
-            #[inline(always)]
-            pub fn borrow_mut(&self) -> &T {
-                &self.0
+            pub fn lock_mut(&mut self) -> &mut T {
+                &mut self.0
             }
         }
 
@@ -221,7 +220,37 @@ pub fn take(&self) -> Option<T> {
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
 
-        pub use self::Lock as MTLock;
+        pub type MTRef<'a, T> = &'a T;
+
+        #[derive(Debug)]
+        pub struct MTLock<T>(Lock<T>);
+
+        impl<T> MTLock<T> {
+            #[inline(always)]
+            pub fn new(inner: T) -> Self {
+                MTLock(Lock::new(inner))
+            }
+
+            #[inline(always)]
+            pub fn into_inner(self) -> T {
+                self.0.into_inner()
+            }
+
+            #[inline(always)]
+            pub fn get_mut(&mut self) -> &mut T {
+                self.0.get_mut()
+            }
+
+            #[inline(always)]
+            pub fn lock(&self) -> LockGuard<T> {
+                self.0.lock()
+            }
+
+            #[inline(always)]
+            pub fn lock_mut(&self) -> LockGuard<T> {
+                self.lock()
+            }
+        }
 
         use parking_lot::Mutex as InnerLock;
         use parking_lot::RwLock as InnerRwLock;
index 5d5baf765497ef8b883af96482fbf97e07059eab..c18a089268659e06668c04083748f609239539f9 100644 (file)
@@ -1272,11 +1272,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
 
             time(sess, "borrow checking", || borrowck::check_crate(tcx));
 
-            time(sess, "MIR borrow checking", || {
-                for def_id in tcx.body_owners() {
-                    tcx.mir_borrowck(def_id);
-                }
-            });
+            time(sess,
+                 "MIR borrow checking",
+                 || tcx.par_body_owners(|def_id| { tcx.mir_borrowck(def_id); }));
 
             time(sess, "dumping chalk-like clauses", || {
                 rustc_traits::lowering::dump_program_clauses(tcx);
index 17e0472bda93fbdee39a201266349dba837e3304..9808e289f3b3a4285293a1b887a903517cf7cade 100644 (file)
@@ -183,7 +183,7 @@ fn test_env_with_pool<F>(
     });
 }
 
-const D1: ty::DebruijnIndex = ty::DebruijnIndex::INNERMOST;
+const D1: ty::DebruijnIndex = ty::INNERMOST;
 const D2: ty::DebruijnIndex = D1.shifted_in(1);
 
 impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
@@ -256,6 +256,7 @@ fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<as
                 hir::ItemFn(..) |
                 hir::ItemForeignMod(..) |
                 hir::ItemGlobalAsm(..) |
+                hir::ItemExistential(..) |
                 hir::ItemTy(..) => None,
 
                 hir::ItemEnum(..) |
index ababce69e3170d850e939df33dfefdc3b4039ad6..3839c133a6eb22692d99b1bd8b4597257299c184 100644 (file)
@@ -17,6 +17,8 @@
 #![feature(fs_read_write)]
 #![feature(specialization)]
 
+#![recursion_limit="256"]
+
 extern crate graphviz;
 #[macro_use] extern crate rustc;
 extern crate rustc_data_structures;
index be725b17933215661af70724ba01e6b4c432a7b7..dcef0c662c3a1164ca53bbf87b24fa9f07d68400 100644 (file)
@@ -13,6 +13,7 @@
 use rustc::ty::TyCtxt;
 use rustc::util::common::time;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::join;
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::Encoder;
 use std::io::{self, Cursor};
@@ -33,23 +34,28 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
             return;
         }
 
-        time(sess, "persist query result cache", || {
-            save_in(sess,
-                    query_cache_path(sess),
-                    |e| encode_query_cache(tcx, e));
-        });
+        let query_cache_path = query_cache_path(sess);
+        let dep_graph_path = dep_graph_path(sess);
 
-        if tcx.sess.opts.debugging_opts.incremental_queries {
+        join(move || {
+            if tcx.sess.opts.debugging_opts.incremental_queries {
+                time(sess, "persist query result cache", || {
+                    save_in(sess,
+                            query_cache_path,
+                            |e| encode_query_cache(tcx, e));
+                });
+            }
+        }, || {
             time(sess, "persist dep-graph", || {
                 save_in(sess,
-                        dep_graph_path(sess),
+                        dep_graph_path,
                         |e| {
                             time(sess, "encode dep-graph", || {
                                 encode_dep_graph(tcx, e)
                             })
                         });
             });
-        }
+        });
 
         dirty_clean::check_dirty_clean_annotations(tcx);
     })
index fd00cde375b90054fcef50854f0509f1102ba581..9e4f695d28fd482b776398388bf47eec2eab2328 100644 (file)
@@ -419,6 +419,7 @@ fn to_def(&self, did: DefId) -> Option<Def> {
             EntryKind::ForeignFn(_) => Def::Fn(did),
             EntryKind::Method(_) => Def::Method(did),
             EntryKind::Type => Def::TyAlias(did),
+            EntryKind::Existential => Def::Existential(did),
             EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
             EntryKind::Mod(_) => Def::Mod(did),
             EntryKind::Variant(_) => Def::Variant(did),
index ab30ff7f072b7f065e4e631dd1fee02982e5b7d9..33d4df1c3a5dc2b37984615144fc81cd22ba15fa 100644 (file)
@@ -1060,6 +1060,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
             hir::ItemForeignMod(_) => EntryKind::ForeignMod,
             hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
             hir::ItemTy(..) => EntryKind::Type,
+            hir::ItemExistential(..) => EntryKind::Existential,
             hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
             hir::ItemStruct(ref struct_def, _) => {
                 let variant = tcx.adt_def(def_id).non_enum_variant();
@@ -1187,6 +1188,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemConst(..) |
                 hir::ItemFn(..) |
                 hir::ItemTy(..) |
+                hir::ItemExistential(..) |
                 hir::ItemEnum(..) |
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
@@ -1210,6 +1212,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
                 hir::ItemImpl(..) |
+                hir::ItemExistential(..) |
                 hir::ItemTrait(..) => Some(self.encode_generics(def_id)),
                 _ => None,
             },
@@ -1222,6 +1225,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
                 hir::ItemImpl(..) |
+                hir::ItemExistential(..) |
                 hir::ItemTrait(..) => Some(self.encode_predicates(def_id)),
                 _ => None,
             },
@@ -1301,28 +1305,6 @@ fn encode_info_for_ty_param(&mut self,
         }
     }
 
-    fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_anon_ty({:?})", def_id);
-        let tcx = self.tcx;
-        Entry {
-            kind: EntryKind::Type,
-            visibility: self.lazy(&ty::Visibility::Public),
-            span: self.lazy(&tcx.def_span(def_id)),
-            attributes: LazySeq::empty(),
-            children: LazySeq::empty(),
-            stability: None,
-            deprecation: None,
-
-            ty: Some(self.encode_item_type(def_id)),
-            inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
-            generics: Some(self.encode_generics(def_id)),
-            predicates: Some(self.encode_predicates(def_id)),
-
-            mir: None,
-        }
-    }
-
     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
         let tcx = self.tcx;
@@ -1672,10 +1654,6 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
 
     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         match ty.node {
-            hir::TyImplTraitExistential(..) => {
-                let def_id = self.tcx.hir.local_def_id(ty.id);
-                self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
-            }
             hir::TyArray(_, ref length) => {
                 let def_id = self.tcx.hir.local_def_id(length.id);
                 self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
@@ -1710,6 +1688,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
             hir::ItemExternCrate(..) |
             hir::ItemUse(..) |
             hir::ItemTy(..) |
+            hir::ItemExistential(..) |
             hir::ItemTraitAlias(..) => {
                 // no sub-item recording needed in these cases
             }
index 2e89ea6d2c1213bc7899cd49300738b6c4246245..21d6d15457aa0252a4ac51f14e6f61af78e3b913 100644 (file)
@@ -304,6 +304,7 @@ pub enum EntryKind<'tcx> {
     ForeignType,
     GlobalAsm,
     Type,
+    Existential,
     Enum(ReprOptions),
     Field,
     Variant(Lazy<VariantData<'tcx>>),
@@ -336,6 +337,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             EntryKind::GlobalAsm        |
             EntryKind::ForeignType      |
             EntryKind::Field |
+            EntryKind::Existential |
             EntryKind::Type => {
                 // Nothing else to hash here.
             }
index 4f87a2b30ae843bae1587d3a75e91631edc5ffb0..72db9f8da987251f1e69bf71da2de0167349b1d2 100644 (file)
@@ -11,6 +11,8 @@
 use borrow_check::borrow_set::BorrowSet;
 use borrow_check::location::LocationTable;
 use borrow_check::nll::facts::AllFacts;
+use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
+use borrow_check::nll::ToRegionVid;
 use rustc::hir;
 use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
@@ -21,9 +23,7 @@
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts};
-
-use super::region_infer::{Cause, RegionInferenceContext};
-use super::ToRegionVid;
+use std::iter;
 
 pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
@@ -32,6 +32,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     location_table: &LocationTable,
     mir: &Mir<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
+    liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)],
 ) {
     let mut cg = ConstraintGeneration {
         borrow_set,
@@ -42,6 +43,8 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
         mir,
     };
 
+    cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
+
     for (bb, data) in mir.basic_blocks().iter_enumerated() {
         cg.visit_basic_block_data(bb, data);
     }
@@ -209,7 +212,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                 self.add_reborrow_constraint(location, region, borrowed_place);
             }
 
-            _ => { }
+            _ => {}
         }
 
         self.super_rvalue(rvalue, location);
@@ -225,6 +228,42 @@ fn visit_user_assert_ty(
 }
 
 impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
+    /// The MIR type checker generates region liveness constraints
+    /// that we also have to respect.
+    fn add_region_liveness_constraints_from_type_check(
+        &mut self,
+        liveness_set: &[(ty::Region<'tcx>, Location, Cause)],
+    ) {
+        debug!(
+            "add_region_liveness_constraints_from_type_check(liveness_set={} items)",
+            liveness_set.len(),
+        );
+
+        let ConstraintGeneration {
+            regioncx,
+            location_table,
+            all_facts,
+            ..
+        } = self;
+
+        for (region, location, cause) in liveness_set {
+            debug!("generate: {:#?} is live at {:#?}", region, location);
+            let region_vid = regioncx.to_region_vid(region);
+            regioncx.add_live_point(region_vid, *location, &cause);
+        }
+
+        if let Some(all_facts) = all_facts {
+            all_facts
+                .region_live_at
+                .extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
+                    let r = regioncx.to_region_vid(region);
+                    let p1 = location_table.start_index(*location);
+                    let p2 = location_table.mid_index(*location);
+                    iter::once((r, p1)).chain(iter::once((r, p2)))
+                }));
+        }
+    }
+
     /// Some variable with type `live_ty` is "regular live" at
     /// `location` -- i.e., it may be used later. This means that all
     /// regions appearing in the type `live_ty` must be live at
index c3d9dd8378d4a80c7a4f228411356838026d5ed0..dcb52a3b18a724cf2829b9a5653471815ea2625d 100644 (file)
@@ -11,6 +11,7 @@
 use borrow_check::borrow_set::BorrowSet;
 use borrow_check::location::{LocationIndex, LocationTable};
 use borrow_check::nll::facts::AllFactsExt;
+use borrow_check::nll::type_check::MirTypeckRegionConstraints;
 use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
@@ -41,7 +42,6 @@
 mod invalidation;
 crate mod region_infer;
 mod renumber;
-mod subtype_constraint_generation;
 crate mod type_check;
 mod universal_regions;
 
@@ -91,46 +91,53 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     Option<Rc<Output<RegionVid, BorrowIndex, LocationIndex>>>,
     Option<ClosureRegionRequirements<'gcx>>,
 ) {
+    let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts
+        || infcx.tcx.sess.opts.debugging_opts.polonius
+    {
+        Some(AllFacts::default())
+    } else {
+        None
+    };
+
     // Run the MIR type-checker.
     let liveness = &LivenessResults::compute(mir);
-    let constraint_sets = &type_check::type_check(
+    let constraint_sets = type_check::type_check(
         infcx,
         param_env,
         mir,
         def_id,
         &universal_regions,
+        location_table,
         &liveness,
+        &mut all_facts,
         flow_inits,
         move_data,
     );
 
-    let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts
-        || infcx.tcx.sess.opts.debugging_opts.polonius
-    {
-        Some(AllFacts::default())
-    } else {
-        None
-    };
-
     if let Some(all_facts) = &mut all_facts {
         all_facts
             .universal_region
             .extend(universal_regions.universal_regions());
     }
 
-    // Create the region inference context, taking ownership of the region inference
-    // data that was contained in `infcx`.
+    // Create the region inference context, taking ownership of the
+    // region inference data that was contained in `infcx`, and the
+    // base constraints generated by the type-check.
     let var_origins = infcx.take_region_var_origins();
-    let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir);
-
-    // Generate various constraints.
-    subtype_constraint_generation::generate(
-        &mut regioncx,
-        &mut all_facts,
-        location_table,
+    let MirTypeckRegionConstraints {
+        liveness_set,
+        outlives_constraints,
+        type_tests,
+    } = constraint_sets;
+    let mut regioncx = RegionInferenceContext::new(
+        var_origins,
+        universal_regions,
         mir,
-        constraint_sets,
+        outlives_constraints,
+        type_tests,
     );
+
+    // Generate various additional constraints.
     constraint_generation::generate_constraints(
         infcx,
         &mut regioncx,
@@ -138,6 +145,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         location_table,
         &mir,
         borrow_set,
+        &liveness_set,
     );
     invalidation::generate_invalidates(
         infcx,
index b0346abee5a5fbe83c67aee6fab39a668ecdb453..6c796ea4c73abe66195dd0d9e533e9ff2bf2721e 100644 (file)
@@ -14,7 +14,7 @@
 //! context internal state.
 
 use std::io::{self, Write};
-use super::{Constraint, RegionInferenceContext};
+use super::{OutlivesConstraint, RegionInferenceContext};
 
 // Room for "'_#NNNNr" before things get misaligned.
 // Easy enough to fix if this ever doesn't seem like
@@ -79,7 +79,7 @@ fn for_each_constraint(
         let mut constraints: Vec<_> = self.constraints.iter().collect();
         constraints.sort();
         for constraint in &constraints {
-            let Constraint {
+            let OutlivesConstraint {
                 sup,
                 sub,
                 point,
index 6c4c02a36a0d73c3e0205145bccf8f0be1820542..c02e4ff315687f54ef59bf1790d24656c9974309 100644 (file)
@@ -27,7 +27,7 @@ pub(crate) fn dump_graphviz(&self, mut w: &mut dyn Write) -> io::Result<()> {
 
 impl<'this, 'tcx> dot::Labeller<'this> for RegionInferenceContext<'tcx> {
     type Node = RegionVid;
-    type Edge = Constraint;
+    type Edge = OutlivesConstraint;
 
     fn graph_id(&'this self) -> dot::Id<'this> {
         dot::Id::new(format!("RegionInferenceContext")).unwrap()
@@ -41,31 +41,31 @@ fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
     fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
         dot::LabelText::LabelStr(format!("{:?}", n).into_cow())
     }
-    fn edge_label(&'this self, e: &Constraint) -> dot::LabelText<'this> {
+    fn edge_label(&'this self, e: &OutlivesConstraint) -> dot::LabelText<'this> {
         dot::LabelText::LabelStr(format!("{:?}", e.point).into_cow())
     }
 }
 
 impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> {
     type Node = RegionVid;
-    type Edge = Constraint;
+    type Edge = OutlivesConstraint;
 
     fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
         let vids: Vec<RegionVid> = self.definitions.indices().collect();
         vids.into_cow()
     }
-    fn edges(&'this self) -> dot::Edges<'this, Constraint> {
+    fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
         (&self.constraints.raw[..]).into_cow()
     }
 
     // Render `a: b` as `a <- b`, indicating the flow
     // of data during inference.
 
-    fn source(&'this self, edge: &Constraint) -> RegionVid {
+    fn source(&'this self, edge: &OutlivesConstraint) -> RegionVid {
         edge.sub
     }
 
-    fn target(&'this self, edge: &Constraint) -> RegionVid {
+    fn target(&'this self, edge: &OutlivesConstraint) -> RegionVid {
         edge.sup
     }
 }
index dea2683789bdfb81729890c3b761a2947766b5fd..0eeacda467e03336ceac4d643d01beeae507ba7d 100644 (file)
@@ -68,7 +68,7 @@ pub struct RegionInferenceContext<'tcx> {
     dependency_map: Option<IndexVec<RegionVid, Option<ConstraintIndex>>>,
 
     /// The constraints we have accumulated and used during solving.
-    constraints: IndexVec<ConstraintIndex, Constraint>,
+    constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
 
     /// Type constraints that we check after solving.
     type_tests: Vec<TypeTest<'tcx>>,
@@ -118,19 +118,19 @@ pub(crate) enum Cause {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Constraint {
+pub struct OutlivesConstraint {
     // NB. The ordering here is not significant for correctness, but
     // it is for convenience. Before we dump the constraints in the
     // debugging logs, we sort them, and we'd like the "super region"
     // to be first, etc. (In particular, span should remain last.)
     /// The region SUP must outlive SUB...
-    sup: RegionVid,
+    pub sup: RegionVid,
 
     /// Region that must be outlived.
-    sub: RegionVid,
+    pub sub: RegionVid,
 
     /// At this location.
-    point: Location,
+    pub point: Location,
 
     /// Later on, we thread the constraints onto a linked list
     /// grouped by their `sub` field. So if you had:
@@ -140,10 +140,10 @@ pub struct Constraint {
     /// 0     | `'a: 'b`   | Some(2)
     /// 1     | `'b: 'c`   | None
     /// 2     | `'c: 'b`   | None
-    next: Option<ConstraintIndex>,
+    pub next: Option<ConstraintIndex>,
 
     /// Where did this constraint arise?
-    span: Span,
+    pub span: Span,
 }
 
 newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" });
@@ -239,11 +239,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// `num_region_variables` valid inference variables; the first N
     /// of those will be constant regions representing the free
     /// regions defined in `universal_regions`.
+    ///
+    /// The `outlives_constraints` and `type_tests` are an initial set
+    /// of constraints produced by the MIR type check.
     pub(crate) fn new(
         var_infos: VarInfos,
         universal_regions: UniversalRegions<'tcx>,
         mir: &Mir<'tcx>,
+        outlives_constraints: Vec<OutlivesConstraint>,
+        type_tests: Vec<TypeTest<'tcx>>,
     ) -> Self {
+        // The `next` field should not yet have been initialized:
+        debug_assert!(outlives_constraints.iter().all(|c| c.next.is_none()));
+
         let num_region_variables = var_infos.len();
         let num_universal_regions = universal_regions.len();
 
@@ -261,8 +269,8 @@ pub(crate) fn new(
             liveness_constraints: RegionValues::new(elements, num_region_variables),
             inferred_values: None,
             dependency_map: None,
-            constraints: IndexVec::new(),
-            type_tests: Vec::new(),
+            constraints: IndexVec::from_raw(outlives_constraints),
+            type_tests,
             universal_regions,
         };
 
@@ -345,7 +353,8 @@ pub fn region_contains_point<R>(&self, r: R, p: Location) -> bool
     where
         R: ToRegionVid,
     {
-        let inferred_values = self.inferred_values
+        let inferred_values = self
+            .inferred_values
             .as_ref()
             .expect("region values not yet inferred");
         inferred_values.contains(r.to_region_vid(), p)
@@ -353,7 +362,8 @@ pub fn region_contains_point<R>(&self, r: R, p: Location) -> bool
 
     /// Returns access to the value of `r` for debugging purposes.
     crate fn region_value_str(&self, r: RegionVid) -> String {
-        let inferred_values = self.inferred_values
+        let inferred_values = self
+            .inferred_values
             .as_ref()
             .expect("region values not yet inferred");
 
@@ -387,7 +397,7 @@ pub(super) fn add_outlives(
     ) {
         debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
         assert!(self.inferred_values.is_none(), "values already inferred");
-        self.constraints.push(Constraint {
+        self.constraints.push(OutlivesConstraint {
             span,
             sup,
             sub,
@@ -396,11 +406,6 @@ pub(super) fn add_outlives(
         });
     }
 
-    /// Add a "type test" that must be satisfied.
-    pub(super) fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
-        self.type_tests.push(type_test);
-    }
-
     /// Perform region inference and report errors if we see any
     /// unsatisfiable constraints. If this is a closure, returns the
     /// region requirements to propagate to our creator, if any.
@@ -465,7 +470,6 @@ fn propagate_constraints(&mut self, mir: &Mir<'tcx>) {
         self.inferred_values = Some(inferred_values);
     }
 
-    #[inline(never)] // ensure dfs is identifiable in profiles
     fn compute_region_values(&self, _mir: &Mir<'tcx>) -> RegionValues {
         debug!("compute_region_values()");
         debug!("compute_region_values: constraints={:#?}", {
@@ -516,7 +520,6 @@ fn compute_region_values(&self, _mir: &Mir<'tcx>) -> RegionValues {
     /// indices of constraints that need to be re-evaluated when X changes.
     /// These are constraints like Y: X @ P -- so if X changed, we may
     /// need to grow Y.
-    #[inline(never)] // ensure dfs is identifiable in profiles
     fn build_dependency_map(&mut self) -> IndexVec<RegionVid, Option<ConstraintIndex>> {
         let mut map = IndexVec::from_elem(None, &self.definitions);
 
@@ -595,7 +598,8 @@ pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
         if self.universal_regions.is_universal_region(r) {
             return self.definitions[r].external_name;
         } else {
-            let inferred_values = self.inferred_values
+            let inferred_values = self
+                .inferred_values
                 .as_ref()
                 .expect("region values not yet inferred");
             let upper_bound = self.universal_upper_bound(r);
@@ -634,8 +638,11 @@ fn try_promote_type_test<'gcx>(
         // region, which ensures it can be encoded in a `ClosureOutlivesRequirement`.
         let lower_bound_plus = self.non_local_universal_upper_bound(*lower_bound);
         assert!(self.universal_regions.is_universal_region(lower_bound_plus));
-        assert!(!self.universal_regions
-            .is_local_free_region(lower_bound_plus));
+        assert!(
+            !self
+                .universal_regions
+                .is_local_free_region(lower_bound_plus)
+        );
 
         propagated_outlives_requirements.push(ClosureOutlivesRequirement {
             subject,
@@ -663,7 +670,8 @@ fn try_promote_type_test_subject<'gcx>(
     ) -> Option<ClosureOutlivesSubject<'gcx>> {
         let tcx = infcx.tcx;
         let gcx = tcx.global_tcx();
-        let inferred_values = self.inferred_values
+        let inferred_values = self
+            .inferred_values
             .as_ref()
             .expect("region values not yet inferred");
 
@@ -844,7 +852,8 @@ fn eval_outlives(
             sup_region, sub_region, point
         );
 
-        let inferred_values = self.inferred_values
+        let inferred_values = self
+            .inferred_values
             .as_ref()
             .expect("values for regions not yet inferred");
 
@@ -911,7 +920,8 @@ fn check_universal_regions<'gcx>(
     ) {
         // The universal regions are always found in a prefix of the
         // full list.
-        let universal_definitions = self.definitions
+        let universal_definitions = self
+            .definitions
             .iter_enumerated()
             .take_while(|(_, fr_definition)| fr_definition.is_universal);
 
@@ -1139,7 +1149,7 @@ fn new(origin: RegionVariableOrigin) -> Self {
     }
 }
 
-impl fmt::Debug for Constraint {
+impl fmt::Debug for OutlivesConstraint {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(
             formatter,
diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
deleted file mode 100644 (file)
index 9db1908..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2017 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 borrow_check::location::LocationTable;
-use borrow_check::nll::facts::AllFacts;
-use rustc::infer::region_constraints::Constraint;
-use rustc::infer::region_constraints::RegionConstraintData;
-use rustc::infer::region_constraints::{Verify, VerifyBound};
-use rustc::mir::{Location, Mir};
-use rustc::ty;
-use std::iter;
-use syntax::codemap::Span;
-
-use super::region_infer::{RegionInferenceContext, RegionTest, TypeTest};
-use super::type_check::Locations;
-use super::type_check::MirTypeckRegionConstraints;
-use super::type_check::OutlivesSet;
-
-/// When the MIR type-checker executes, it validates all the types in
-/// the MIR, and in the process generates a set of constraints that
-/// must hold regarding the regions in the MIR, along with locations
-/// *where* they must hold. This code takes those constriants and adds
-/// them into the NLL `RegionInferenceContext`.
-pub(super) fn generate<'tcx>(
-    regioncx: &mut RegionInferenceContext<'tcx>,
-    all_facts: &mut Option<AllFacts>,
-    location_table: &LocationTable,
-    mir: &Mir<'tcx>,
-    constraints: &MirTypeckRegionConstraints<'tcx>,
-) {
-    SubtypeConstraintGenerator {
-        regioncx,
-        location_table,
-        mir,
-    }.generate(constraints, all_facts);
-}
-
-struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> {
-    regioncx: &'cx mut RegionInferenceContext<'tcx>,
-    location_table: &'cx LocationTable,
-    mir: &'cx Mir<'tcx>,
-}
-
-impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
-    fn generate(
-        &mut self,
-        constraints: &MirTypeckRegionConstraints<'tcx>,
-        all_facts: &mut Option<AllFacts>,
-    ) {
-        let MirTypeckRegionConstraints {
-            liveness_set,
-            outlives_sets,
-        } = constraints;
-
-        debug!(
-            "generate(liveness_set={} items, outlives_sets={} items)",
-            liveness_set.len(),
-            outlives_sets.len()
-        );
-
-        for (region, location, cause) in liveness_set {
-            debug!("generate: {:#?} is live at {:#?}", region, location);
-            let region_vid = self.to_region_vid(region);
-            self.regioncx.add_live_point(region_vid, *location, &cause);
-        }
-
-        if let Some(all_facts) = all_facts {
-            all_facts
-                .region_live_at
-                .extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
-                    let r = self.to_region_vid(region);
-                    let p1 = self.location_table.start_index(*location);
-                    let p2 = self.location_table.mid_index(*location);
-                    iter::once((r, p1)).chain(iter::once((r, p2)))
-                }));
-        }
-
-        for OutlivesSet { locations, data } in outlives_sets {
-            debug!("generate: constraints at: {:#?}", locations);
-            let RegionConstraintData {
-                constraints,
-                verifys,
-                givens,
-            } = data;
-
-            let span = self.mir
-                .source_info(locations.from_location().unwrap_or(Location::START))
-                .span;
-
-            let at_location = locations.at_location().unwrap_or(Location::START);
-
-            for constraint in constraints.keys() {
-                debug!("generate: constraint: {:?}", constraint);
-                let (a_vid, b_vid) = match constraint {
-                    Constraint::VarSubVar(a_vid, b_vid) => (*a_vid, *b_vid),
-                    Constraint::RegSubVar(a_r, b_vid) => (self.to_region_vid(a_r), *b_vid),
-                    Constraint::VarSubReg(a_vid, b_r) => (*a_vid, self.to_region_vid(b_r)),
-                    Constraint::RegSubReg(a_r, b_r) => {
-                        (self.to_region_vid(a_r), self.to_region_vid(b_r))
-                    }
-                };
-
-                // We have the constraint that `a_vid <= b_vid`. Add
-                // `b_vid: a_vid` to our region checker. Note that we
-                // reverse direction, because `regioncx` talks about
-                // "outlives" (`>=`) whereas the region constraints
-                // talk about `<=`.
-                self.regioncx.add_outlives(span, b_vid, a_vid, at_location);
-
-                // In the new analysis, all outlives relations etc
-                // "take effect" at the mid point of the statement
-                // that requires them, so ignore the `at_location`.
-                if let Some(all_facts) = all_facts {
-                    if let Some(from_location) = locations.from_location() {
-                        all_facts.outlives.push((
-                            b_vid,
-                            a_vid,
-                            self.location_table.mid_index(from_location),
-                        ));
-                    } else {
-                        for location in self.location_table.all_points() {
-                            all_facts.outlives.push((b_vid, a_vid, location));
-                        }
-                    }
-                }
-            }
-
-            for verify in verifys {
-                let type_test = self.verify_to_type_test(verify, span, locations);
-                self.regioncx.add_type_test(type_test);
-            }
-
-            assert!(
-                givens.is_empty(),
-                "MIR type-checker does not use givens (thank goodness)"
-            );
-        }
-    }
-
-    fn verify_to_type_test(
-        &self,
-        verify: &Verify<'tcx>,
-        span: Span,
-        locations: &Locations,
-    ) -> TypeTest<'tcx> {
-        let generic_kind = verify.kind;
-
-        let lower_bound = self.to_region_vid(verify.region);
-
-        let point = locations.at_location().unwrap_or(Location::START);
-
-        let test = self.verify_bound_to_region_test(&verify.bound);
-
-        TypeTest {
-            generic_kind,
-            lower_bound,
-            point,
-            span,
-            test,
-        }
-    }
-
-    fn verify_bound_to_region_test(&self, verify_bound: &VerifyBound<'tcx>) -> RegionTest {
-        match verify_bound {
-            VerifyBound::AnyRegion(regions) => RegionTest::IsOutlivedByAnyRegionIn(
-                regions.iter().map(|r| self.to_region_vid(r)).collect(),
-            ),
-
-            VerifyBound::AllRegions(regions) => RegionTest::IsOutlivedByAllRegionsIn(
-                regions.iter().map(|r| self.to_region_vid(r)).collect(),
-            ),
-
-            VerifyBound::AnyBound(bounds) => RegionTest::Any(
-                bounds
-                    .iter()
-                    .map(|b| self.verify_bound_to_region_test(b))
-                    .collect(),
-            ),
-
-            VerifyBound::AllBounds(bounds) => RegionTest::All(
-                bounds
-                    .iter()
-                    .map(|b| self.verify_bound_to_region_test(b))
-                    .collect(),
-            ),
-        }
-    }
-
-    fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
-        self.regioncx.to_region_vid(r)
-    }
-}
diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
new file mode 100644 (file)
index 0000000..06aaf68
--- /dev/null
@@ -0,0 +1,190 @@
+// Copyright 2017 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 borrow_check::location::LocationTable;
+use borrow_check::nll::facts::AllFacts;
+use borrow_check::nll::region_infer::{OutlivesConstraint, RegionTest, TypeTest};
+use borrow_check::nll::type_check::Locations;
+use borrow_check::nll::universal_regions::UniversalRegions;
+use rustc::infer::region_constraints::Constraint;
+use rustc::infer::region_constraints::RegionConstraintData;
+use rustc::infer::region_constraints::{Verify, VerifyBound};
+use rustc::mir::{Location, Mir};
+use rustc::ty;
+use syntax::codemap::Span;
+
+crate struct ConstraintConversion<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+    universal_regions: &'a UniversalRegions<'tcx>,
+    location_table: &'a LocationTable,
+    outlives_constraints: &'a mut Vec<OutlivesConstraint>,
+    type_tests: &'a mut Vec<TypeTest<'tcx>>,
+    all_facts: &'a mut Option<AllFacts>,
+
+}
+
+impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
+    crate fn new(
+        mir: &'a Mir<'tcx>,
+        universal_regions: &'a UniversalRegions<'tcx>,
+        location_table: &'a LocationTable,
+        outlives_constraints: &'a mut Vec<OutlivesConstraint>,
+        type_tests: &'a mut Vec<TypeTest<'tcx>>,
+        all_facts: &'a mut Option<AllFacts>,
+    ) -> Self {
+        Self {
+            mir,
+            universal_regions,
+            location_table,
+            outlives_constraints,
+            type_tests,
+            all_facts,
+        }
+    }
+
+    crate fn convert(
+        &mut self,
+        locations: Locations,
+        data: &RegionConstraintData<'tcx>,
+    ) {
+        debug!("generate: constraints at: {:#?}", locations);
+        let RegionConstraintData {
+            constraints,
+            verifys,
+            givens,
+        } = data;
+
+        let span = self
+            .mir
+            .source_info(locations.from_location().unwrap_or(Location::START))
+            .span;
+
+        let at_location = locations.at_location().unwrap_or(Location::START);
+
+        for constraint in constraints.keys() {
+            debug!("generate: constraint: {:?}", constraint);
+            let (a_vid, b_vid) = match constraint {
+                Constraint::VarSubVar(a_vid, b_vid) => (*a_vid, *b_vid),
+                Constraint::RegSubVar(a_r, b_vid) => (self.to_region_vid(a_r), *b_vid),
+                Constraint::VarSubReg(a_vid, b_r) => (*a_vid, self.to_region_vid(b_r)),
+                Constraint::RegSubReg(a_r, b_r) => {
+                    (self.to_region_vid(a_r), self.to_region_vid(b_r))
+                }
+            };
+
+            // We have the constraint that `a_vid <= b_vid`. Add
+            // `b_vid: a_vid` to our region checker. Note that we
+            // reverse direction, because `regioncx` talks about
+            // "outlives" (`>=`) whereas the region constraints
+            // talk about `<=`.
+            self.add_outlives(span, b_vid, a_vid, at_location);
+
+            // In the new analysis, all outlives relations etc
+            // "take effect" at the mid point of the statement
+            // that requires them, so ignore the `at_location`.
+            if let Some(all_facts) = &mut self.all_facts {
+                if let Some(from_location) = locations.from_location() {
+                    all_facts.outlives.push((
+                        b_vid,
+                        a_vid,
+                        self.location_table.mid_index(from_location),
+                    ));
+                } else {
+                    for location in self.location_table.all_points() {
+                        all_facts.outlives.push((b_vid, a_vid, location));
+                    }
+                }
+            }
+        }
+
+        for verify in verifys {
+            let type_test = self.verify_to_type_test(verify, span, locations);
+            self.add_type_test(type_test);
+        }
+
+        assert!(
+            givens.is_empty(),
+            "MIR type-checker does not use givens (thank goodness)"
+        );
+    }
+
+    fn verify_to_type_test(
+        &self,
+        verify: &Verify<'tcx>,
+        span: Span,
+        locations: Locations,
+    ) -> TypeTest<'tcx> {
+        let generic_kind = verify.kind;
+
+        let lower_bound = self.to_region_vid(verify.region);
+
+        let point = locations.at_location().unwrap_or(Location::START);
+
+        let test = self.verify_bound_to_region_test(&verify.bound);
+
+        TypeTest {
+            generic_kind,
+            lower_bound,
+            point,
+            span,
+            test,
+        }
+    }
+
+    fn verify_bound_to_region_test(&self, verify_bound: &VerifyBound<'tcx>) -> RegionTest {
+        match verify_bound {
+            VerifyBound::AnyRegion(regions) => RegionTest::IsOutlivedByAnyRegionIn(
+                regions.iter().map(|r| self.to_region_vid(r)).collect(),
+            ),
+
+            VerifyBound::AllRegions(regions) => RegionTest::IsOutlivedByAllRegionsIn(
+                regions.iter().map(|r| self.to_region_vid(r)).collect(),
+            ),
+
+            VerifyBound::AnyBound(bounds) => RegionTest::Any(
+                bounds
+                    .iter()
+                    .map(|b| self.verify_bound_to_region_test(b))
+                    .collect(),
+            ),
+
+            VerifyBound::AllBounds(bounds) => RegionTest::All(
+                bounds
+                    .iter()
+                    .map(|b| self.verify_bound_to_region_test(b))
+                    .collect(),
+            ),
+        }
+    }
+
+    fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
+        self.universal_regions.to_region_vid(r)
+    }
+
+    fn add_outlives(
+        &mut self,
+        span: Span,
+        sup: ty::RegionVid,
+        sub: ty::RegionVid,
+        point: Location,
+    ) {
+        self.outlives_constraints.push(OutlivesConstraint {
+            span,
+            sub,
+            sup,
+            point,
+            next: None,
+        });
+    }
+
+    fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
+        self.type_tests.push(type_test);
+    }
+}
index 2b1878c33e90b78f877672427d6c7f6703fae1de..d44eed65201cd91112c3ed96ffd607a9a6b8875f 100644 (file)
 use borrow_check::nll::universal_regions::UniversalRegions;
 use rustc::hir::def_id::DefId;
 use rustc::infer::InferOk;
-use rustc::ty::Ty;
-use rustc::ty::subst::Subst;
-use rustc::mir::*;
 use rustc::mir::visit::TyContext;
-use rustc::traits::PredicateObligations;
+use rustc::mir::*;
+use rustc::traits::{ObligationCause, PredicateObligations};
+use rustc::ty::subst::Subst;
+use rustc::ty::Ty;
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -56,8 +56,8 @@ pub(super) fn equate_inputs_and_outputs(
         }
 
         assert!(
-            mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
-            mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
+            mir.yield_ty.is_some() && universal_regions.yield_ty.is_some()
+                || mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
         );
         if let Some(mir_yield_ty) = mir.yield_ty {
             let ur_yield_ty = universal_regions.yield_ty.unwrap();
@@ -76,57 +76,67 @@ pub(super) fn equate_inputs_and_outputs(
             output_ty
         );
         let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
-        let anon_type_map = self.fully_perform_op(Locations::All, |cx| {
-            let mut obligations = ObligationAccumulator::default();
-
-            let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types(
-                mir_def_id,
-                cx.body_id,
-                cx.param_env,
-                &output_ty,
-            ));
-            debug!(
-                "equate_inputs_and_outputs: instantiated output_ty={:?}",
-                output_ty
-            );
-            debug!(
-                "equate_inputs_and_outputs: anon_type_map={:#?}",
-                anon_type_map
-            );
-
-            debug!(
-                "equate_inputs_and_outputs: mir_output_ty={:?}",
-                mir_output_ty
-            );
-            obligations.add(infcx
-                .at(&cx.misc(cx.last_span), cx.param_env)
-                .eq(output_ty, mir_output_ty)?);
-
-            for (&anon_def_id, anon_decl) in &anon_type_map {
-                let anon_defn_ty = tcx.type_of(anon_def_id);
-                let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs);
-                let anon_defn_ty = renumber::renumber_regions(
-                    cx.infcx,
-                    TyContext::Location(Location::START),
-                    &anon_defn_ty,
-                );
-                debug!(
-                    "equate_inputs_and_outputs: concrete_ty={:?}",
-                    anon_decl.concrete_ty
-                );
-                debug!("equate_inputs_and_outputs: anon_defn_ty={:?}", anon_defn_ty);
-                obligations.add(infcx
-                    .at(&cx.misc(cx.last_span), cx.param_env)
-                    .eq(anon_decl.concrete_ty, anon_defn_ty)?);
-            }
-
-            debug!("equate_inputs_and_outputs: equated");
-
-            Ok(InferOk {
-                value: Some(anon_type_map),
-                obligations: obligations.into_vec(),
-            })
-        }).unwrap_or_else(|terr| {
+        let anon_type_map =
+            self.fully_perform_op(
+                Locations::All,
+                || format!("input_output"),
+                |cx| {
+                    let mut obligations = ObligationAccumulator::default();
+
+                    let dummy_body_id = ObligationCause::dummy().body_id;
+                    let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types(
+                        mir_def_id,
+                        dummy_body_id,
+                        cx.param_env,
+                        &output_ty,
+                    ));
+                    debug!(
+                        "equate_inputs_and_outputs: instantiated output_ty={:?}",
+                        output_ty
+                    );
+                    debug!(
+                        "equate_inputs_and_outputs: anon_type_map={:#?}",
+                        anon_type_map
+                    );
+
+                    debug!(
+                        "equate_inputs_and_outputs: mir_output_ty={:?}",
+                        mir_output_ty
+                    );
+                    obligations.add(
+                        infcx
+                            .at(&ObligationCause::dummy(), cx.param_env)
+                            .eq(output_ty, mir_output_ty)?,
+                    );
+
+                    for (&anon_def_id, anon_decl) in &anon_type_map {
+                        let anon_defn_ty = tcx.type_of(anon_def_id);
+                        let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs);
+                        let anon_defn_ty = renumber::renumber_regions(
+                            cx.infcx,
+                            TyContext::Location(Location::START),
+                            &anon_defn_ty,
+                        );
+                        debug!(
+                            "equate_inputs_and_outputs: concrete_ty={:?}",
+                            anon_decl.concrete_ty
+                        );
+                        debug!("equate_inputs_and_outputs: anon_defn_ty={:?}", anon_defn_ty);
+                        obligations.add(
+                            infcx
+                                .at(&ObligationCause::dummy(), cx.param_env)
+                                .eq(anon_decl.concrete_ty, anon_defn_ty)?,
+                        );
+                    }
+
+                    debug!("equate_inputs_and_outputs: equated");
+
+                    Ok(InferOk {
+                        value: Some(anon_type_map),
+                        obligations: obligations.into_vec(),
+                    })
+                },
+            ).unwrap_or_else(|terr| {
                 span_mirbug!(
                     self,
                     Location::START,
@@ -143,13 +153,17 @@ pub(super) fn equate_inputs_and_outputs(
         // prove that `T: Iterator` where `T` is the type we
         // instantiated it with).
         if let Some(anon_type_map) = anon_type_map {
-            self.fully_perform_op(Locations::All, |_cx| {
-                infcx.constrain_anon_types(&anon_type_map, universal_regions);
-                Ok(InferOk {
-                    value: (),
-                    obligations: vec![],
-                })
-            }).unwrap();
+            self.fully_perform_op(
+                Locations::All,
+                || format!("anon_type_map"),
+                |_cx| {
+                    infcx.constrain_anon_types(&anon_type_map, universal_regions);
+                    Ok(InferOk {
+                        value: (),
+                        obligations: vec![],
+                    })
+                },
+            ).unwrap();
         }
     }
 
index 76320c6a2eacc96912c70f3ae3579ebb474bad0f..80f5fe4184f9db508757dd51fd05f566fce0d1f1 100644 (file)
@@ -8,15 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use dataflow::{FlowAtLocation, FlowsAtLocation};
 use borrow_check::nll::region_infer::Cause;
-use dataflow::MaybeInitializedPlaces;
+use borrow_check::nll::type_check::AtLocation;
 use dataflow::move_paths::{HasMoveData, MoveData};
-use rustc::mir::{BasicBlock, Location, Mir};
+use dataflow::MaybeInitializedPlaces;
+use dataflow::{FlowAtLocation, FlowsAtLocation};
+use rustc::infer::region_constraints::RegionConstraintData;
 use rustc::mir::Local;
-use rustc::ty::{Ty, TyCtxt, TypeFoldable};
-use rustc::infer::InferOk;
-use borrow_check::nll::type_check::AtLocation;
+use rustc::mir::{BasicBlock, Location, Mir};
+use rustc::traits::ObligationCause;
+use rustc::ty::subst::Kind;
+use rustc::ty::{Ty, TypeFoldable};
+use rustc_data_structures::fx::FxHashMap;
+use std::rc::Rc;
 use util::liveness::LivenessResults;
 
 use super::TypeChecker;
@@ -36,14 +40,13 @@ pub(super) fn generate<'gcx, 'tcx>(
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
-    let tcx = cx.tcx();
     let mut generator = TypeLivenessGenerator {
         cx,
-        tcx,
         mir,
         liveness,
         flow_inits,
         move_data,
+        drop_data: FxHashMap(),
     };
 
     for bb in mir.basic_blocks().indices() {
@@ -59,11 +62,16 @@ struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx>
     'gcx: 'tcx,
 {
     cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>,
-    tcx: TyCtxt<'typeck, 'gcx, 'tcx>,
     mir: &'gen Mir<'tcx>,
     liveness: &'gen LivenessResults,
     flow_inits: &'gen mut FlowAtLocation<MaybeInitializedPlaces<'flow, 'gcx, 'tcx>>,
     move_data: &'gen MoveData<'tcx>,
+    drop_data: FxHashMap<Ty<'tcx>, DropData<'tcx>>,
+}
+
+struct DropData<'tcx> {
+    dropped_kinds: Vec<Kind<'tcx>>,
+    region_constraint_data: Option<Rc<RegionConstraintData<'tcx>>>,
 }
 
 impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> {
@@ -80,7 +88,7 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
                 for live_local in live_locals.iter() {
                     let live_local_ty = self.mir.local_decls[live_local].ty;
                     let cause = Cause::LiveVar(live_local, location);
-                    self.push_type_live_constraint(live_local_ty, location, cause);
+                    Self::push_type_live_constraint(&mut self.cx, live_local_ty, location, cause);
                 }
             });
 
@@ -148,8 +156,12 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
     /// `location` -- i.e., it may be used later. This means that all
     /// regions appearing in the type `live_ty` must be live at
     /// `location`.
-    fn push_type_live_constraint<T>(&mut self, value: T, location: Location, cause: Cause)
-    where
+    fn push_type_live_constraint<T>(
+        cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
+        value: T,
+        location: Location,
+        cause: Cause,
+    ) where
         T: TypeFoldable<'tcx>,
     {
         debug!(
@@ -157,8 +169,8 @@ fn push_type_live_constraint<T>(&mut self, value: T, location: Location, cause:
             value, location
         );
 
-        self.tcx.for_each_free_region(&value, |live_region| {
-            self.cx
+        cx.tcx().for_each_free_region(&value, |live_region| {
+            cx
                 .constraints
                 .liveness_set
                 .push((live_region, location, cause.clone()));
@@ -181,47 +193,44 @@ fn add_drop_live_constraint(
             dropped_local, dropped_ty, location
         );
 
-        // If we end visiting the same type twice (usually due to a cycle involving
-        // associated types), we need to ensure that its region types match up with the type
-        // we added to the 'known' map the first time around. For this reason, we need
-        // our infcx to hold onto its calculated region constraints after each call
-        // to dtorck_constraint_for_ty. Otherwise, normalizing the corresponding associated
-        // type will end up instantiating the type with a new set of inference variables
-        // Since this new type will never be in 'known', we end up looping forever.
-        //
-        // For this reason, we avoid calling TypeChecker.normalize, instead doing all normalization
-        // ourselves in one large 'fully_perform_op' callback.
-        let kind_constraints = self.cx
-            .fully_perform_op(location.at_self(), |cx| {
-                let span = cx.last_span;
-
-                let mut final_obligations = Vec::new();
-                let mut kind_constraints = Vec::new();
-
-                let InferOk {
-                    value: kinds,
-                    obligations,
-                } = cx.infcx
-                    .at(&cx.misc(span), cx.param_env)
-                    .dropck_outlives(dropped_ty);
-                for kind in kinds {
-                    // All things in the `outlives` array may be touched by
-                    // the destructor and must be live at this point.
-                    let cause = Cause::DropVar(dropped_local, location);
-                    kind_constraints.push((kind, location, cause));
-                }
+        let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
+            let cx = &mut self.cx;
+            move || Self::compute_drop_data(cx, dropped_ty)
+        });
 
-                final_obligations.extend(obligations);
+        if let Some(data) = &drop_data.region_constraint_data {
+            self.cx
+                .push_region_constraints(location.at_self(), data.clone());
+        }
 
-                Ok(InferOk {
-                    value: kind_constraints,
-                    obligations: final_obligations,
-                })
-            })
-            .unwrap();
+        // All things in the `outlives` array may be touched by
+        // the destructor and must be live at this point.
+        let cause = Cause::DropVar(dropped_local, location);
+        for &kind in &drop_data.dropped_kinds {
+            Self::push_type_live_constraint(&mut self.cx, kind, location, cause);
+        }
+    }
 
-        for (kind, location, cause) in kind_constraints {
-            self.push_type_live_constraint(kind, location, cause);
+    fn compute_drop_data(
+        cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
+        dropped_ty: Ty<'tcx>,
+    ) -> DropData<'tcx> {
+        debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
+
+        let (dropped_kinds, region_constraint_data) =
+            cx.fully_perform_op_and_get_region_constraint_data(
+                || format!("compute_drop_data(dropped_ty={:?})", dropped_ty),
+                |cx| {
+                    Ok(cx
+                        .infcx
+                        .at(&ObligationCause::dummy(), cx.param_env)
+                        .dropck_outlives(dropped_ty))
+                },
+            ).unwrap();
+
+        DropData {
+            dropped_kinds,
+            region_constraint_data,
         }
     }
 }
index 04f5024b76946602cd2341f393ac30ba921fe7eb..d25cec7979140cdee49791fcfd523fe1c72bdfb6 100644 (file)
 //! This pass type-checks the MIR to ensure it is not broken.
 #![allow(unreachable_code)]
 
+use borrow_check::location::LocationTable;
+use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::Cause;
-use borrow_check::nll::region_infer::ClosureRegionRequirementsExt;
+use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, OutlivesConstraint, TypeTest};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
 use rustc::hir::def_id::DefId;
 use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
 use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
+use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::*;
 use rustc::traits::query::NoSolution;
-use rustc::traits::{self, Normalized, TraitEngine};
+use rustc::traits::{self, ObligationCause, Normalized, TraitEngine};
 use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
 use std::fmt;
-use syntax::ast;
+use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 use util::liveness::LivenessResults;
@@ -45,7 +47,7 @@ macro_rules! span_mirbug {
             $context.last_span,
             &format!(
                 "broken MIR in {:?} ({:?}): {}",
-                $context.body_id,
+                $context.mir_def_id,
                 $elem,
                 format_args!($($message)*),
             ),
@@ -62,6 +64,7 @@ macro_rules! span_mirbug_and_err {
     })
 }
 
+mod constraint_conversion;
 mod input_output;
 mod liveness;
 
@@ -100,19 +103,25 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     mir: &Mir<'tcx>,
     mir_def_id: DefId,
     universal_regions: &UniversalRegions<'tcx>,
+    location_table: &LocationTable,
     liveness: &LivenessResults,
+    all_facts: &mut Option<AllFacts>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) -> MirTypeckRegionConstraints<'tcx> {
-    let body_id = infcx.tcx.hir.as_local_node_id(mir_def_id).unwrap();
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
     type_check_internal(
         infcx,
-        body_id,
+        mir_def_id,
         param_env,
         mir,
         &universal_regions.region_bound_pairs,
         Some(implicit_region_bound),
+        Some(BorrowCheckContext {
+            universal_regions,
+            location_table,
+            all_facts,
+        }),
         &mut |cx| {
             liveness::generate(cx, mir, liveness, flow_inits, move_data);
 
@@ -123,19 +132,22 @@ pub(crate) fn type_check<'gcx, 'tcx>(
 
 fn type_check_internal<'gcx, 'tcx>(
     infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-    body_id: ast::NodeId,
+    mir_def_id: DefId,
     param_env: ty::ParamEnv<'gcx>,
     mir: &Mir<'tcx>,
     region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
+    borrowck_context: Option<BorrowCheckContext<'_, 'tcx>>,
     extra: &mut dyn FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>),
 ) -> MirTypeckRegionConstraints<'tcx> {
     let mut checker = TypeChecker::new(
         infcx,
-        body_id,
+        mir_def_id,
         param_env,
         region_bound_pairs,
         implicit_region_bound,
+        borrowck_context,
+        mir,
     );
     let errors_reported = {
         let mut verifier = TypeVerifier::new(&mut checker, mir);
@@ -173,7 +185,7 @@ struct TypeVerifier<'a, 'b: 'a, 'gcx: 'b + 'tcx, 'tcx: 'b> {
     cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
     last_span: Span,
-    body_id: ast::NodeId,
+    mir_def_id: DefId,
     errors_reported: bool,
 }
 
@@ -221,7 +233,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
         TypeVerifier {
             mir,
-            body_id: cx.body_id,
+            mir_def_id: cx.mir_def_id,
             cx,
             last_span: mir.span,
             errors_reported: false,
@@ -300,7 +312,8 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
 
         debug!("sanitize_constant: expected_ty={:?}", expected_ty);
 
-        if let Err(terr) = self.cx
+        if let Err(terr) = self
+            .cx
             .eq_types(expected_ty, constant.ty, location.at_self())
         {
             span_mirbug!(
@@ -580,17 +593,25 @@ struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
     last_span: Span,
-    body_id: ast::NodeId,
+    mir_def_id: DefId,
     region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
     constraints: MirTypeckRegionConstraints<'tcx>,
+    borrowck_context: Option<BorrowCheckContext<'a, 'tcx>>,
+    mir: &'a Mir<'tcx>,
+}
+
+struct BorrowCheckContext<'a, 'tcx: 'a> {
+    universal_regions: &'a UniversalRegions<'tcx>,
+    location_table: &'a LocationTable,
+    all_facts: &'a mut Option<AllFacts>,
 }
 
 /// A collection of region constraints that must be satisfied for the
 /// program to be considered well-typed.
 #[derive(Default)]
-pub(crate) struct MirTypeckRegionConstraints<'tcx> {
+crate struct MirTypeckRegionConstraints<'tcx> {
     /// In general, the type-checker is not responsible for enforcing
     /// liveness constraints; this job falls to the region inferencer,
     /// which performs a liveness analysis. However, in some limited
@@ -598,24 +619,11 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
     /// not otherwise appear in the MIR -- in particular, the
     /// late-bound regions that it instantiates at call-sites -- and
     /// hence it must report on their liveness constraints.
-    pub liveness_set: Vec<(ty::Region<'tcx>, Location, Cause)>,
-
-    /// During the course of type-checking, we will accumulate region
-    /// constraints due to performing subtyping operations or solving
-    /// traits. These are accumulated into this vector for later use.
-    pub outlives_sets: Vec<OutlivesSet<'tcx>>,
-}
+    crate liveness_set: Vec<(ty::Region<'tcx>, Location, Cause)>,
 
-/// Outlives relationships between regions and types created at a
-/// particular point within the control-flow graph.
-pub struct OutlivesSet<'tcx> {
-    /// The locations associated with these constraints.
-    pub locations: Locations,
+    crate outlives_constraints: Vec<OutlivesConstraint>,
 
-    /// Constraints generated. In terms of the NLL RFC, when you have
-    /// a constraint `R1: R2 @ P`, the data in there specifies things
-    /// like `R1: R2`.
-    pub data: RegionConstraintData<'tcx>,
+    crate type_tests: Vec<TypeTest<'tcx>>,
 }
 
 /// The `Locations` type summarizes *where* region constraints are
@@ -667,7 +675,7 @@ pub enum Locations {
         /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field
         /// is the `P` value.
         at_location: Location,
-    }
+    },
 }
 
 impl Locations {
@@ -689,37 +697,99 @@ pub fn at_location(&self) -> Option<Location> {
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn new(
         infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-        body_id: ast::NodeId,
+        mir_def_id: DefId,
         param_env: ty::ParamEnv<'gcx>,
         region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
         implicit_region_bound: Option<ty::Region<'tcx>>,
+        borrowck_context: Option<BorrowCheckContext<'a, 'tcx>>,
+        mir: &'a Mir<'tcx>,
     ) -> Self {
         TypeChecker {
             infcx,
             last_span: DUMMY_SP,
-            body_id,
+            mir_def_id,
             param_env,
             region_bound_pairs,
             implicit_region_bound,
+            borrowck_context,
+            mir,
             reported_errors: FxHashSet(),
             constraints: MirTypeckRegionConstraints::default(),
         }
     }
 
-    fn misc(&self, span: Span) -> traits::ObligationCause<'tcx> {
-        traits::ObligationCause::misc(span, self.body_id)
+    /// Given some operation `op` that manipulates types, proves
+    /// predicates, or otherwise uses the inference context, executes
+    /// `op` and then executes all the further obligations that `op`
+    /// returns. This will yield a set of outlives constraints amongst
+    /// regions which are extracted and stored as having occured at
+    /// `locations`.
+    ///
+    /// **Any `rustc::infer` operations that might generate region
+    /// constraints should occur within this method so that those
+    /// constraints can be properly localized!**
+    fn fully_perform_op<R>(
+        &mut self,
+        locations: Locations,
+        describe_op: impl Fn() -> String,
+        op: impl FnOnce(&mut Self) -> InferResult<'tcx, R>,
+    ) -> Result<R, TypeError<'tcx>> {
+        let (r, opt_data) = self.fully_perform_op_and_get_region_constraint_data(
+            || format!("{} at {:?}", describe_op(), locations),
+            op,
+        )?;
+
+        if let Some(data) = opt_data {
+            self.push_region_constraints(locations, data);
+        }
+
+        Ok(r)
     }
 
-    fn fully_perform_op<OP, R>(
+    fn push_region_constraints(
         &mut self,
         locations: Locations,
-        op: OP,
-    ) -> Result<R, TypeError<'tcx>>
-    where
-        OP: FnOnce(&mut Self) -> InferResult<'tcx, R>,
-    {
+        data: Rc<RegionConstraintData<'tcx>>,
+    ) {
+        debug!(
+            "push_region_constraints: constraints generated at {:?} are {:#?}",
+            locations, data
+        );
+
+        if let Some(borrowck_context) = &mut self.borrowck_context {
+            constraint_conversion::ConstraintConversion::new(
+                self.mir,
+                borrowck_context.universal_regions,
+                borrowck_context.location_table,
+                &mut self.constraints.outlives_constraints,
+                &mut self.constraints.type_tests,
+                &mut borrowck_context.all_facts,
+            ).convert(locations, &data);
+        }
+    }
+
+    /// Helper for `fully_perform_op`, but also used on its own
+    /// sometimes to enable better caching: executes `op` fully (along
+    /// with resulting obligations) and returns the full set of region
+    /// obligations. If the same `op` were to be performed at some
+    /// other location, then the same set of region obligations would
+    /// be generated there, so this can be useful for caching.
+    fn fully_perform_op_and_get_region_constraint_data<R>(
+        &mut self,
+        describe_op: impl Fn() -> String,
+        op: impl FnOnce(&mut Self) -> InferResult<'tcx, R>,
+    ) -> Result<(R, Option<Rc<RegionConstraintData<'tcx>>>), TypeError<'tcx>> {
+        if cfg!(debug_assertions) {
+            info!(
+                "fully_perform_op_and_get_region_constraint_data({})",
+                describe_op(),
+            );
+        }
+
         let mut fulfill_cx = TraitEngine::new(self.infcx.tcx);
+        let dummy_body_id = ObligationCause::dummy().body_id;
         let InferOk { value, obligations } = self.infcx.commit_if_ok(|_| op(self))?;
+        debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
         fulfill_cx.register_predicate_obligations(self.infcx, obligations);
         if let Err(e) = fulfill_cx.select_all_or_error(self.infcx) {
             span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
@@ -729,21 +799,15 @@ fn fully_perform_op<OP, R>(
             self.region_bound_pairs,
             self.implicit_region_bound,
             self.param_env,
-            self.body_id,
+            dummy_body_id,
         );
 
         let data = self.infcx.take_and_reset_region_constraints();
-        if !data.is_empty() {
-            debug!(
-                "fully_perform_op: constraints generated at {:?} are {:#?}",
-                locations, data
-            );
-            self.constraints
-                .outlives_sets
-                .push(OutlivesSet { locations, data });
+        if data.is_empty() {
+            Ok((value, None))
+        } else {
+            Ok((value, Some(Rc::new(data))))
         }
-
-        Ok(value)
     }
 
     fn sub_types(
@@ -752,19 +816,37 @@ fn sub_types(
         sup: Ty<'tcx>,
         locations: Locations,
     ) -> UnitResult<'tcx> {
-        self.fully_perform_op(locations, |this| {
-            this.infcx
-                .at(&this.misc(this.last_span), this.param_env)
-                .sup(sup, sub)
-        })
+        // Micro-optimization.
+        if sub == sup {
+            return Ok(());
+        }
+
+        self.fully_perform_op(
+            locations,
+            || format!("sub_types({:?} <: {:?})", sub, sup),
+            |this| {
+                this.infcx
+                    .at(&ObligationCause::dummy(), this.param_env)
+                    .sup(sup, sub)
+            },
+        )
     }
 
     fn eq_types(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, locations: Locations) -> UnitResult<'tcx> {
-        self.fully_perform_op(locations, |this| {
-            this.infcx
-                .at(&this.misc(this.last_span), this.param_env)
-                .eq(b, a)
-        })
+        // Micro-optimization.
+        if a == b {
+            return Ok(());
+        }
+
+        self.fully_perform_op(
+            locations,
+            || format!("eq_types({:?} = {:?})", a, b),
+            |this| {
+                this.infcx
+                    .at(&ObligationCause::dummy(), this.param_env)
+                    .eq(b, a)
+            },
+        )
     }
 
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -819,7 +901,8 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
             }
             StatementKind::UserAssertTy(ref c_ty, ref local) => {
                 let local_ty = mir.local_decls()[*local].ty;
-                let (ty, _) = self.infcx
+                let (ty, _) = self
+                    .infcx
                     .instantiate_canonical_with_fresh_inference_vars(stmt.source_info.span, c_ty);
                 debug!(
                     "check_stmt: user_assert_ty ty={:?} local_ty={:?}",
@@ -1431,9 +1514,7 @@ fn check_aggregate_rvalue(
                 }
             };
             let operand_ty = operand.ty(mir, tcx);
-            if let Err(terr) =
-                self.sub_types(operand_ty, field_ty, location.at_self())
-            {
+            if let Err(terr) = self.sub_types(operand_ty, field_ty, location.at_self()) {
                 span_mirbug!(
                     self,
                     rvalue,
@@ -1487,9 +1568,10 @@ fn prove_aggregate_predicates(
                 if let Some(closure_region_requirements) =
                     tcx.mir_borrowck(*def_id).closure_requirements
                 {
+                    let dummy_body_id = ObligationCause::dummy().body_id;
                     closure_region_requirements.apply_requirements(
                         self.infcx,
-                        self.body_id,
+                        dummy_body_id,
                         location,
                         *def_id,
                         *substs,
@@ -1522,27 +1604,44 @@ fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location)
 
     fn prove_predicates<T>(&mut self, predicates: T, location: Location)
     where
-        T: IntoIterator<Item = ty::Predicate<'tcx>>,
-        T::IntoIter: Clone,
+        T: IntoIterator<Item = ty::Predicate<'tcx>> + Clone,
     {
-        let predicates = predicates.into_iter();
+        let cause = ObligationCause::dummy();
+        let obligations: Vec<_> = predicates
+            .into_iter()
+            .map(|p| traits::Obligation::new(cause.clone(), self.param_env, p))
+            .collect();
+
+        // Micro-optimization
+        if obligations.is_empty() {
+            return;
+        }
+
+        // This intermediate vector is mildly unfortunate, in that we
+        // sometimes create it even when logging is disabled, but only
+        // if debug-info is enabled, and I doubt it is actually
+        // expensive. -nmatsakis
+        let predicates_vec: Vec<_> = if cfg!(debug_assertions) {
+            obligations.iter().map(|o| o.predicate).collect()
+        } else {
+            Vec::new()
+        };
 
         debug!(
             "prove_predicates(predicates={:?}, location={:?})",
-            predicates.clone().collect::<Vec<_>>(),
-            location,
+            predicates_vec, location,
         );
-        self.fully_perform_op(location.at_self(), |this| {
-            let cause = this.misc(this.last_span);
-            let obligations = predicates
-                .into_iter()
-                .map(|p| traits::Obligation::new(cause.clone(), this.param_env, p))
-                .collect();
-            Ok(InferOk {
-                value: (),
-                obligations,
-            })
-        }).unwrap()
+
+        self.fully_perform_op(
+            location.at_self(),
+            || format!("prove_predicates({:?})", predicates_vec),
+            |_this| {
+                Ok(InferOk {
+                    value: (),
+                    obligations,
+                })
+            },
+        ).unwrap()
     }
 
     fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
@@ -1575,21 +1674,31 @@ fn normalize<T>(&mut self, value: &T, location: impl ToLocations) -> T
     where
         T: fmt::Debug + TypeFoldable<'tcx>,
     {
+        // Micro-optimization: avoid work when we don't have to
+        if !value.has_projections() {
+            return value.clone();
+        }
+
         debug!("normalize(value={:?}, location={:?})", value, location);
-        self.fully_perform_op(location.to_locations(), |this| {
-            let Normalized { value, obligations } = this.infcx
-                .at(&this.misc(this.last_span), this.param_env)
-                .normalize(value)
-                .unwrap_or_else(|NoSolution| {
-                    span_bug!(
-                        this.last_span,
-                        "normalization of `{:?}` failed at {:?}",
-                        value,
-                        location,
-                    );
-                });
-            Ok(InferOk { value, obligations })
-        }).unwrap()
+        self.fully_perform_op(
+            location.to_locations(),
+            || format!("normalize(value={:?})", value),
+            |this| {
+                let Normalized { value, obligations } = this
+                    .infcx
+                    .at(&ObligationCause::dummy(), this.param_env)
+                    .normalize(value)
+                    .unwrap_or_else(|NoSolution| {
+                        span_bug!(
+                            this.last_span,
+                            "normalization of `{:?}` failed at {:?}",
+                            value,
+                            location,
+                        );
+                    });
+                Ok(InferOk { value, obligations })
+            },
+        ).unwrap()
     }
 }
 
@@ -1598,7 +1707,6 @@ fn normalize<T>(&mut self, value: &T, location: impl ToLocations) -> T
 impl MirPass for TypeckMir {
     fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
         let def_id = src.def_id;
-        let id = tcx.hir.as_local_node_id(def_id).unwrap();
         debug!("run_pass: {:?}", def_id);
 
         // When NLL is enabled, the borrow checker runs the typeck
@@ -1614,7 +1722,16 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &
         }
         let param_env = tcx.param_env(def_id);
         tcx.infer_ctxt().enter(|infcx| {
-            let _ = type_check_internal(&infcx, id, param_env, mir, &[], None, &mut |_| ());
+            let _ = type_check_internal(
+                &infcx,
+                def_id,
+                param_env,
+                mir,
+                &[],
+                None,
+                None,
+                &mut |_| (),
+            );
 
             // For verification purposes, we just ignore the resulting
             // region constraint sets. Not our problem. =)
index d815d4a7dba917ef1477acfe307616acc3852f06..dc0d0b244633f28de71e578dbd136b23c9a3d5f5 100644 (file)
 #![feature(specialization)]
 #![feature(try_trait)]
 
+#![recursion_limit="256"]
+
 extern crate arena;
+
 #[macro_use]
 extern crate bitflags;
 #[macro_use] extern crate log;
index a8a50c50f592e844ca5468bba3bd7d6e179bed00..96aeb969d89f96eb20f367b49609748498373db2 100644 (file)
 
 use monomorphize::{self, Instance};
 use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
+use rustc::util::common::time;
 
 use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode};
 
 use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
 
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum MonoItemCollectionMode {
@@ -298,22 +300,32 @@ pub fn collect_crate_mono_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                           mode: MonoItemCollectionMode)
                                           -> (FxHashSet<MonoItem<'tcx>>,
                                                      InliningMap<'tcx>) {
-    let roots = collect_roots(tcx, mode);
+    let roots = time(tcx.sess, "collecting roots", || {
+        collect_roots(tcx, mode)
+    });
 
     debug!("Building mono item graph, beginning at roots");
-    let mut visited = FxHashSet();
-    let mut recursion_depths = DefIdMap();
-    let mut inlining_map = InliningMap::new();
-
-    for root in roots {
-        collect_items_rec(tcx,
-                          root,
-                          &mut visited,
-                          &mut recursion_depths,
-                          &mut inlining_map);
+
+    let mut visited = MTLock::new(FxHashSet());
+    let mut inlining_map = MTLock::new(InliningMap::new());
+
+    {
+        let visited: MTRef<'_, _> = &mut visited;
+        let inlining_map: MTRef<'_, _> = &mut inlining_map;
+
+        time(tcx.sess, "collecting mono items", || {
+            par_iter(roots).for_each(|root| {
+                let mut recursion_depths = DefIdMap();
+                collect_items_rec(tcx,
+                                root,
+                                visited,
+                                &mut recursion_depths,
+                                inlining_map);
+            });
+        });
     }
 
-    (visited, inlining_map)
+    (visited.into_inner(), inlining_map.into_inner())
 }
 
 // Find all non-generic items by walking the HIR. These items serve as roots to
@@ -354,10 +366,10 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 // Collect all monomorphized items reachable from `starting_point`
 fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    starting_point: MonoItem<'tcx>,
-                                   visited: &mut FxHashSet<MonoItem<'tcx>>,
+                                   visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
                                    recursion_depths: &mut DefIdMap<usize>,
-                                   inlining_map: &mut InliningMap<'tcx>) {
-    if !visited.insert(starting_point.clone()) {
+                                   inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>) {
+    if !visited.lock_mut().insert(starting_point.clone()) {
         // We've been here already, no need to search again.
         return;
     }
@@ -428,7 +440,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn record_accesses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              caller: MonoItem<'tcx>,
                              callees: &[MonoItem<'tcx>],
-                             inlining_map: &mut InliningMap<'tcx>) {
+                             inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>) {
     let is_inlining_candidate = |mono_item: &MonoItem<'tcx>| {
         mono_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy
     };
@@ -438,7 +450,7 @@ fn record_accesses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              (*mono_item, is_inlining_candidate(mono_item))
                           });
 
-    inlining_map.record_accesses(caller, accesses);
+    inlining_map.lock_mut().record_accesses(caller, accesses);
 }
 
 fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -944,6 +956,7 @@ fn visit_item(&mut self, item: &'v hir::Item) {
             hir::ItemTy(..)          |
             hir::ItemTrait(..)       |
             hir::ItemTraitAlias(..)  |
+            hir::ItemExistential(..) |
             hir::ItemMod(..)         => {
                 // Nothing to do, just keep recursing...
             }
index 308c5b9f201562b397d1a1ceff4e77db18c39f61..291092015b57f06c208538d7d52b66c22985680b 100644 (file)
@@ -160,6 +160,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
             hir::ItemStatic(..) | hir::ItemStruct(..) |
             hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
+            hir::ItemExistential(..) |
             hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
                 if item.vis == hir::Public { self.prev_level } else { None }
             }
@@ -212,6 +213,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     }
                 }
             }
+            hir::ItemExistential(..) |
             hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
             hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
             hir::ItemFn(..) | hir::ItemExternCrate(..) => {}
@@ -227,6 +229,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemUse(..) => {}
             // The interface is empty
             hir::ItemGlobalAsm(..) => {}
+            // Checked by visit_ty
+            hir::ItemExistential(..) => {}
             // Visit everything
             hir::ItemConst(..) | hir::ItemStatic(..) |
             hir::ItemFn(..) | hir::ItemTy(..) => {
@@ -388,10 +392,10 @@ fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
     }
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyImplTraitExistential(..) = ty.node {
-            if self.get(ty.id).is_some() {
-                // Reach the (potentially private) type and the API being exposed.
-                self.reach(ty.id).ty().predicates();
+        if let hir::TyImplTraitExistential(item_id, _, _) = ty.node {
+            if self.get(item_id.id).is_some() {
+                // Reach the (potentially private) type and the API being exposed
+                self.reach(item_id.id).ty().predicates();
             }
         }
 
@@ -436,6 +440,10 @@ fn predicates(&mut self) -> &mut Self {
 
     fn ty(&mut self) -> &mut Self {
         let ty = self.ev.tcx.type_of(self.item_def_id);
+        self.walk_ty(ty)
+    }
+
+    fn walk_ty(&mut self, ty: Ty<'tcx>) -> &mut Self {
         ty.visit_with(self);
         if let ty::TyFnDef(def_id, _) = ty.sty {
             if def_id == self.item_def_id {
@@ -1546,6 +1554,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemUse(..) => {}
             // No subitems
             hir::ItemGlobalAsm(..) => {}
+            // Checked in visit_ty
+            hir::ItemExistential(..) => {}
             // Subitems of these items have inherited publicity
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
             hir::ItemTy(..) => {
@@ -1644,13 +1654,14 @@ fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {
     }
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyImplTraitExistential(..) = ty.node {
+        if let hir::TyImplTraitExistential(ref exist_item, _, _) = ty.node {
             // Check the traits being exposed, as they're separate,
             // e.g. `impl Iterator<Item=T>` has two predicates,
             // `X: Iterator` and `<X as Iterator>::Item == T`,
             // where `X` is the `impl Iterator<Item=T>` itself,
             // stored in `predicates_of`, not in the `Ty` itself.
-            self.check(ty.id, self.inner_visibility).predicates();
+
+            self.check(exist_item.id, self.inner_visibility).predicates();
         }
 
         intravisit::walk_ty(self, ty);
index 2471430798e3c752f791195bd6eeb87dd8cc5ff1..a2b2096ccaa47aa01cf39bfa5587ea91556cfce3 100644 (file)
@@ -205,6 +205,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                 Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) |
                 Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) |
                 Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) |
+                Def::Existential(..) |
                 Def::Macro(..) | Def::GlobalAsm(..) | Def::Err =>
                     bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
                          Def::TyParam")
index 64dcd3e51751c1c4f7fd473aa4d832d4ad969e6d..f9510970e43d44edb2a753b8dbfd6f785c56a586 100644 (file)
@@ -749,6 +749,7 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::TraitAlias(def_id) |
             HirDef::AssociatedTy(def_id) |
             HirDef::Trait(def_id) |
+            HirDef::Existential(def_id) |
             HirDef::TyParam(def_id) => {
                 let span = self.span_from_span(sub_span);
                 Some(Ref {
index f2e32286e9ee652499fa384842133cdbf61644c1..18911b47ed1d08434ac9ba141d56d92bacef8980 100644 (file)
@@ -1118,8 +1118,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyTraitObject(ref bounds, ref lifetime) => {
                 self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
             }
-            hir::TyImplTraitExistential(_, ref lifetimes) => {
-                let def_id = tcx.hir.local_def_id(ast_ty.id);
+            hir::TyImplTraitExistential(_, def_id, ref lifetimes) => {
                 self.impl_trait_ty_to_ty(def_id, lifetimes)
             }
             hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
@@ -1171,9 +1170,14 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
         result_ty
     }
 
-    pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) -> Ty<'tcx> {
+    pub fn impl_trait_ty_to_ty(
+        &self,
+        def_id: DefId,
+        lifetimes: &[hir::Lifetime],
+    ) -> Ty<'tcx> {
         debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
         let tcx = self.tcx();
+
         let generics = tcx.generics_of(def_id);
 
         debug!("impl_trait_ty_to_ty: generics={:?}", generics);
@@ -1198,7 +1202,9 @@ pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) ->
         });
         debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
 
-        tcx.mk_anon(def_id, substs)
+        let ty = tcx.mk_anon(def_id, substs);
+        debug!("impl_trait_ty_to_ty: {}", ty);
+        ty
     }
 
     pub fn ty_of_arg(&self,
index 439c1b34227940fdf6f8cde064734ea4dd9dcb6a..cfe9e420c5fee79b739b4f1fe923880baf6efbd1 100644 (file)
@@ -463,7 +463,7 @@ fn sig_of_closure_with_expectation(
         // Create a `PolyFnSig`. Note the oddity that late bound
         // regions appearing free in `expected_sig` are now bound up
         // in this binder we are creating.
-        assert!(!expected_sig.sig.has_regions_bound_above(ty::DebruijnIndex::INNERMOST));
+        assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST));
         let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
             expected_sig.sig.inputs().iter().cloned(),
             expected_sig.sig.output(),
index 215a3163a9c0a9b167de09372e45a49c06aa3c75..c93023edcea08285207dd94d67ac34959846ca6a 100644 (file)
@@ -119,7 +119,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "pref_align_of" | "min_align_of" => (1, Vec::new(), tcx.types.usize),
             "size_of_val" |  "min_align_of_val" => {
                 (1, vec![
-                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::INNERMOST,
+                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST,
                                                                   ty::BrAnon(0))),
                                     param(0))
                  ], tcx.types.usize)
@@ -298,7 +298,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "unlikely" => (0, vec![tcx.types.bool], tcx.types.bool),
 
             "discriminant_value" => (1, vec![
-                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::INNERMOST,
+                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST,
                                                                   ty::BrAnon(0))),
                                    param(0))], tcx.types.u64),
 
index 7dcd6d1a3b350061713bda5ca6743578c475ba2c..b70b61d191594f0baa9c8e2c6b4ee983a5b7de33 100644 (file)
@@ -702,9 +702,9 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum
 {
     debug_assert!(crate_num == LOCAL_CRATE);
     Ok(tcx.sess.track_errors(|| {
-        for body_owner_def_id in tcx.body_owners() {
+        tcx.par_body_owners(|body_owner_def_id| {
             ty::query::queries::typeck_tables_of::ensure(tcx, body_owner_def_id);
-        }
+        });
     })?)
 }
 
@@ -1013,7 +1013,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env);
 
     // Create the function context.  This is either derived from scratch or,
-    // in the case of function expressions, based on the outer context.
+    // in the case of closures, based on the outer context.
     let mut fcx = FnCtxt::new(inherited, param_env, body.value.id);
     *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
 
index f295d1763c4c75c5c3ac575ea7022f411f0c6c18..f7d1e40794580612dbbf3d35fc7686d3223fcecf 100644 (file)
@@ -43,7 +43,7 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
         wbcx.visit_fru_field_types();
-        wbcx.visit_anon_types();
+        wbcx.visit_anon_types(body.value.span);
         wbcx.visit_cast_types();
         wbcx.visit_free_region_map();
         wbcx.visit_user_provided_tys();
@@ -385,18 +385,28 @@ fn visit_user_provided_tys(&mut self) {
         }
     }
 
-    fn visit_anon_types(&mut self) {
-        let gcx = self.tcx().global_tcx();
+    fn visit_anon_types(&mut self, span: Span) {
         for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() {
-            let node_id = gcx.hir.as_local_node_id(def_id).unwrap();
+            let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
             let instantiated_ty = self.resolve(&anon_defn.concrete_ty, &node_id);
             let definition_ty = self.fcx.infer_anon_definition_from_instantiation(
                 def_id,
                 anon_defn,
                 instantiated_ty,
             );
-            let hir_id = self.tcx().hir.node_to_hir_id(node_id);
-            self.tables.node_types_mut().insert(hir_id, definition_ty);
+            let old = self.tables.concrete_existential_types.insert(def_id, definition_ty);
+            if let Some(old) = old {
+                if old != definition_ty {
+                    span_bug!(
+                        span,
+                        "visit_anon_types tried to write \
+                        different types for the same existential type: {:?}, {:?}, {:?}",
+                        def_id,
+                        definition_ty,
+                        old,
+                    );
+                }
+            }
         }
     }
 
index 05256be6ec91008461179625d457e6b28ae059f2..58e804fc13f2d8c9497f04672c4b528fa0fada04 100644 (file)
@@ -131,15 +131,6 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         intravisit::walk_expr(self, expr);
     }
 
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        if let hir::TyImplTraitExistential(..) = ty.node {
-            let def_id = self.tcx.hir.local_def_id(ty.id);
-            self.tcx.generics_of(def_id);
-            self.tcx.predicates_of(def_id);
-        }
-        intravisit::walk_ty(self, ty);
-    }
-
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         convert_trait_item(self.tcx, trait_item.id);
         intravisit::walk_trait_item(self, trait_item);
@@ -420,6 +411,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
                 convert_variant_ctor(tcx, struct_def.id());
             }
         },
+        hir::ItemExistential(..) |
         hir::ItemTy(..) | hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
@@ -744,7 +736,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         -> Option<Span> {
         let mut visitor = LateBoundRegionsDetector {
             tcx,
-            outer_index: ty::DebruijnIndex::INNERMOST,
+            outer_index: ty::INNERMOST,
             has_late_bound_regions: None,
         };
         for lifetime in generics.lifetimes() {
@@ -803,18 +795,12 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
             Some(tcx.closure_base_def_id(def_id))
         }
-        NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(..), .. }) => {
-            let mut parent_id = node_id;
-            loop {
-                match tcx.hir.get(parent_id) {
-                    NodeItem(_) | NodeImplItem(_) | NodeTraitItem(_) => break,
-                    _ => {
-                        parent_id = tcx.hir.get_parent_node(parent_id);
-                    }
-                }
+        NodeItem(item) => {
+            match item.node {
+                ItemExistential(hir::ExistTy { impl_trait_fn, .. }) => impl_trait_fn,
+                _ => None,
             }
-            Some(tcx.hir.local_def_id(parent_id))
-        }
+        },
         _ => None
     };
 
@@ -835,6 +821,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemTy(_, ref generics) |
                 ItemEnum(_, ref generics) |
                 ItemStruct(_, ref generics) |
+                ItemExistential(hir::ExistTy { ref generics, .. }) |
                 ItemUnion(_, ref generics) => {
                     allow_defaults = true;
                     generics
@@ -875,8 +862,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(ref exist_ty, _), .. }) => {
-            &exist_ty.generics
+        NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(..), .. }) => {
+            bug!("impl Trait is desugared to existential type items");
         }
 
         _ => &no_generics,
@@ -1056,6 +1043,12 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
+                // this is only reachable once we have named existential types
+                ItemExistential(hir::ExistTy { impl_trait_fn: None, .. }) => unimplemented!(),
+                // existential types desugared from impl Trait
+                ItemExistential(hir::ExistTy { impl_trait_fn: Some(owner), .. }) => {
+                    tcx.typeck_tables_of(owner).concrete_existential_types[&def_id]
+                },
                 ItemTrait(..) | ItemTraitAlias(..) |
                 ItemMod(..) |
                 ItemForeignMod(..) |
@@ -1130,12 +1123,6 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             icx.to_ty(ty)
         }
 
-        NodeTy(&hir::Ty { node: TyImplTraitExistential(..), .. }) => {
-            let owner = tcx.hir.get_parent_did(node_id);
-            let hir_id = tcx.hir.node_to_hir_id(node_id);
-            tcx.typeck_tables_of(owner).node_id_to_type(hir_id)
-        }
-
         x => {
             bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
         }
@@ -1353,6 +1340,24 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     }, items));
                     generics
                 }
+                ItemExistential(ref exist_ty) => {
+                    let substs = Substs::identity_for_item(tcx, def_id);
+                    let anon_ty = tcx.mk_anon(def_id, substs);
+
+                    // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
+                    let bounds = compute_bounds(&icx,
+                                                anon_ty,
+                                                &exist_ty.bounds,
+                                                SizedByDefault::Yes,
+                                                tcx.def_span(def_id));
+
+                    let predicates = bounds.predicates(tcx, anon_ty);
+
+                    return ty::GenericPredicates {
+                        parent: None,
+                        predicates: predicates
+                    };
+                }
 
                 _ => &no_generics,
             }
@@ -1366,31 +1371,6 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        NodeTy(&Ty { node: TyImplTraitExistential(ref exist_ty, _), span, .. }) => {
-            let substs = Substs::identity_for_item(tcx, def_id);
-            let anon_ty = tcx.mk_anon(def_id, substs);
-
-            debug!("explicit_predicates_of: anon_ty={:?}", anon_ty);
-
-            // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
-            let bounds = compute_bounds(&icx,
-                                        anon_ty,
-                                        &exist_ty.bounds,
-                                        SizedByDefault::Yes,
-                                        span);
-
-            debug!("explicit_predicates_of: bounds={:?}", bounds);
-
-            let predicates = bounds.predicates(tcx, anon_ty);
-
-            debug!("explicit_predicates_of: predicates={:?}", predicates);
-
-            return ty::GenericPredicates {
-                parent: None,
-                predicates: predicates
-            };
-        }
-
         _ => &no_generics,
     };
 
index ce7249bd7b5b719d32ae985d828953168d7bc5f1..80f57adf580bfc6b5743025a4a812c2c14effd55 100644 (file)
@@ -83,6 +83,8 @@
 #![feature(slice_sort_by_cached_key)]
 #![feature(never_type)]
 
+#![recursion_limit="256"]
+
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
index 8d3cf22350900f6e0db2593fcd1018b31dbe1e15..852a4479199df6f5f75741b421e6037aaaad771b 100644 (file)
@@ -2939,7 +2939,14 @@ fn clean(&self, cx: &DocContext) -> Type {
                 }
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
-            TyImplTraitExistential(ref exist_ty, ref _lts) => ImplTrait(exist_ty.bounds.clean(cx)),
+            TyImplTraitExistential(hir_id, _, _) => {
+                match cx.tcx.hir.expect_item(hir_id.id).node {
+                    hir::ItemExistential(ref exist_ty) => {
+                        ImplTrait(exist_ty.bounds.clean(cx))
+                    },
+                    ref other => panic!("impl Trait pointed to {:#?}", other),
+                }
+            },
             TyInfer | TyErr => Infer,
             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
         }
index 44b41439511f7eac6ff9fbd22dd239771894592e..10b1a2e1e0b67a0c413364ff8f4ea06e762f62bf 100644 (file)
@@ -564,6 +564,9 @@ pub fn visit_item(&mut self, item: &hir::Item,
                     om.impls.push(i);
                 }
             },
+            hir::ItemExistential(_) => {
+                // FIXME(oli-obk): actually generate docs for real existential items
+            }
         }
     }
 
index 13f55e9261fc2acf9a8a4eb98e2da340ca5bb8d8..3dc1e9c3dadc85ff4c5c250d8f0d58a68c997fe5 100644 (file)
@@ -1042,8 +1042,6 @@ fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
 /// # Examples
 ///
 /// ```
-/// #![feature(path_ancestors)]
-///
 /// use std::path::Path;
 ///
 /// let path = Path::new("/foo/bar");
@@ -1056,12 +1054,12 @@ fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
 /// [`ancestors`]: struct.Path.html#method.ancestors
 /// [`Path`]: struct.Path.html
 #[derive(Copy, Clone, Debug)]
-#[unstable(feature = "path_ancestors", issue = "48581")]
+#[stable(feature = "path_ancestors", since = "1.28.0")]
 pub struct Ancestors<'a> {
     next: Option<&'a Path>,
 }
 
-#[unstable(feature = "path_ancestors", issue = "48581")]
+#[stable(feature = "path_ancestors", since = "1.28.0")]
 impl<'a> Iterator for Ancestors<'a> {
     type Item = &'a Path;
 
@@ -1075,7 +1073,7 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
-#[unstable(feature = "path_ancestors", issue = "48581")]
+#[stable(feature = "path_ancestors", since = "1.28.0")]
 impl<'a> FusedIterator for Ancestors<'a> {}
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1890,8 +1888,6 @@ pub fn parent(&self) -> Option<&Path> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(path_ancestors)]
-    ///
     /// use std::path::Path;
     ///
     /// let mut ancestors = Path::new("/foo/bar").ancestors();
@@ -1903,7 +1899,7 @@ pub fn parent(&self) -> Option<&Path> {
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     /// [`parent`]: struct.Path.html#method.parent
-    #[unstable(feature = "path_ancestors", issue = "48581")]
+    #[stable(feature = "path_ancestors", since = "1.28.0")]
     pub fn ancestors(&self) -> Ancestors {
         Ancestors {
             next: Some(&self),
index 530094e22f2437c9af45a37f9e85af356c574525..1735951da2f34638008e06bd45f482dc2c1ad6c0 100644 (file)
@@ -6128,7 +6128,19 @@ fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
     }
 
     pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
-        attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
+        if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") {
+            let s = s.as_str();
+
+            // On windows, the base path might have the form
+            // `\\?\foo\bar` in which case it does not tolerate
+            // mixed `/` and `\` separators, so canonicalize
+            // `/` to `\`.
+            #[cfg(windows)]
+            let s = s.replace("/", "\\");
+            Some(dir_path.join(s))
+        } else {
+            None
+        }
     }
 
     /// Returns either a path to a module, or .
index 76da1746a0397a100b4901f9e55d4dcd0b997800..c3958bb58ddf6bf4c3ddd105c602e3ab09ffc396 100644 (file)
@@ -57,16 +57,17 @@ fn expand(&self,
             Annotatable::Stmt(_) |
             Annotatable::Expr(_) => {
                 ecx.span_err(span, "proc-macro derives may only be \
-                                    applied to struct/enum items");
+                                    applied to a struct, enum, or union");
                 return Vec::new()
             }
         };
         match item.node {
             ItemKind::Struct(..) |
-            ItemKind::Enum(..) => {},
+            ItemKind::Enum(..) |
+            ItemKind::Union(..) => {},
             _ => {
                 ecx.span_err(span, "proc-macro derives may only be \
-                                    applied to struct/enum items");
+                                    applied to a struct, enum, or union");
                 return Vec::new()
             }
         }
index 1365ac396ffdf5f4e21bf89e535556ad8a730a52..6dd910fba8218ab482e8a789d9a9ab8e93bfafc8 100644 (file)
@@ -489,6 +489,10 @@ pub enum CompilerDesugaringKind {
     DotFill,
     QuestionMark,
     Catch,
+    /// Desugaring of an `impl Trait` in return type position
+    /// to an `existential type Foo: Trait;` + replacing the
+    /// `impl Trait` with `Foo`.
+    ExistentialReturnType,
 }
 
 impl CompilerDesugaringKind {
@@ -498,6 +502,7 @@ pub fn as_symbol(&self) -> Symbol {
             DotFill => "...",
             QuestionMark => "?",
             Catch => "do catch",
+            ExistentialReturnType => "existental type",
         };
         Symbol::intern(s)
     }
index 09cc5380d276e16c55744bb44dec35cfeb4022ed..03860ae2122a81953efc7e1f1b202550bc6634f2 100644 (file)
@@ -284,7 +284,7 @@ pub fn change_return_impl_trait() -> impl Clone {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn change_return_impl_trait() -> impl Copy {
     0u32
diff --git a/src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs b/src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs
new file mode 100644 (file)
index 0000000..3bf5065
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2012-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.
+
+// Testing that a libsyntax can parse modules with canonicalized base path
+// ignore-cross-compile
+
+#![feature(rustc_private)]
+
+extern crate syntax;
+
+use std::path::Path;
+use syntax::codemap::FilePathMapping;
+use syntax::parse::{self, ParseSess};
+
+#[path = "mod_dir_simple/test.rs"]
+mod gravy;
+
+pub fn main() {
+    syntax::with_globals(|| parse());
+
+    assert_eq!(gravy::foo(), 10);
+}
+
+fn parse() {
+    let parse_session = ParseSess::new(FilePathMapping::empty());
+
+    let path = Path::new(file!());
+    let path = path.canonicalize().unwrap();
+    let mut parser = parse::new_parser_from_file(&parse_session, &path);
+    let _ = parser.parse_crate_mod();
+}
diff --git a/src/test/run-pass-fulldeps/mod_dir_simple/compiletest-ignore-dir b/src/test/run-pass-fulldeps/mod_dir_simple/compiletest-ignore-dir
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/test/run-pass-fulldeps/mod_dir_simple/test.rs b/src/test/run-pass-fulldeps/mod_dir_simple/test.rs
new file mode 100644 (file)
index 0000000..58c1bee
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2012 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.
+
+pub fn foo() -> isize { 10 }
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-union.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-union.rs
new file mode 100644 (file)
index 0000000..41bb88a
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(UnionTest)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert!(input.contains("#[repr(C)]"));
+    assert!(input.contains("union Test {"));
+    assert!(input.contains("a: u8,"));
+    assert!(input.contains("}"));
+    "".parse().unwrap()
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-union.rs b/src/test/run-pass-fulldeps/proc-macro/derive-union.rs
new file mode 100644 (file)
index 0000000..71807e2
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+// aux-build:derive-union.rs
+// ignore-stage1
+
+#[macro_use]
+extern crate derive_union;
+
+#[repr(C)]
+#[derive(UnionTest)]
+union Test {
+    a: u8,
+}
+
+fn main() {
+    let t = Test { a: 0 };
+}
index c27a2dd89d52473584e980064b357d59a204e218..6e2944e8400e32f4f9f9a5c10dd729fda2c4ea1c 100644 (file)
@@ -23,3 +23,7 @@ pub fn return_closure_accessing_internal_fn() -> impl Fn() -> u32 {
         some_internal_fn() + 1
     }
 }
+
+pub fn return_internal_fn() -> impl Fn() -> u32 {
+    some_internal_fn
+}
diff --git a/src/test/run-pass/impl-trait/bounds_regression.rs b/src/test/run-pass/impl-trait/bounds_regression.rs
new file mode 100644 (file)
index 0000000..cc931a6
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+pub trait FakeGenerator {
+    type Yield;
+    type Return;
+}
+
+pub trait FakeFuture {
+    type Output;
+}
+
+pub fn future_from_generator<
+    T: FakeGenerator<Yield = ()>
+>(x: T) -> impl FakeFuture<Output = T::Return> {
+    GenFuture(x)
+}
+
+struct GenFuture<T: FakeGenerator<Yield = ()>>(T);
+
+impl<T: FakeGenerator<Yield = ()>> FakeFuture for GenFuture<T> {
+    type Output = T::Return;
+}
+
+fn main() {}
index e3b7322e48b6b93ac2b05050dc98417cdb818982..fce31256db4921879c531834c0046bd772538fba 100644 (file)
@@ -14,8 +14,6 @@
 #![feature(fn_traits,
            step_trait,
            unboxed_closures,
-           copy_closures,
-           clone_closures
 )]
 
 //! Derived from: <https://raw.githubusercontent.com/quickfur/dcal/master/dcal.d>.
diff --git a/src/test/run-pass/impl-trait/existential-minimal.rs b/src/test/run-pass/impl-trait/existential-minimal.rs
new file mode 100644 (file)
index 0000000..4e9d786
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {}
+
+fn foo() -> impl std::fmt::Debug { "cake" }
diff --git a/src/test/run-pass/impl-trait/nesting.rs b/src/test/run-pass/impl-trait/nesting.rs
new file mode 100644 (file)
index 0000000..73e6c1c
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+fn foo<T>(t: T) -> impl Into<[T; { const FOO: usize = 1; FOO }]> {
+    [t]
+}
+
+fn bar() -> impl Into<[u8; { const FOO: usize = 1; FOO }]> {
+    [99]
+}
+
+fn main() {
+    println!("{:?}", foo(42).into());
+    println!("{:?}", bar().into());
+}
diff --git a/src/test/run-pass/impl-trait/xcrate_simple.rs b/src/test/run-pass/impl-trait/xcrate_simple.rs
new file mode 100644 (file)
index 0000000..8d4086c
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2016 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.
+
+// aux-build:xcrate.rs
+
+extern crate xcrate;
+
+fn main() {
+    xcrate::return_internal_fn()();
+}
index 54d548757643320c57c973f1359202c5eceaaba7..abb3682a4987a3533b8b70b8d75c53e381f6b54b 100644 (file)
 use std::cell::Cell;
 use std::rc::Rc;
 
-// Fast path, main can see the concrete type returned.
-fn before() -> impl Fn(i32) {
-    let p = Rc::new(Cell::new(0));
-    move |x| p.set(x)
-}
-
 fn send<T: Send>(_: T) {}
 
 fn main() {
-    send(before());
-    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
-
-    send(after());
-    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
-}
-
-// Deferred path, main has to wait until typeck finishes,
-// to check if the return type of after is Send.
-fn after() -> impl Fn(i32) {
-    let p = Rc::new(Cell::new(0));
-    move |x| p.set(x)
 }
 
 // Cycles should work as the deferred obligations are
@@ -41,7 +23,9 @@ fn after() -> impl Fn(i32) {
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
+    //~| ERROR cycle detected
     send(cycle2().clone());
+    //~^ ERROR Send` is not satisfied
 
     Rc::new(Cell::new(5))
 }
index efa9a58d6331036e1f634923a141f120a32d8d43..4537c96c4ab3b8319984f8f5d09d1c97604c38a5 100644 (file)
@@ -1,58 +1,65 @@
-error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
-  --> $DIR/auto-trait-leak.rs:25:5
+error[E0391]: cycle detected when processing `cycle1::{{exist-impl-Trait}}`
+  --> $DIR/auto-trait-leak.rs:24:16
    |
-LL |     send(before());
-   |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+LL | fn cycle1() -> impl Clone {
+   |                ^^^^^^^^^^
    |
-   = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
-   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:19:5: 19:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
-   = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
-note: required by `send`
-  --> $DIR/auto-trait-leak.rs:22:1
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:24:1
    |
-LL | fn send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
-  --> $DIR/auto-trait-leak.rs:28:5
-   |
-LL |     send(after());
-   |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+note: ...which requires processing `cycle2::{{exist-impl-Trait}}`...
+  --> $DIR/auto-trait-leak.rs:33:16
    |
-   = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
-   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:36:5: 36:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
-   = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
-note: required by `send`
-  --> $DIR/auto-trait-leak.rs:22:1
+LL | fn cycle2() -> impl Clone {
+   |                ^^^^^^^^^^
+note: ...which requires processing `cycle2`...
+  --> $DIR/auto-trait-leak.rs:33:1
    |
-LL | fn send<T: Send>(_: T) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+   = note: ...which again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle
 
-error[E0391]: cycle detected when processing `cycle1`
-  --> $DIR/auto-trait-leak.rs:42:1
+error[E0391]: cycle detected when processing `cycle1::{{exist-impl-Trait}}`
+  --> $DIR/auto-trait-leak.rs:24:16
    |
 LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^^
    |
+note: ...which requires processing `cycle1`...
+  --> $DIR/auto-trait-leak.rs:24:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires processing `cycle2::{{impl-Trait}}`...
-  --> $DIR/auto-trait-leak.rs:49:16
+note: ...which requires processing `cycle2::{{exist-impl-Trait}}`...
+  --> $DIR/auto-trait-leak.rs:33:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:49:1
+  --> $DIR/auto-trait-leak.rs:33:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires processing `cycle1::{{impl-Trait}}`...
-  --> $DIR/auto-trait-leak.rs:42:16
+   = note: ...which again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle
+
+error[E0277]: the trait bound `std::rc::Rc<std::string::String>: std::marker::Send` is not satisfied in `impl std::clone::Clone`
+  --> $DIR/auto-trait-leak.rs:27:5
    |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   = note: ...which again requires processing `cycle1`, completing the cycle
-note: cycle used when type-checking all item bodies
+LL |     send(cycle2().clone());
+   |     ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
+   |
+   = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
+   = note: required because it appears within the type `impl std::clone::Clone`
+note: required by `send`
+  --> $DIR/auto-trait-leak.rs:16:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.rs b/src/test/ui/impl-trait/auto-trait-leak2.rs
new file mode 100644 (file)
index 0000000..16310e6
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2016 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.
+
+// ignore-tidy-linelength
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+// Fast path, main can see the concrete type returned.
+fn before() -> impl Fn(i32) {
+    let p = Rc::new(Cell::new(0));
+    move |x| p.set(x)
+}
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+    send(before());
+    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+
+    send(after());
+    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+}
+
+// Deferred path, main has to wait until typeck finishes,
+// to check if the return type of after is Send.
+fn after() -> impl Fn(i32) {
+    let p = Rc::new(Cell::new(0));
+    move |x| p.set(x)
+}
+
diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr
new file mode 100644 (file)
index 0000000..59623ae
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
+  --> $DIR/auto-trait-leak2.rs:25:5
+   |
+LL |     send(before());
+   |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+   |
+   = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
+   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:19:5: 19:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
+   = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
+note: required by `send`
+  --> $DIR/auto-trait-leak2.rs:22:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
+  --> $DIR/auto-trait-leak2.rs:28:5
+   |
+LL |     send(after());
+   |     ^^^^ `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+   |
+   = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
+   = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:36:5: 36:22 p:std::rc::Rc<std::cell::Cell<i32>>]`
+   = note: required because it appears within the type `impl std::ops::Fn<(i32,)>`
+note: required by `send`
+  --> $DIR/auto-trait-leak2.rs:22:1
+   |
+LL | fn send<T: Send>(_: T) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index b65e477f21f9002ccd62ba3314a34d207d1ddb77..71fccc022b71bcc2bb029e009283869044ff371b 100644 (file)
@@ -50,23 +50,4 @@ fn leak(self) -> i32 { self }
 }
 
 fn main() {
-    let _: u32 = hide(0_u32);
-    //~^ ERROR mismatched types
-    //~| expected type `u32`
-    //~| found type `impl Foo`
-    //~| expected u32, found anonymized type
-
-    let _: i32 = Leak::leak(hide(0_i32));
-    //~^ ERROR mismatched types
-    //~| expected type `i32`
-    //~| found type `<impl Foo as Leak>::T`
-    //~| expected i32, found associated type
-
-    let mut x = (hide(0_u32), hide(0_i32));
-    x = (x.1,
-    //~^ ERROR mismatched types
-    //~| expected u32, found i32
-         x.0);
-    //~^ ERROR mismatched types
-    //~| expected i32, found u32
 }
index 0f310df07142b27e3931b86ef299394d9657903b..e277d4e28cb2ba6a974341d92e032e59c996ceb7 100644 (file)
@@ -15,43 +15,7 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
 
-error[E0308]: mismatched types
-  --> $DIR/equality.rs:53:18
-   |
-LL |     let _: u32 = hide(0_u32);
-   |                  ^^^^^^^^^^^ expected u32, found anonymized type
-   |
-   = note: expected type `u32`
-              found type `impl Foo`
-
-error[E0308]: mismatched types
-  --> $DIR/equality.rs:59:18
-   |
-LL |     let _: i32 = Leak::leak(hide(0_i32));
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found associated type
-   |
-   = note: expected type `i32`
-              found type `<impl Foo as Leak>::T`
-
-error[E0308]: mismatched types
-  --> $DIR/equality.rs:66:10
-   |
-LL |     x = (x.1,
-   |          ^^^ expected u32, found i32
-   |
-   = note: expected type `impl Foo` (u32)
-              found type `impl Foo` (i32)
-
-error[E0308]: mismatched types
-  --> $DIR/equality.rs:69:10
-   |
-LL |          x.0);
-   |          ^^^ expected i32, found u32
-   |
-   = note: expected type `impl Foo` (i32)
-              found type `impl Foo` (u32)
-
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
 Some errors occurred: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs
new file mode 100644 (file)
index 0000000..ec3dc15
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2016 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(specialization)]
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+trait Leak: Sized {
+    type T;
+    fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+    default type T = ();
+    default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+    type T = i32;
+    fn leak(self) -> i32 { self }
+}
+
+fn main() {
+    let _: u32 = hide(0_u32);
+    //~^ ERROR mismatched types
+    //~| expected type `u32`
+    //~| found type `impl Foo`
+    //~| expected u32, found anonymized type
+
+    let _: i32 = Leak::leak(hide(0_i32));
+    //~^ ERROR mismatched types
+    //~| expected type `i32`
+    //~| found type `<impl Foo as Leak>::T`
+    //~| expected i32, found associated type
+
+    let mut x = (hide(0_u32), hide(0_i32));
+    x = (x.1,
+    //~^ ERROR mismatched types
+    //~| expected u32, found i32
+         x.0);
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
new file mode 100644 (file)
index 0000000..e4ff2f6
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:35:18
+   |
+LL |     let _: u32 = hide(0_u32);
+   |                  ^^^^^^^^^^^ expected u32, found anonymized type
+   |
+   = note: expected type `u32`
+              found type `impl Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:41:18
+   |
+LL |     let _: i32 = Leak::leak(hide(0_i32));
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found associated type
+   |
+   = note: expected type `i32`
+              found type `<impl Foo as Leak>::T`
+
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:48:10
+   |
+LL |     x = (x.1,
+   |          ^^^ expected u32, found i32
+   |
+   = note: expected type `impl Foo` (u32)
+              found type `impl Foo` (i32)
+
+error[E0308]: mismatched types
+  --> $DIR/equality2.rs:51:10
+   |
+LL |          x.0);
+   |          ^^^ expected i32, found u32
+   |
+   = note: expected type `impl Foo` (i32)
+              found type `impl Foo` (u32)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index a0ad8ee43809504182577774403ef7b09b505c02..067b5ebc6c4addc7740103e23446f6eb8baff3db 100644 (file)
@@ -18,7 +18,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't0)) i32))
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32))
            ]
 
 note: No external requirements
index 6aeb8d4fcd5c3123d9615d41c000336b460917ab..dba27f16e8cac234111f4735c8e9c9db2086c057 100644 (file)
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) i32))
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32))
            ]
 
 note: No external requirements
index 26ad522f6f4d66dcb5cac58d976d9dca6b2d90dd..c88f0efba6f4b6192f76692242950c6f6d08d91f 100644 (file)
@@ -24,7 +24,7 @@ LL | |         },
    |
    = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
            ]
 
 note: No external requirements
index 537e951ddf1c398c7327240ccb3079e41a702919..840b4071a8776e172ef175e4d07bc22ad273d734 100644 (file)
@@ -18,7 +18,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
            ]
    = note: number of external vids: 3
    = note: where '_#1r: '_#2r
index 93ae534b25c95a790719a7a8f59e3deb39b5cc20..ac4efecc8ac075a12b59a4a0fbe645a26c2c4fa4 100644 (file)
@@ -23,7 +23,7 @@ LL | |     })
    |
    = note: defining type: DefId(0/1:12 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
            ]
 
 note: No external requirements
@@ -51,7 +51,7 @@ LL | |     })
    |
    = note: defining type: DefId(0/1:13 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
            ]
    = note: number of external vids: 2
    = note: where '_#1r: '_#0r
index 4081ec65f8030000fc02d279283aea58b472797f..93a7c1a0c6c33a0c3165040276dbeae87f7d6bd9 100644 (file)
@@ -18,22 +18,21 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't2)) u32>))
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) u32>))
            ]
    = note: number of external vids: 2
    = note: where '_#1r: '_#0r
 
 error: free region `ReFree(DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]), BrNamed(crate0:DefIndex(1:16), 'a))` does not outlive free region `ReStatic`
-  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
    |
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-   |  _______________________________________________^
+LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
 LL | |         //~^ ERROR does not outlive free region
 LL | |
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
 LL | |     });
-   | |_____^
+   | |______^
 
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1
index 7a745bb09642f0c4e1d770e53064138f3e4d1028..c62f62efda361795c70e2426b4f14881f3eac9ce 100644 (file)
@@ -18,22 +18,21 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
            ]
    = note: number of external vids: 3
    = note: where '_#1r: '_#0r
 
 error: free region `ReFree(DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]), BrNamed(crate0:DefIndex(1:16), 'a))` does not outlive free region `ReStatic`
-  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
    |
-LL |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-   |  _______________________________________________^
+LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
 LL | |         //~^ ERROR does not outlive free region
 LL | |         // Only works if 'x: 'y:
 LL | |         demand_y(x, y, x.get())
 LL | |         //~^ WARNING not reporting region error due to nll
 LL | |     });
-   | |_____^
+   | |______^
 
 note: No external requirements
   --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1
index 4e2680585e9d444984e57e7a9ffb59d3aed19e4f..cf5f4d415b669cc88ddec9555edd86ef80b30c75 100644 (file)
@@ -18,7 +18,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
            ]
    = note: number of external vids: 3
    = note: where '_#1r: '_#2r
index 2cc9a11dbc3cf11175ef1aa85fc25647bfea903f..ef27218e0899fd38f4304ec66f85a8e8f9410e18 100644 (file)
@@ -16,7 +16,7 @@ LL | |         },
    |
    = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
            ]
    = note: number of external vids: 3
    = note: where '_#1r: '_#2r
index e53ece696c9f09488325c63efb718d9c38e66494..8b6cd2ea432dbea8744477b808c8fc113b2fb300 100644 (file)
@@ -24,7 +24,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
            ]
 
 note: No external requirements
index 45f308b2323cd79738d79ae7368b8ff1c3e27e34..2fd6ce50095fc15be47af685158640eef93c8a36 100644 (file)
@@ -24,7 +24,7 @@ LL | |     });
    |
    = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
            ]
 
 note: No external requirements
index 9e6fd28565e691ce85e23ccb384686c53f560235..04ff4aaadf875bc036b78aa8a53a65af70f7b214 100644 (file)
@@ -18,7 +18,7 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
    |
    = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) i32
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32
            ]
 
 note: No external requirements
index 70bda0d7a186f8effd2dce92fa4e901997786ce1..0ada3fb64ae80da3434b905e504091a59bda0647 100644 (file)
@@ -25,7 +25,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: defining type: DefId(0/1:14 ~ ty_param_closure_approximate_lower_bound[317d]::generic[0]::{{closure}}[0]) with closure substs [
                T,
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) T))
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T))
            ]
    = note: number of external vids: 2
    = note: where T: '_#1r
@@ -55,7 +55,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: defining type: DefId(0/1:17 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]::{{closure}}[0]) with closure substs [
                T,
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex { index: 0 }, BrNamed(crate0:DefIndex(0:0), 's)) T))
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) T))
            ]
    = note: number of external vids: 2
    = note: where T: '_#1r