]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #55349 - bjorn3:rustc_mir_collect_and_partition_mono_items, r=oli-obk
authorbors <bors@rust-lang.org>
Sun, 4 Nov 2018 12:20:55 +0000 (12:20 +0000)
committerbors <bors@rust-lang.org>
Sun, 4 Nov 2018 12:20:55 +0000 (12:20 +0000)
Move collect_and_partition_mono_items to rustc_mir

Most of the logic of it is inside rustc_mir anyway.

Also removes the single function crate rustc_metadata_utils. Based on #55225

160 files changed:
src/bootstrap/builder.rs
src/bootstrap/cache.rs
src/bootstrap/mk/Makefile.in
src/doc/unstable-book/src/language-features/trait-alias.md [new file with mode: 0644]
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/canonical/mod.rs
src/librustc/infer/canonical/query_response.rs
src/librustc/infer/canonical/substitute.rs
src/librustc/infer/combine.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/freshen.rs
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/infer/outlives/verify.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/infer/sub.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/query/normalize.rs
src/librustc/traits/query/outlives_bounds.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc/traits/util.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/instance.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/callee.rs
src/librustc_codegen_llvm/debuginfo/type_names.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_driver/test.rs
src/librustc_lint/types.rs
src/librustc_metadata/decoder.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/lower_128bit.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/lib.rs
src/librustc_traits/chalk_context.rs
src/librustc_traits/dropck_outlives.rs
src/librustc_traits/implied_outlives_bounds.rs
src/librustc_traits/lowering/environment.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/outlives/utils.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/storage.js
src/librustdoc/test.rs
src/libsyntax/ast.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/test/run-pass/traits/trait-alias-bounds.rs [new file with mode: 0644]
src/test/run-pass/traits/trait-alias-object-type.rs [new file with mode: 0644]
src/test/run-pass/traits/trait-alias-syntax.rs [new file with mode: 0644]
src/test/rustdoc/assoc-consts.rs
src/test/rustdoc/auxiliary/enum_primitive.rs [new file with mode: 0644]
src/test/rustdoc/manual_impl.rs
src/test/rustdoc/no-stack-overflow-25295.rs [new file with mode: 0644]
src/test/ui/codemap_tests/two_files.stderr
src/test/ui/derive-uninhabited-enum-38885.rs [new file with mode: 0644]
src/test/ui/derive-uninhabited-enum-38885.stderr [new file with mode: 0644]
src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
src/test/ui/feature-gates/feature-gate-trait-alias.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-trait-alias.stderr [new file with mode: 0644]
src/test/ui/if/if-without-block.rs
src/test/ui/if/if-without-block.stderr
src/test/ui/issue-51602.stderr
src/test/ui/issues/issue-39848.stderr
src/test/ui/label/label_break_value_illegal_uses.stderr
src/test/ui/missing/missing-block-hint.stderr
src/test/ui/missing/missing-semicolon-warning.stderr
src/test/ui/parser/doc-before-identifier.rs
src/test/ui/parser/doc-before-identifier.stderr
src/test/ui/parser/doc-comment-in-if-statement.rs [new file with mode: 0644]
src/test/ui/parser/doc-comment-in-if-statement.stderr [new file with mode: 0644]
src/test/ui/parser/import-from-rename.stderr
src/test/ui/parser/import-glob-rename.stderr
src/test/ui/parser/issue-17904-2.rs
src/test/ui/parser/issue-17904-2.stderr
src/test/ui/parser/unsized.rs
src/test/ui/parser/unsized.stderr
src/test/ui/parser/virtual-structs.rs
src/test/ui/parser/virtual-structs.stderr
src/test/ui/resolve/issue-3907.stderr
src/test/ui/resolve/issue-5035.stderr
src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.fixed [new file with mode: 0644]
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.rs
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
src/test/ui/single-use-lifetime/one-use-in-fn-argument.rs
src/test/ui/single-use-lifetime/one-use-in-fn-argument.stderr
src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs
src/test/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr
src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs
src/test/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr
src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.rs
src/test/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr
src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed
src/test/ui/single-use-lifetime/zero-uses-in-fn.rs
src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr
src/test/ui/single-use-lifetime/zero-uses-in-impl.stderr
src/test/ui/trait-alias-fail.rs [deleted file]
src/test/ui/trait-alias-fail.stderr [deleted file]
src/test/ui/traits/trait-alias-impl.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-impl.stderr [new file with mode: 0644]
src/test/ui/traits/trait-alias-objects.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-objects.stderr [new file with mode: 0644]
src/test/ui/traits/trait-alias-wf.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-wf.stderr [new file with mode: 0644]
src/test/ui/traits/trait-alias.rs [deleted file]
src/test/ui/traits/trait-alias.stderr [deleted file]
src/tools/clippy
src/tools/error_index_generator/main.rs
src/tools/publish_toolstate.py

index c7121cb03692f4403c8002e42949302944420be1..900f336ef8cdc1dd06f8c9bc1dd42c7f225ecf6e 100644 (file)
@@ -130,7 +130,7 @@ fn one<P: Into<PathBuf>>(path: P) -> PathSet {
     fn has(&self, needle: &Path) -> bool {
         match self {
             PathSet::Set(set) => set.iter().any(|p| p.ends_with(needle)),
-            PathSet::Suite(_) => false,
+            PathSet::Suite(suite) => suite.ends_with(needle),
         }
     }
 
@@ -1849,7 +1849,7 @@ fn test_with_no_doc_stage0() {
         );
 
         // Ensure we don't build any compiler artifacts.
-        assert!(builder.cache.all::<compile::Rustc>().is_empty());
+        assert!(!builder.cache.contains::<compile::Rustc>());
         assert_eq!(
             first(builder.cache.all::<test::Crate>()),
             &[test::Crate {
@@ -1861,4 +1861,34 @@ fn test_with_no_doc_stage0() {
             },]
         );
     }
+
+    #[test]
+    fn test_exclude() {
+        let mut config = configure(&[], &[]);
+        config.exclude = vec![
+            "src/test/run-pass".into(),
+            "src/tools/tidy".into(),
+        ];
+        config.cmd = Subcommand::Test {
+            paths: Vec::new(),
+            test_args: Vec::new(),
+            rustc_args: Vec::new(),
+            fail_fast: true,
+            doc_tests: DocTests::No,
+            bless: false,
+            compare_mode: None,
+        };
+
+        let build = Build::new(config);
+        let builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
+
+        // Ensure we have really excluded run-pass & tidy
+        assert!(!builder.cache.contains::<test::RunPass>());
+        assert!(!builder.cache.contains::<test::Tidy>());
+
+        // Ensure other tests are not affected.
+        assert!(builder.cache.contains::<test::RunPassFullDeps>());
+        assert!(builder.cache.contains::<test::RustdocUi>());
+    }
 }
index fd9a1be207280f788e98f0bacfebbe861c40679d..0b561a3523f2b483460d8549b75f4913d7a6bcd0 100644 (file)
@@ -286,4 +286,9 @@ pub fn all<S: Ord + Copy + Step>(&mut self) -> Vec<(S, S::Output)> {
         v.sort_by_key(|&(a, _)| a);
         v
     }
+
+    #[cfg(test)]
+    pub fn contains<S: Step>(&self) -> bool {
+        self.0.borrow().contains_key(&TypeId::of::<S>())
+    }
 }
index bcf2f6a675e02715340fcd22a0350c9d264703ef..862fbbf1f286bce28a9d4e65415e3e7b3aeceed0 100644 (file)
@@ -85,7 +85,12 @@ check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
 check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu:
        $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl
 
-TESTS_IN_2 := src/test/run-pass src/test/compile-fail src/test/run-pass-fulldeps
+TESTS_IN_2 := \
+       src/test/ui \
+       src/test/run-pass \
+       src/test/compile-fail \
+       src/test/run-pass-fulldeps \
+       src/tools/linkchecker
 
 appveyor-subset-1:
        $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %)
diff --git a/src/doc/unstable-book/src/language-features/trait-alias.md b/src/doc/unstable-book/src/language-features/trait-alias.md
new file mode 100644 (file)
index 0000000..4f2db04
--- /dev/null
@@ -0,0 +1,34 @@
+# `trait_alias`
+
+The tracking issue for this feature is: [#41517]
+
+[#41417]: https://github.com/rust-lang/rust/issues/41517
+
+------------------------
+
+The `trait_alias` feature adds support for trait aliases. These allow aliases
+to be created for one or more traits (currently just a single regular trait plus
+any number of auto-traits), and used wherever traits would normally be used as
+either bounds or trait objects.
+
+```rust
+#![feature(trait_alias)]
+
+trait Foo = std::fmt::Debug + Send;
+trait Bar = Foo + Sync;
+
+// Use trait alias as bound on type parameter.
+fn foo<T: Foo>(v: &T) {
+    println!("{:?}", v);
+}
+
+pub fn main() {
+    foo(&1);
+
+    // Use trait alias for trait objects.
+    let a: &Bar = &123;
+    println!("{:?}", a);
+    let b = Box::new(456) as Box<dyn Foo>;
+    println!("{:?}", b);
+}
+```
index b6621e0962cf6e384e044a0f59bb42b87c3709b8..e558d945516713d2f690d4b698cbadc6a3c6a886 100644 (file)
@@ -4875,23 +4875,24 @@ fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::
         let node = match qpath {
             hir::QPath::Resolved(None, path) => {
                 // Turn trait object paths into `TyKind::TraitObject` instead.
-                if let Def::Trait(_) = path.def {
-                    let principal = hir::PolyTraitRef {
-                        bound_generic_params: hir::HirVec::new(),
-                        trait_ref: hir::TraitRef {
-                            path: path.and_then(|path| path),
-                            ref_id: id.node_id,
-                            hir_ref_id: id.hir_id,
-                        },
-                        span,
-                    };
+                match path.def {
+                    Def::Trait(_) | Def::TraitAlias(_) => {
+                        let principal = hir::PolyTraitRef {
+                            bound_generic_params: hir::HirVec::new(),
+                            trait_ref: hir::TraitRef {
+                                path: path.and_then(|path| path),
+                                ref_id: id.node_id,
+                                hir_ref_id: id.hir_id,
+                            },
+                            span,
+                        };
 
-                    // The original ID is taken by the `PolyTraitRef`,
-                    // so the `Ty` itself needs a different one.
-                    id = self.next_id();
-                    hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
-                } else {
-                    hir::TyKind::Path(hir::QPath::Resolved(None, path))
+                        // The original ID is taken by the `PolyTraitRef`,
+                        // so the `Ty` itself needs a different one.
+                        id = self.next_id();
+                        hir::TyKind::TraitObject(hir_vec![principal], self.elided_dyn_bound(span))
+                    }
+                    _ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),
                 }
             }
             _ => hir::TyKind::Path(qpath),
index f5f8e3512a0eaa9ad355f3290c0088d6ea5d3666..cf7a7abf95a6c55956d041461c18f04c615dc93d 100644 (file)
@@ -301,9 +301,7 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                     ItemKind::Struct(..) => Some(Def::Struct(def_id())),
                     ItemKind::Union(..) => Some(Def::Union(def_id())),
                     ItemKind::Trait(..) => Some(Def::Trait(def_id())),
-                    ItemKind::TraitAlias(..) => {
-                        bug!("trait aliases are not yet implemented (see issue #41517)")
-                    },
+                    ItemKind::TraitAlias(..) => Some(Def::TraitAlias(def_id())),
                     ItemKind::ExternCrate(_) |
                     ItemKind::Use(..) |
                     ItemKind::ForeignMod(..) |
index 0c93b86ee4d11771778483c29142b54e369ac371..7d25ecedb4e046de7389bc32359f47dbd45dfc5f 100644 (file)
@@ -100,9 +100,6 @@ fn hash_stable<W: StableHasherResult>(&self,
             ty::ReEmpty => {
                 // No variant fields to hash for these ...
             }
-            ty::ReCanonical(c) => {
-                c.hash_stable(hcx, hasher);
-            }
             ty::ReLateBound(db, ty::BrAnon(i)) => {
                 db.hash_stable(hcx, hasher);
                 i.hash_stable(hcx, hasher);
@@ -147,7 +144,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundTyIndex {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
@@ -852,6 +849,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             Param(param_ty) => {
                 param_ty.hash_stable(hcx, hasher);
             }
+            Bound(bound_ty) => {
+                bound_ty.hash_stable(hcx, hasher);
+            }
             Foreign(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
@@ -869,7 +869,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     FreshTy(a),
     FreshIntTy(a),
     FreshFloatTy(a),
-    BoundTy(a),
 });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
@@ -1119,6 +1118,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             &VtableClosure(ref table_closure) => table_closure.hash_stable(hcx, hasher),
             &VtableFnPointer(ref table_fn_pointer) => table_fn_pointer.hash_stable(hcx, hasher),
             &VtableGenerator(ref table_generator) => table_generator.hash_stable(hcx, hasher),
+            &VtableTraitAlias(ref table_alias) => table_alias.hash_stable(hcx, hasher),
         }
     }
 }
@@ -1227,6 +1227,22 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+for traits::VtableTraitAliasData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let traits::VtableTraitAliasData {
+            alias_def_id,
+            substs,
+            ref nested,
+        } = *self;
+        alias_def_id.hash_stable(hcx, hasher);
+        substs.hash_stable(hcx, hasher);
+        nested.hash_stable(hcx, hasher);
+    }
+}
+
 impl_stable_hash_for!(
     impl<'tcx, V> for struct infer::canonical::Canonical<'tcx, V> {
         max_universe, variables, value
index cc6e4df07103307c72730fb6865b1ad7ffffc944..61a861a8a1cd8b193a08c3a269c1641973498d31 100644 (file)
@@ -23,7 +23,7 @@
 use std::sync::atomic::Ordering;
 use ty::fold::{TypeFoldable, TypeFolder};
 use ty::subst::Kind;
-use ty::{self, BoundTy, BoundTyIndex, Lift, List, Ty, TyCtxt, TypeFlags};
+use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
@@ -277,9 +277,11 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     query_state: &'cx mut OriginalQueryValues<'tcx>,
     // Note that indices is only used once `var_values` is big enough to be
     // heap-allocated.
-    indices: FxHashMap<Kind<'tcx>, BoundTyIndex>,
+    indices: FxHashMap<Kind<'tcx>, BoundVar>,
     canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
     needs_canonical_flags: TypeFlags,
+
+    binder_index: ty::DebruijnIndex,
 }
 
 impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> {
@@ -287,11 +289,23 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
         self.tcx
     }
 
+    fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+        where T: TypeFoldable<'tcx>
+    {
+        self.binder_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.binder_index.shift_out(1);
+        t
+    }
+
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReLateBound(..) => {
-                // leave bound regions alone
-                r
+            ty::ReLateBound(index, ..) => {
+                if index >= self.binder_index {
+                    bug!("escaping late bound region during canonicalization")
+                } else {
+                    r
+                }
             }
 
             ty::ReVar(vid) => {
@@ -317,8 +331,8 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             | ty::ReErased => self.canonicalize_region_mode
                 .canonicalize_free_region(self, r),
 
-            ty::ReClosureBound(..) | ty::ReCanonical(_) => {
-                bug!("canonical region encountered during canonicalization")
+            ty::ReClosureBound(..) => {
+                bug!("closure bound region encountered during canonicalization")
             }
         }
     }
@@ -337,8 +351,12 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 bug!("encountered a fresh type during canonicalization")
             }
 
-            ty::Infer(ty::BoundTy(_)) => {
-                bug!("encountered a canonical type during canonicalization")
+            ty::Bound(bound_ty) => {
+                if bound_ty.index >= self.binder_index {
+                    bug!("escaping bound type during canonicalization")
+                } else {
+                    t
+                }
             }
 
             ty::Closure(..)
@@ -389,12 +407,6 @@ fn canonicalize<V>(
     where
         V: TypeFoldable<'tcx> + Lift<'gcx>,
     {
-        debug_assert!(
-            !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS),
-            "canonicalizing a canonical value: {:?}",
-            value,
-        );
-
         let needs_canonical_flags = if canonicalize_region_mode.any() {
             TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
         } else {
@@ -422,6 +434,7 @@ fn canonicalize<V>(
             variables: SmallVec::new(),
             query_state,
             indices: FxHashMap::default(),
+            binder_index: ty::INNERMOST,
         };
         let out_value = value.fold_with(&mut canonicalizer);
 
@@ -455,7 +468,7 @@ fn canonicalize<V>(
     /// or returns an existing variable if `kind` has already been
     /// seen. `kind` is expected to be an unbound variable (or
     /// potentially a free region).
-    fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy {
+    fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundVar {
         let Canonicalizer {
             variables,
             query_state,
@@ -475,7 +488,7 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy
             // direct linear search of `var_values`.
             if let Some(idx) = var_values.iter().position(|&k| k == kind) {
                 // `kind` is already present in `var_values`.
-                BoundTyIndex::new(idx)
+                BoundVar::new(idx)
             } else {
                 // `kind` isn't present in `var_values`. Append it. Likewise
                 // for `info` and `variables`.
@@ -490,11 +503,11 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy
                     *indices = var_values
                         .iter()
                         .enumerate()
-                        .map(|(i, &kind)| (kind, BoundTyIndex::new(i)))
+                        .map(|(i, &kind)| (kind, BoundVar::new(i)))
                         .collect();
                 }
                 // The cv is the index of the appended element.
-                BoundTyIndex::new(var_values.len() - 1)
+                BoundVar::new(var_values.len() - 1)
             }
         } else {
             // `var_values` is large. Do a hashmap search via `indices`.
@@ -502,14 +515,11 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy
                 variables.push(info);
                 var_values.push(kind);
                 assert_eq!(variables.len(), var_values.len());
-                BoundTyIndex::new(variables.len() - 1)
+                BoundVar::new(variables.len() - 1)
             })
         };
 
-        BoundTy {
-            level: ty::INNERMOST,
-            var,
-        }
+        var
     }
 
     /// Shorthand helper that creates a canonical region variable for
@@ -552,9 +562,12 @@ fn canonical_var_for_region(
         info: CanonicalVarInfo,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
-        let b = self.canonical_var(info, r.into());
-        debug_assert_eq!(ty::INNERMOST, b.level);
-        self.tcx().mk_region(ty::ReCanonical(b.var))
+        let var = self.canonical_var(info, r.into());
+        let region = ty::ReLateBound(
+            self.binder_index,
+            ty::BoundRegion::BrAnon(var.as_u32())
+        );
+        self.tcx().mk_region(region)
     }
 
     /// Given a type variable `ty_var` of the given kind, first check
@@ -570,9 +583,8 @@ fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>)
             let info = CanonicalVarInfo {
                 kind: CanonicalVarKind::Ty(ty_kind),
             };
-            let b = self.canonical_var(info, ty_var.into());
-            debug_assert_eq!(ty::INNERMOST, b.level);
-            self.tcx().mk_infer(ty::InferTy::BoundTy(b))
+            let var = self.canonical_var(info, ty_var.into());
+            self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
         }
     }
 }
index f2b7c6e0d0d986760762fae0e4f42cf39f654ee6..f7eb7118f412f6f0c55676c6966eff30628f8104 100644 (file)
@@ -20,7 +20,7 @@
 //! - a map M (of type `CanonicalVarValues`) from those canonical
 //!   variables back to the original.
 //!
-//! We can then do queries using T2. These will give back constriants
+//! We can then do queries using T2. These will give back constraints
 //! on the canonical variables which can be translated, using the map
 //! M, into constraints in our source context. This process of
 //! translating the results back is done by the
@@ -40,7 +40,7 @@
 use syntax::source_map::Span;
 use ty::fold::TypeFoldable;
 use ty::subst::Kind;
-use ty::{self, BoundTyIndex, Lift, List, Region, TyCtxt};
+use ty::{self, BoundVar, Lift, List, Region, TyCtxt};
 
 mod canonicalizer;
 
@@ -73,7 +73,7 @@ impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {}
 /// canonicalized query response.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
 pub struct CanonicalVarValues<'tcx> {
-    pub var_values: IndexVec<BoundTyIndex, Kind<'tcx>>,
+    pub var_values: IndexVec<BoundVar, Kind<'tcx>>,
 }
 
 /// When we canonicalize a value to form a query, we wind up replacing
@@ -337,7 +337,7 @@ fn instantiate_canonical_vars(
         variables: &List<CanonicalVarInfo>,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> CanonicalVarValues<'tcx> {
-        let var_values: IndexVec<BoundTyIndex, Kind<'tcx>> = variables
+        let var_values: IndexVec<BoundVar, Kind<'tcx>> = variables
             .iter()
             .map(|info| self.instantiate_canonical_var(span, *info, &universe_map))
             .collect();
@@ -456,10 +456,10 @@ impl<'a, 'tcx, R> Lift<'tcx> for QueryResponse<'a, R> {
     } where R: Lift<'tcx>
 }
 
-impl<'tcx> Index<BoundTyIndex> for CanonicalVarValues<'tcx> {
+impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
     type Output = Kind<'tcx>;
 
-    fn index(&self, value: BoundTyIndex) -> &Kind<'tcx> {
+    fn index(&self, value: BoundVar) -> &Kind<'tcx> {
         &self.var_values[value]
     }
 }
index b3ce5eb7e56c26dee4fac39f0f845186b99824e2..f4607f7a9092f4ee01bd6a31b534bc06a88a1d84 100644 (file)
@@ -35,7 +35,7 @@
 use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
-use ty::{self, BoundTyIndex, Lift, Ty, TyCtxt};
+use ty::{self, BoundVar, Lift, Ty, TyCtxt};
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
@@ -273,7 +273,7 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
         for (index, original_value) in original_values.var_values.iter().enumerate() {
             // ...with the value `v_r` of that variable from the query.
             let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
-                &v.var_values[BoundTyIndex::new(index)]
+                &v.var_values[BoundVar::new(index)]
             });
             match (original_value.unpack(), result_value.unpack()) {
                 (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
@@ -308,11 +308,14 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
         // ...also include the other query region constraints from the query.
         output_query_region_constraints.extend(
             query_response.value.region_constraints.iter().filter_map(|r_c| {
-                let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
-                let k1 = substitute_value(self.tcx, &result_subst, &k1);
-                let r2 = substitute_value(self.tcx, &result_subst, &r2);
+                let r_c = substitute_value(self.tcx, &result_subst, r_c);
+
+                // Screen out `'a: 'a` cases -- we skip the binder here but
+                // only care the inner values to one another, so they are still at
+                // consistent binding levels.
+                let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
                 if k1 != r2.into() {
-                    Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)))
+                    Some(r_c)
                 } else {
                     None
                 }
@@ -423,7 +426,7 @@ fn query_response_substitution_guess<R>(
         // is directly equal to one of the canonical variables in the
         // result, then we can type the corresponding value from the
         // input. See the example above.
-        let mut opt_values: IndexVec<BoundTyIndex, Option<Kind<'tcx>>> =
+        let mut opt_values: IndexVec<BoundVar, Option<Kind<'tcx>>> =
             IndexVec::from_elem_n(None, query_response.variables.len());
 
         // In terms of our example above, we are iterating over pairs like:
@@ -432,16 +435,22 @@ fn query_response_substitution_guess<R>(
             match result_value.unpack() {
                 UnpackedKind::Type(result_value) => {
                     // e.g., here `result_value` might be `?0` in the example above...
-                    if let ty::Infer(ty::InferTy::BoundTy(b)) = result_value.sty {
-                        // in which case we would set `canonical_vars[0]` to `Some(?U)`.
+                    if let ty::Bound(b) = result_value.sty {
+                        // ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
+
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(b.index, ty::INNERMOST);
                         opt_values[b.var] = Some(*original_value);
                     }
                 }
                 UnpackedKind::Lifetime(result_value) => {
                     // e.g., here `result_value` might be `'?1` in the example above...
-                    if let &ty::RegionKind::ReCanonical(index) = result_value {
-                        // in which case we would set `canonical_vars[0]` to `Some('static)`.
-                        opt_values[index] = Some(*original_value);
+                    if let &ty::RegionKind::ReLateBound(index, br) = result_value {
+                        // ... in which case we would set `canonical_vars[0]` to `Some('static)`.
+
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(index, ty::INNERMOST);
+                        opt_values[br.assert_bound_var()] = Some(*original_value);
                     }
                 }
             }
@@ -457,7 +466,7 @@ fn query_response_substitution_guess<R>(
                 .enumerate()
                 .map(|(index, info)| {
                     if info.is_existential() {
-                        match opt_values[BoundTyIndex::new(index)] {
+                        match opt_values[BoundVar::new(index)] {
                             Some(k) => k,
                             None => self.instantiate_canonical_var(cause.span, *info, |u| {
                                 universe_map[u.as_usize()]
@@ -496,7 +505,7 @@ fn unify_query_response_substitution_guess<R>(
         // canonical variable; this is taken from
         // `query_response.var_values` after applying the substitution
         // `result_subst`.
-        let substituted_query_response = |index: BoundTyIndex| -> Kind<'tcx> {
+        let substituted_query_response = |index: BoundVar| -> Kind<'tcx> {
             query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
         };
 
@@ -523,22 +532,23 @@ fn query_region_constraints_into_obligations<'a>(
             unsubstituted_region_constraints
                 .iter()
                 .map(move |constraint| {
-                    let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
-                    let k1 = substitute_value(self.tcx, result_subst, k1);
-                    let r2 = substitute_value(self.tcx, result_subst, r2);
+                    let constraint = substitute_value(self.tcx, result_subst, constraint);
+                    let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
 
                     Obligation::new(
                         cause.clone(),
                         param_env,
                         match k1.unpack() {
                             UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
-                                ty::Binder::dummy(
+                                ty::Binder::bind(
                                     ty::OutlivesPredicate(r1, r2)
-                            )),
+                                )
+                            ),
                             UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
-                                ty::Binder::dummy(ty::OutlivesPredicate(
-                                    t1, r2
-                            )))
+                                ty::Binder::bind(
+                                    ty::OutlivesPredicate(t1, r2)
+                                )
+                            ),
                         }
                     )
                 })
@@ -552,12 +562,12 @@ fn unify_canonical_vars(
         cause: &ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         variables1: &OriginalQueryValues<'tcx>,
-        variables2: impl Fn(BoundTyIndex) -> Kind<'tcx>,
+        variables2: impl Fn(BoundVar) -> Kind<'tcx>,
     ) -> InferResult<'tcx, ()> {
         self.commit_if_ok(|_| {
             let mut obligations = vec![];
             for (index, value1) in variables1.var_values.iter().enumerate() {
-                let value2 = variables2(BoundTyIndex::new(index));
+                let value2 = variables2(BoundVar::new(index));
 
                 match (value1.unpack(), value2.unpack()) {
                     (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
@@ -620,11 +630,11 @@ pub fn make_query_outlives<'tcx>(
             }
             Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
         })
-        .map(ty::Binder::dummy) // no bound regions in the code above
+        .map(ty::Binder::dummy) // no bound vars in the code above
         .chain(
             outlives_obligations
                 .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
-                .map(ty::Binder::dummy), // no bound regions in the code above
+                .map(ty::Binder::dummy) // no bound vars in the code above
         )
         .collect();
 
index 03441c3dee35e2ba40c49fb6b7e12bbe19fa3afa..b8c1ed236c0ba17aededa8aff24c46641052eb22 100644 (file)
@@ -17,9 +17,9 @@
 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
 
 use infer::canonical::{Canonical, CanonicalVarValues};
-use ty::fold::{TypeFoldable, TypeFolder};
+use ty::fold::TypeFoldable;
 use ty::subst::UnpackedKind;
-use ty::{self, Ty, TyCtxt, TypeFlags};
+use ty::{self, TyCtxt};
 
 impl<'tcx, V> Canonical<'tcx, V> {
     /// Instantiate the wrapped value, replacing each canonical value
@@ -64,51 +64,22 @@ pub(super) fn substitute_value<'a, 'tcx, T>(
     T: TypeFoldable<'tcx>,
 {
     if var_values.var_values.is_empty() {
-        debug_assert!(!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS));
-        value.clone()
-    } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
         value.clone()
     } else {
-        value.fold_with(&mut CanonicalVarValuesSubst { tcx, var_values })
-    }
-}
-
-struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
-    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-    var_values: &'cx CanonicalVarValues<'tcx>,
-}
-
-impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
-        self.tcx
-    }
-
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        match t.sty {
-            ty::Infer(ty::InferTy::BoundTy(b)) => {
-                debug_assert_eq!(ty::INNERMOST, b.level);
-                match self.var_values.var_values[b.var].unpack() {
-                    UnpackedKind::Type(ty) => ty,
-                    r => bug!("{:?} is a type but value is {:?}", b, r),
-                }
+        let fld_r = |br: ty::BoundRegion| {
+            match var_values.var_values[br.assert_bound_var()].unpack() {
+                UnpackedKind::Lifetime(l) => l,
+                r => bug!("{:?} is a region but value is {:?}", br, r),
             }
-            _ => {
-                if !t.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
-                    t
-                } else {
-                    t.super_fold_with(self)
-                }
+        };
+
+        let fld_t = |bound_ty: ty::BoundTy| {
+            match var_values.var_values[bound_ty.var].unpack() {
+                UnpackedKind::Type(ty) => ty,
+                r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
             }
-        }
-    }
+        };
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match r {
-            ty::RegionKind::ReCanonical(c) => match self.var_values.var_values[*c].unpack() {
-                UnpackedKind::Lifetime(l) => l,
-                r => bug!("{:?} is a region but value is {:?}", c, r),
-            },
-            _ => r.super_fold_with(self),
-        }
+        tcx.replace_escaping_bound_vars(value, fld_r, fld_t)
     }
 }
index 0ee03bc4c6e00902d0026a78e23b8be1c63a0a5d..f13210926a79b77361e21c83c2d5f3b814b7d88f 100644 (file)
@@ -485,7 +485,6 @@ fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
                 }
             }
 
-            ty::ReCanonical(..) |
             ty::ReClosureBound(..) => {
                 span_bug!(
                     self.span,
index d19c495af3b9685c11240ace5d55bfc4dcc9b4ad..1963d366e7a66d5d5daa5ba3111852663416bd6c 100644 (file)
@@ -152,7 +152,7 @@ pub fn note_and_explain_region(
             }
 
             // We shouldn't encounter an error message with ReClosureBound.
-            ty::ReCanonical(..) | ty::ReClosureBound(..) => {
+            ty::ReClosureBound(..) => {
                 bug!("encountered unexpected ReClosureBound: {:?}", region,);
             }
         };
index 1647f259db9fb27e855ae0db4fe08cdb39480104..b53444992fa216972d4e32b36bbdabd7d36e27d4 100644 (file)
@@ -114,7 +114,6 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 self.tcx().types.re_erased
             }
 
-            ty::ReCanonical(..) |
             ty::ReClosureBound(..) => {
                 bug!(
                     "encountered unexpected region: {:?}",
@@ -171,8 +170,8 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 t
             }
 
-            ty::Infer(ty::BoundTy(..)) =>
-                bug!("encountered canonical ty during freshening"),
+            ty::Bound(..) =>
+                bug!("encountered bound ty during freshening"),
 
             ty::Generator(..) |
             ty::Bool |
index 8f28e9a320df24854af4fb9088387a458310da74..75f503d3bcfb4b331780bcd1e50cc6177f564c9b 100644 (file)
@@ -260,9 +260,7 @@ fn expand_node(
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
         let tcx = self.tcx();
         match (a, b) {
-            (&ty::ReCanonical(..), _)
-            | (_, &ty::ReCanonical(..))
-            | (&ty::ReClosureBound(..), _)
+            (&ty::ReClosureBound(..), _)
             | (_, &ty::ReClosureBound(..))
             | (&ReLateBound(..), _)
             | (_, &ReLateBound(..))
index 5db850f1588b6a24bd4c784d56a28e64751a95a6..523f03c2cfc4773afc81f9c008a0fa7294bb5f92 100644 (file)
@@ -305,7 +305,7 @@ pub fn type_must_outlive(
             ty, region, origin
         );
 
-        assert!(!ty.has_escaping_regions());
+        assert!(!ty.has_escaping_bound_vars());
 
         let components = self.tcx.outlives_components(ty);
         self.components_must_outlive(origin, components, region);
index e1db295b7e14d6e10dcfa3fd006ccbb5ff3b1403..88d45671b9afdfab86538d6a1b6d6345cfeed3ba 100644 (file)
@@ -323,7 +323,7 @@ fn collect_outlives_from_predicate_list(
         predicates
             .into_iter()
             .filter_map(|p| p.as_ref().to_opt_type_outlives())
-            .filter_map(|p| p.no_late_bound_regions())
+            .filter_map(|p| p.no_bound_vars())
             .filter(move |p| compare_ty(p.0))
     }
 }
index c82603bf5605788cbd6db75fb9708df35087c6cc..46b12d01829e7089835c2090715878efd39a79f9 100644 (file)
@@ -833,10 +833,6 @@ fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
             ty::RePlaceholder(placeholder) => placeholder.universe,
             ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
             ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
-            ty::ReCanonical(..) => bug!(
-                "region_universe(): encountered canonical region {:?}",
-                region
-            ),
         }
     }
 
index 048810c042722f552de6844b3e5862f1d13b9a53..3b0f9a5e545fde48e157985c952b8b510f9cb83a 100644 (file)
@@ -84,8 +84,8 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 // Shouldn't have any LBR here, so we can safely put
                 // this under a binder below without fear of accidental
                 // capture.
-                assert!(!a.has_escaping_regions());
-                assert!(!b.has_escaping_regions());
+                assert!(!a.has_escaping_bound_vars());
+                assert!(!b.has_escaping_bound_vars());
 
                 // can't make progress on `A <: B` if both A and B are
                 // type variables, so record an obligation. We also
index 361abb1689619e1cd92ee0557b54cfef1f17b292..79cd8b21f1b6aa7d7fd68499f4f8f604c4ca3553 100644 (file)
@@ -447,6 +447,17 @@ fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap {
     map
 }
 
+/// In traits, there is an implicit `Self` type parameter which comes before the generics.
+/// We have to account for this when computing the index of the other generic parameters.
+/// This function returns whether there is such an implicit parameter defined on the given item.
+fn sub_items_have_self_param(node: &hir::ItemKind) -> bool {
+    match *node {
+        hir::ItemKind::Trait(..) |
+        hir::ItemKind::TraitAlias(..) => true,
+        _ => false,
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
         NestedVisitorMap::All(&self.tcx.hir)
@@ -522,8 +533,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     hir::ItemKind::Impl(..) => true,
                     _ => false,
                 };
-                // These kinds of items have only early bound lifetime parameters.
-                let mut index = if let hir::ItemKind::Trait(..) = item.node {
+                // These kinds of items have only early-bound lifetime parameters.
+                let mut index = if sub_items_have_self_param(&item.node) {
                     1 // Self comes before lifetimes
                 } else {
                     0
@@ -1443,23 +1454,101 @@ fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
     /// helper method to determine the span to remove when suggesting the
     /// deletion of a lifetime
     fn lifetime_deletion_span(&self, name: ast::Ident, generics: &hir::Generics) -> Option<Span> {
-        if generics.params.len() == 1 {
-            // if sole lifetime, remove the `<>` brackets
-            Some(generics.span)
-        } else {
-            generics.params.iter().enumerate().find_map(|(i, param)| {
-                if param.name.ident() == name {
-                    // We also want to delete a leading or trailing comma
-                    // as appropriate
-                    if i >= generics.params.len() - 1 {
-                        Some(generics.params[i - 1].span.shrink_to_hi().to(param.span))
-                    } else {
-                        Some(param.span.to(generics.params[i + 1].span.shrink_to_lo()))
+        generics.params.iter().enumerate().find_map(|(i, param)| {
+            if param.name.ident() == name {
+                let mut in_band = false;
+                if let hir::GenericParamKind::Lifetime { kind } = param.kind {
+                    if let hir::LifetimeParamKind::InBand = kind {
+                        in_band = true;
                     }
+                }
+                if in_band {
+                    Some(param.span)
                 } else {
-                    None
+                    if generics.params.len() == 1 {
+                        // if sole lifetime, remove the entire `<>` brackets
+                        Some(generics.span)
+                    } else {
+                        // if removing within `<>` brackets, we also want to
+                        // delete a leading or trailing comma as appropriate
+                        if i >= generics.params.len() - 1 {
+                            Some(generics.params[i - 1].span.shrink_to_hi().to(param.span))
+                        } else {
+                            Some(param.span.to(generics.params[i + 1].span.shrink_to_lo()))
+                        }
+                    }
                 }
-            })
+            } else {
+                None
+            }
+        })
+    }
+
+    // helper method to issue suggestions from `fn rah<'a>(&'a T)` to `fn rah(&T)`
+    fn suggest_eliding_single_use_lifetime(
+        &self, err: &mut DiagnosticBuilder<'_>, def_id: DefId, lifetime: &hir::Lifetime
+    ) {
+        // FIXME: future work: also suggest `impl Foo<'_>` for `impl<'a> Foo<'a>`
+        let name = lifetime.name.ident();
+        let mut remove_decl = None;
+        if let Some(parent_def_id) = self.tcx.parent(def_id) {
+            if let Some(generics) = self.tcx.hir.get_generics(parent_def_id) {
+                remove_decl = self.lifetime_deletion_span(name, generics);
+            }
+        }
+
+        let mut remove_use = None;
+        let mut find_arg_use_span = |inputs: &hir::HirVec<hir::Ty>| {
+            for input in inputs {
+                if let hir::TyKind::Rptr(lt, _) = input.node {
+                    if lt.name.ident() == name {
+                        // include the trailing whitespace between the ampersand and the type name
+                        let lt_through_ty_span = lifetime.span.to(input.span.shrink_to_hi());
+                        remove_use = Some(
+                            self.tcx.sess.source_map()
+                                .span_until_non_whitespace(lt_through_ty_span)
+                        );
+                        break;
+                    }
+                }
+            }
+        };
+        if let Node::Lifetime(hir_lifetime) = self.tcx.hir.get(lifetime.id) {
+            if let Some(parent) = self.tcx.hir.find(self.tcx.hir.get_parent(hir_lifetime.id)) {
+                match parent {
+                    Node::Item(item) => {
+                        if let hir::ItemKind::Fn(decl, _, _, _) = &item.node {
+                            find_arg_use_span(&decl.inputs);
+                        }
+                    },
+                    Node::ImplItem(impl_item) => {
+                        if let hir::ImplItemKind::Method(sig, _) = &impl_item.node {
+                            find_arg_use_span(&sig.decl.inputs);
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
+
+        if let (Some(decl_span), Some(use_span)) = (remove_decl, remove_use) {
+            // if both declaration and use deletion spans start at the same
+            // place ("start at" because the latter includes trailing
+            // whitespace), then this is an in-band lifetime
+            if decl_span.shrink_to_lo() == use_span.shrink_to_lo() {
+                err.span_suggestion_with_applicability(
+                    use_span,
+                    "elide the single-use lifetime",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.multipart_suggestion_with_applicability(
+                    "elide the single-use lifetime",
+                    vec![(decl_span, String::new()), (use_span, String::new())],
+                    Applicability::MachineApplicable,
+                );
+            }
         }
     }
 
@@ -1515,14 +1604,26 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                         _ => None,
                     } {
                         debug!("id = {:?} span = {:?} name = {:?}", node_id, span, name);
+
+                        if name == keywords::UnderscoreLifetime.ident() {
+                            continue;
+                        }
+
                         let mut err = self.tcx.struct_span_lint_node(
                             lint::builtin::SINGLE_USE_LIFETIMES,
                             id,
                             span,
                             &format!("lifetime parameter `{}` only used once", name),
                         );
-                        err.span_label(span, "this lifetime...");
-                        err.span_label(lifetime.span, "...is used only here");
+
+                        if span == lifetime.span {
+                            // spans are the same for in-band lifetime declarations
+                            err.span_label(span, "this lifetime is only used here");
+                        } else {
+                            err.span_label(span, "this lifetime...");
+                            err.span_label(lifetime.span, "...is used only here");
+                        }
+                        self.suggest_eliding_single_use_lifetime(&mut err, def_id, lifetime);
                         err.emit();
                     }
                 }
@@ -1555,7 +1656,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                                 if let Some(span) = unused_lt_span {
                                     err.span_suggestion_with_applicability(
                                         span,
-                                        "remove it",
+                                        "elide the unused lifetime",
                                         String::new(),
                                         Applicability::MachineApplicable,
                                     );
@@ -1602,8 +1703,8 @@ fn visit_early_late<F>(
         let mut index = 0;
         if let Some(parent_id) = parent_id {
             let parent = self.tcx.hir.expect_item(parent_id);
-            if let hir::ItemKind::Trait(..) = parent.node {
-                index += 1; // Self comes first.
+            if sub_items_have_self_param(&parent.node) {
+                index += 1; // Self comes before lifetimes
             }
             match parent.node {
                 hir::ItemKind::Trait(_, _, ref generics, ..)
index 50ca6ca78ab3aa5b81dd85670bf025e8101673e2..e87e425762d56eaf96399c1468eb1250f04f9eb4 100644 (file)
@@ -683,8 +683,8 @@ pub fn evaluate_nested_obligations<
                 }
                 &ty::Predicate::TypeOutlives(ref binder) => {
                     match (
-                        binder.no_late_bound_regions(),
-                        binder.map_bound_ref(|pred| pred.0).no_late_bound_regions(),
+                        binder.no_bound_vars(),
+                        binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
                     ) {
                         (None, Some(t_a)) => {
                             select.infcx().register_region_obligation_with_cause(
index 817e9ffcbb55d786bbcb9ab7f56269472241d038..71b77909b82a8e3de49c1cfbdc483a1c9822232b 100644 (file)
@@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
             false
         }
 
-        ty::Infer(..) => match in_crate {
+        ty::Bound(..) | ty::Infer(..) => match in_crate {
             InCrate::Local => false,
             // The inference variable might be unified with a local
             // type in that remote crate.
index 18ee98c515fb27dc643442f890b7b5d207aac060..e6ae0557c33af04c46663da4809ed645f544cfac 100644 (file)
@@ -280,7 +280,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::Generator(..) => Some(18),
                 ty::Foreign(..) => Some(19),
                 ty::GeneratorWitness(..) => Some(20),
-                ty::Infer(..) | ty::Error => None,
+                ty::Bound(..) | ty::Infer(..) | ty::Error => None,
                 ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             }
         }
index cfa77b210e857769f2a3e8f58640bc11367bffab..aea956461f27bea7252ff69d43a72af19d10d377 100644 (file)
@@ -143,7 +143,7 @@ fn normalize_projection_type<'a, 'gcx>(&mut self,
         debug!("normalize_projection_type(projection_ty={:?})",
                projection_ty);
 
-        debug_assert!(!projection_ty.has_escaping_regions());
+        debug_assert!(!projection_ty.has_escaping_bound_vars());
 
         // FIXME(#20304) -- cache
 
@@ -349,15 +349,15 @@ fn process_obligation(&mut self,
             }
 
             ty::Predicate::TypeOutlives(ref binder) => {
-                // Check if there are higher-ranked regions.
-                match binder.no_late_bound_regions() {
+                // Check if there are higher-ranked vars.
+                match binder.no_bound_vars() {
                     // If there are, inspect the underlying type further.
                     None => {
                         // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
                         let binder = binder.map_bound_ref(|pred| pred.0);
 
-                        // Check if the type has any bound regions.
-                        match binder.no_late_bound_regions() {
+                        // Check if the type has any bound vars.
+                        match binder.no_bound_vars() {
                             // If so, this obligation is an error (for now). Eventually we should be
                             // able to support additional cases here, like `for<'a> &'a str: 'a`.
                             // NOTE: this is duplicate-implemented between here and fulfillment.
index 6b2ec64668e9bbb006e1bbce46a7392ff0e9976a..b7512790bfb6913414c2e4d34c618b56c9012f19 100644 (file)
@@ -352,7 +352,7 @@ pub fn from_poly_domain_goal<'a>(
         domain_goal: PolyDomainGoal<'tcx>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ) -> GoalKind<'tcx> {
-        match domain_goal.no_late_bound_regions() {
+        match domain_goal.no_bound_vars() {
             Some(p) => p.into_goal(),
             None => GoalKind::Quantified(
                 QuantifierKind::Universal,
@@ -534,8 +534,11 @@ pub enum Vtable<'tcx, N> {
     /// Same as above, but for a fn pointer type with the given signature.
     VtableFnPointer(VtableFnPointerData<'tcx, N>),
 
-    /// Vtable automatically generated for a generator
+    /// Vtable automatically generated for a generator.
     VtableGenerator(VtableGeneratorData<'tcx, N>),
+
+    /// Vtable for a trait alias.
+    VtableTraitAlias(VtableTraitAliasData<'tcx, N>),
 }
 
 /// Identifies a particular impl in the source, along with a set of
@@ -605,6 +608,13 @@ pub struct VtableFnPointerData<'tcx, N> {
     pub nested: Vec<N>
 }
 
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+pub struct VtableTraitAliasData<'tcx, N> {
+    pub alias_def_id: DefId,
+    pub substs: &'tcx Substs<'tcx>,
+    pub nested: Vec<N>,
+}
+
 /// Creates predicate obligations from the generic bounds.
 pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
                                      param_env: ty::ParamEnv<'tcx>,
@@ -1067,6 +1077,7 @@ pub fn nested_obligations(self) -> Vec<N> {
             VtableGenerator(c) => c.nested,
             VtableObject(d) => d.nested,
             VtableFnPointer(d) => d.nested,
+            VtableTraitAlias(d) => d.nested,
         }
     }
 
@@ -1090,20 +1101,25 @@ pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M {
                 trait_def_id: d.trait_def_id,
                 nested: d.nested.into_iter().map(f).collect(),
             }),
-            VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
-                fn_ty: p.fn_ty,
-                nested: p.nested.into_iter().map(f).collect(),
+            VtableClosure(c) => VtableClosure(VtableClosureData {
+                closure_def_id: c.closure_def_id,
+                substs: c.substs,
+                nested: c.nested.into_iter().map(f).collect(),
             }),
             VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
                 generator_def_id: c.generator_def_id,
                 substs: c.substs,
                 nested: c.nested.into_iter().map(f).collect(),
             }),
-            VtableClosure(c) => VtableClosure(VtableClosureData {
-                closure_def_id: c.closure_def_id,
-                substs: c.substs,
-                nested: c.nested.into_iter().map(f).collect(),
-            })
+            VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
+                fn_ty: p.fn_ty,
+                nested: p.nested.into_iter().map(f).collect(),
+            }),
+            VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
+                alias_def_id: d.alias_def_id,
+                substs: d.substs,
+                nested: d.nested.into_iter().map(f).collect(),
+            }),
         }
     }
 }
index 4eda47d31ebb54cd11f5ecec427378ef3c7c0b56..a388c7eeb7e49ede897bbe130ffc07ffd4071d93 100644 (file)
 use super::Selection;
 use super::SelectionContext;
 use super::SelectionError;
-use super::VtableClosureData;
-use super::VtableGeneratorData;
-use super::VtableFnPointerData;
-use super::VtableImplData;
+use super::{VtableImplData, VtableClosureData, VtableGeneratorData, VtableFnPointerData};
 use super::util;
 
 use hir::def_id::DefId;
@@ -366,7 +363,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*)
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
                     Reveal::UserFacing => ty,
@@ -393,7 +390,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::Projection(ref data) if !data.has_escaping_regions() => { // (*)
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*)
 
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
@@ -1073,7 +1070,8 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
             super::VtableClosure(_) |
             super::VtableGenerator(_) |
             super::VtableFnPointer(_) |
-            super::VtableObject(_) => {
+            super::VtableObject(_) |
+            super::VtableTraitAlias(_) => {
                 debug!("assemble_candidates_from_impls: vtable={:?}",
                        vtable);
                 true
@@ -1235,7 +1233,8 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
             confirm_object_candidate(selcx, obligation, obligation_trait_ref),
         super::VtableAutoImpl(..) |
         super::VtableParam(..) |
-        super::VtableBuiltin(..) =>
+        super::VtableBuiltin(..) |
+        super::VtableTraitAlias(..) =>
             // we don't create Select candidates with this kind of resolution
             span_bug!(
                 obligation.cause.span,
@@ -1486,7 +1485,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
     impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
     -> Progress<'tcx>
 {
-    let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
+    let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
 
     let tcx = selcx.tcx();
     let param_env = obligation.param_env;
@@ -1619,7 +1618,7 @@ pub fn from_poly_projection_predicate(selcx: &mut SelectionContext<'cx, 'gcx, 't
         let infcx = selcx.infcx();
         // We don't do cross-snapshot caching of obligations with escaping regions,
         // so there's no cache key to use
-        predicate.no_late_bound_regions()
+        predicate.no_bound_vars()
             .map(|predicate| ProjectionCacheKey {
                 // We don't attempt to match up with a specific type-variable state
                 // from a specific call to `opt_normalize_projection_type` - if
index 8f7b0df8b95aa74f157d7cab5b1e42da2bb915d9..62317f074764f67248c11feff2203734d46e45a4 100644 (file)
@@ -252,6 +252,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         | ty::Param(_)
         | ty::Opaque(..)
         | ty::Infer(_)
+        | ty::Bound(..)
         | ty::Generator(..) => false,
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
index 4adb65dc58d917de255d7779c109a241ad676b12..59b086e35de310a0ae189d841b8e7270c007fec7 100644 (file)
@@ -100,7 +100,7 @@ fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> {
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => {
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
                 // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
@@ -138,7 +138,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::Projection(ref data) if !data.has_escaping_regions() => {
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
                 // (*)
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
index 99f557d44d9aa4e085cad074ed573aa4db34ad72..b3fae3bab347199ad0d95dd3d9d326725d53f056 100644 (file)
@@ -164,7 +164,7 @@ pub fn explicit_outlives_bounds<'tcx>(
             ty::Predicate::ClosureKind(..) |
             ty::Predicate::TypeOutlives(..) |
             ty::Predicate::ConstEvaluatable(..) => None,
-            ty::Predicate::RegionOutlives(ref data) => data.no_late_bound_regions().map(
+            ty::Predicate::RegionOutlives(ref data) => data.no_bound_vars().map(
                 |ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a),
             ),
         })
index ce515c4507772172102202516d52fd781f80c29e..312cd66dcc75c229b78b1d9d7a4d2b537b7eb55b 100644 (file)
 use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
 use super::{
     VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
-    VtableObject, VtableParam,
+    VtableObject, VtableParam, VtableTraitAlias,
 };
 use super::{
     VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
-    VtableGeneratorData, VtableImplData, VtableObjectData,
+    VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData,
 };
 
 use dep_graph::{DepKind, DepNodeIndex};
@@ -271,6 +271,8 @@ enum SelectionCandidate<'tcx> {
     /// types generated for a fn pointer type (e.g., `fn(int)->int`)
     FnPointerCandidate,
 
+    TraitAliasCandidate(DefId),
+
     ObjectCandidate,
 
     BuiltinObjectCandidate,
@@ -286,12 +288,13 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             ImplCandidate(def_id) => ImplCandidate(def_id),
             AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
             ProjectionCandidate => ProjectionCandidate,
+            ClosureCandidate => ClosureCandidate,
+            GeneratorCandidate => GeneratorCandidate,
             FnPointerCandidate => FnPointerCandidate,
+            TraitAliasCandidate(def_id) => TraitAliasCandidate(def_id),
             ObjectCandidate => ObjectCandidate,
             BuiltinObjectCandidate => BuiltinObjectCandidate,
             BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
-            ClosureCandidate => ClosureCandidate,
-            GeneratorCandidate => GeneratorCandidate,
 
             ParamCandidate(ref trait_ref) => {
                 return tcx.lift(trait_ref).map(ParamCandidate);
@@ -587,7 +590,7 @@ pub fn select(
         obligation: &TraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, Selection<'tcx>> {
         debug!("select({:?})", obligation);
-        debug_assert!(!obligation.predicate.has_escaping_regions());
+        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
 
@@ -690,7 +693,7 @@ fn evaluate_predicate_recursively<'o>(
 
         match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
-                debug_assert!(!t.has_escaping_regions());
+                debug_assert!(!t.has_escaping_bound_vars());
                 let obligation = obligation.with(t.clone());
                 self.evaluate_trait_predicate_recursively(previous_stack, obligation)
             }
@@ -722,9 +725,9 @@ fn evaluate_predicate_recursively<'o>(
             },
 
             ty::Predicate::TypeOutlives(ref binder) => {
-                assert!(!binder.has_escaping_regions());
-                // Check if the type has higher-ranked regions.
-                if binder.skip_binder().0.has_escaping_regions() {
+                assert!(!binder.has_escaping_bound_vars());
+                // Check if the type has higher-ranked vars.
+                if binder.skip_binder().0.has_escaping_bound_vars() {
                     // If so, this obligation is an error (for now). Eventually we should be
                     // able to support additional cases here, like `for<'a> &'a str: 'a`.
 
@@ -740,7 +743,7 @@ fn evaluate_predicate_recursively<'o>(
                         Ok(EvaluatedToErr)
                     }
                 } else {
-                    // If the type has no late bound regions, then if we assign all
+                    // If the type has no late bound vars, then if we assign all
                     // the inference variables in it to be 'static, then the type
                     // will be 'static itself.
                     //
@@ -1199,7 +1202,7 @@ fn candidate_from_obligation<'o>(
             "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
             cache_fresh_trait_pred, stack
         );
-        debug_assert!(!stack.obligation.predicate.has_escaping_regions());
+        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
 
         if let Some(c) =
             self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
@@ -1452,7 +1455,7 @@ fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<
         let predicate = self.infcx()
             .resolve_type_vars_if_possible(&obligation.predicate);
 
-        // ok to skip binder because of the nature of the
+        // OK to skip binder because of the nature of the
         // trait-ref-is-knowable check, which does not care about
         // bound regions
         let trait_ref = predicate.skip_binder().trait_ref;
@@ -1632,6 +1635,8 @@ fn assemble_candidates<'o>(
             ambiguous: false,
         };
 
+        self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?;
+
         // Other bounds. Consider both in-scope bounds from fn decl
         // and applicable impls. There is a certain set of precedence rules here.
         let def_id = obligation.predicate.def_id();
@@ -1801,7 +1806,7 @@ fn match_projection(
         placeholder_map: &infer::PlaceholderMap<'tcx>,
         snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
     ) -> bool {
-        debug_assert!(!skol_trait_ref.has_escaping_regions());
+        debug_assert!(!skol_trait_ref.has_escaping_bound_vars());
         if self.infcx
             .at(&obligation.cause, obligation.param_env)
             .sup(ty::Binder::dummy(skol_trait_ref), trait_bound)
@@ -1879,7 +1884,7 @@ fn assemble_generator_candidates(
             return Ok(());
         }
 
-        // ok to skip binder because the substs on generator types never
+        // OK to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         let self_ty = *obligation.self_ty().skip_binder();
@@ -1923,7 +1928,7 @@ fn assemble_closure_candidates(
             }
         };
 
-        // ok to skip binder because the substs on closure types never
+        // OK to skip binder because the substs on closure types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         match obligation.self_ty().skip_binder().sty {
@@ -1973,7 +1978,7 @@ fn assemble_fn_pointer_candidates(
             return Ok(());
         }
 
-        // ok to skip binder because what we are inspecting doesn't involve bound regions
+        // OK to skip binder because what we are inspecting doesn't involve bound regions
         let self_ty = *obligation.self_ty().skip_binder();
         match self_ty.sty {
             ty::Infer(ty::TyVar(_)) => {
@@ -2168,7 +2173,7 @@ fn assemble_candidates_for_unsizing(
         //     T: Trait
         // so it seems ok if we (conservatively) fail to accept that `Unsize`
         // obligation above. Should be possible to extend this in the future.
-        let source = match obligation.self_ty().no_late_bound_regions() {
+        let source = match obligation.self_ty().no_bound_vars() {
             Some(t) => t,
             None => {
                 // Don't add any candidates if there are bound regions.
@@ -2238,6 +2243,24 @@ fn assemble_candidates_for_unsizing(
         }
     }
 
+    fn assemble_candidates_for_trait_alias(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        // OK to skip binder here because the tests we do below do not involve bound regions
+        let self_ty = *obligation.self_ty().skip_binder();
+        debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
+
+        let def_id = obligation.predicate.def_id();
+
+        if ty::is_trait_alias(self.tcx(), def_id) {
+            candidates.vec.push(TraitAliasCandidate(def_id.clone()));
+        }
+
+        Ok(())
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // WINNOW
     //
@@ -2288,7 +2311,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                 | FnPointerCandidate
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
-                | BuiltinCandidate { .. } => {
+                | BuiltinCandidate { .. }
+                | TraitAliasCandidate(..) => {
                     // Global bounds from the where clause should be ignored
                     // here (see issue #50825). Otherwise, we have a where
                     // clause so don't go around looking for impls.
@@ -2318,7 +2342,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                 | FnPointerCandidate
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
-                | BuiltinCandidate { .. } => true,
+                | BuiltinCandidate { .. }
+                | TraitAliasCandidate(..) => true,
                 ObjectCandidate | ProjectionCandidate => {
                     // Arbitrarily give param candidates priority
                     // over projection and object candidates.
@@ -2445,7 +2470,7 @@ fn sized_conditions(
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::UnnormalizedProjection(..)
-            | ty::Infer(ty::BoundTy(_))
+            | ty::Bound(_)
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
             | ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2530,7 +2555,7 @@ fn copy_clone_conditions(
             }
 
             ty::UnnormalizedProjection(..)
-            | ty::Infer(ty::BoundTy(_))
+            | ty::Bound(_)
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
             | ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2573,7 +2598,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             | ty::Param(..)
             | ty::Foreign(..)
             | ty::Projection(..)
-            | ty::Infer(ty::BoundTy(_))
+            | ty::Bound(_)
             | ty::Infer(ty::TyVar(_))
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
@@ -2712,15 +2737,20 @@ fn confirm_candidate(
                 Ok(VtableParam(obligations))
             }
 
+            ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
+                obligation,
+                impl_def_id,
+            ))),
+
             AutoImplCandidate(trait_def_id) => {
                 let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
                 Ok(VtableAutoImpl(data))
             }
 
-            ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
-                obligation,
-                impl_def_id,
-            ))),
+            ProjectionCandidate => {
+                self.confirm_projection_candidate(obligation);
+                Ok(VtableParam(Vec::new()))
+            }
 
             ClosureCandidate => {
                 let vtable_closure = self.confirm_closure_candidate(obligation)?;
@@ -2732,13 +2762,14 @@ fn confirm_candidate(
                 Ok(VtableGenerator(vtable_generator))
             }
 
-            BuiltinObjectCandidate => {
-                // This indicates something like `(Trait+Send) :
-                // Send`. In this case, we know that this holds
-                // because that's what the object type is telling us,
-                // and there's really no additional obligations to
-                // prove and no types in particular to unify etc.
-                Ok(VtableParam(Vec::new()))
+            FnPointerCandidate => {
+                let data = self.confirm_fn_pointer_candidate(obligation)?;
+                Ok(VtableFnPointer(data))
+            }
+
+            TraitAliasCandidate(alias_def_id) => {
+                let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
+                Ok(VtableTraitAlias(data))
             }
 
             ObjectCandidate => {
@@ -2746,13 +2777,12 @@ fn confirm_candidate(
                 Ok(VtableObject(data))
             }
 
-            FnPointerCandidate => {
-                let data = self.confirm_fn_pointer_candidate(obligation)?;
-                Ok(VtableFnPointer(data))
-            }
-
-            ProjectionCandidate => {
-                self.confirm_projection_candidate(obligation);
+            BuiltinObjectCandidate => {
+                // This indicates something like `(Trait+Send) :
+                // Send`. In this case, we know that this holds
+                // because that's what the object type is telling us,
+                // and there's really no additional obligations to
+                // prove and no types in particular to unify etc.
                 Ok(VtableParam(Vec::new()))
             }
 
@@ -2865,7 +2895,7 @@ fn confirm_auto_impl_candidate(
         self.vtable_auto_impl(obligation, trait_def_id, types)
     }
 
-    /// See `confirm_auto_impl_candidate`
+    /// See `confirm_auto_impl_candidate`.
     fn vtable_auto_impl(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -2922,7 +2952,7 @@ fn confirm_impl_candidate(
         // this time not in a probe.
         self.in_snapshot(|this, snapshot| {
             let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot);
-            debug!("confirm_impl_candidate substs={:?}", substs);
+            debug!("confirm_impl_candidate: substs={:?}", substs);
             let cause = obligation.derived_cause(ImplDerivedObligation);
             this.vtable_impl(
                 impl_def_id,
@@ -2986,10 +3016,10 @@ fn confirm_object_candidate(
     ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
         debug!("confirm_object_candidate({:?})", obligation);
 
-        // FIXME skipping binder here seems wrong -- we should
-        // probably flatten the binder from the obligation and the
-        // binder from the object. Have to try to make a broken test
-        // case that results. -nmatsakis
+        // FIXME(nmatsakis) skipping binder here seems wrong -- we should
+        // probably flatten the binder from the obligation and the binder
+        // from the object. Have to try to make a broken test case that
+        // results.
         let self_ty = self.infcx
             .shallow_resolve(*obligation.self_ty().skip_binder());
         let poly_trait_ref = match self_ty.sty {
@@ -3041,7 +3071,7 @@ fn confirm_fn_pointer_candidate(
     ) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!("confirm_fn_pointer_candidate({:?})", obligation);
 
-        // ok to skip binder; it is reintroduced below
+        // OK to skip binder; it is reintroduced below
         let self_ty = self.infcx
             .shallow_resolve(*obligation.self_ty().skip_binder());
         let sig = self_ty.fn_sig(self.tcx());
@@ -3077,11 +3107,51 @@ fn confirm_fn_pointer_candidate(
         })
     }
 
+    fn confirm_trait_alias_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        alias_def_id: DefId,
+    ) -> VtableTraitAliasData<'tcx, PredicateObligation<'tcx>> {
+        debug!(
+            "confirm_trait_alias_candidate({:?}, {:?})",
+            obligation, alias_def_id
+        );
+
+        self.in_snapshot(|this, snapshot| {
+            let (predicate, placeholder_map) = this.infcx()
+                .replace_late_bound_regions_with_placeholders(&obligation.predicate);
+            let trait_ref = predicate.trait_ref;
+            let trait_def_id = trait_ref.def_id;
+            let substs = trait_ref.substs;
+
+            let trait_obligations = this.impl_or_trait_obligations(
+                obligation.cause.clone(),
+                obligation.recursion_depth,
+                obligation.param_env,
+                trait_def_id,
+                &substs,
+                placeholder_map,
+                snapshot,
+            );
+
+            debug!(
+                "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}",
+                trait_def_id, trait_obligations
+            );
+
+            VtableTraitAliasData {
+                alias_def_id,
+                substs: substs,
+                nested: trait_obligations,
+            }
+        })
+    }
+
     fn confirm_generator_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
     ) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // ok to skip binder because the substs on generator types never
+        // OK to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         let self_ty = self.infcx
@@ -3139,7 +3209,7 @@ fn confirm_closure_candidate(
             .fn_trait_kind(obligation.predicate.def_id())
             .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
 
-        // ok to skip binder because the substs on closure types never
+        // OK to skip binder because the substs on closure types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         let self_ty = self.infcx
@@ -3235,7 +3305,7 @@ fn confirm_builtin_unsize_candidate(
         // assemble_candidates_for_unsizing should ensure there are no late bound
         // regions here. See the comment there for more details.
         let source = self.infcx
-            .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap());
+            .shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
         let target = obligation
             .predicate
             .skip_binder()
index 24779a350d74bdfcf5382244a26db480dfd44560..e83d085971caa32ef52c6b2fbab491d53c5cc58d 100644 (file)
@@ -62,6 +62,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
 
             super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
+
+            super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
         }
     }
 }
@@ -70,7 +72,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "VtableImpl(impl_def_id={:?}, substs={:?}, nested={:?})",
+            "VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
             self.impl_def_id, self.substs, self.nested
         )
     }
@@ -80,7 +82,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "VtableGenerator(generator_def_id={:?}, substs={:?}, nested={:?})",
+            "VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
             self.generator_def_id, self.substs, self.nested
         )
     }
@@ -90,7 +92,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "VtableClosure(closure_def_id={:?}, substs={:?}, nested={:?})",
+            "VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
             self.closure_def_id, self.substs, self.nested
         )
     }
@@ -98,7 +100,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "VtableBuiltin(nested={:?})", self.nested)
+        write!(f, "VtableBuiltinData(nested={:?})", self.nested)
     }
 }
 
@@ -116,7 +118,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "VtableObject(upcast={:?}, vtable_base={}, nested={:?})",
+            "VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
             self.upcast_trait_ref, self.vtable_base, self.nested
         )
     }
@@ -126,12 +128,22 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             f,
-            "VtableFnPointer(fn_ty={:?}, nested={:?})",
+            "VtableFnPointerData(fn_ty={:?}, nested={:?})",
             self.fn_ty, self.nested
         )
     }
 }
 
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
+            self.alias_def_id, self.substs, self.nested
+        )
+    }
+}
+
 impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
@@ -321,6 +333,17 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                     nested,
                 })
             ),
+            traits::VtableTraitAlias(traits::VtableTraitAliasData {
+                alias_def_id,
+                substs,
+                nested,
+            }) => tcx.lift(&substs).map(|substs|
+                traits::VtableTraitAlias(traits::VtableTraitAliasData {
+                    alias_def_id,
+                    substs,
+                    nested,
+                })
+            ),
         }
     }
 }
@@ -386,6 +409,12 @@ impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> {
     } where N: TypeFoldable<'tcx>
 }
 
+BraceStructTypeFoldableImpl! {
+    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableTraitAliasData<'tcx, N> {
+        alias_def_id, substs, nested
+    } where N: TypeFoldable<'tcx>
+}
+
 EnumTypeFoldableImpl! {
     impl<'tcx, N> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
         (traits::VtableImpl)(a),
@@ -396,6 +425,7 @@ impl<'tcx, N> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
         (traits::VtableParam)(a),
         (traits::VtableBuiltin)(a),
         (traits::VtableObject)(a),
+        (traits::VtableTraitAlias)(a),
     } where N: TypeFoldable<'tcx>
 }
 
index 940cf736012ec0c0e2a9bde0ffdce2c34b5a0270..74f8d67ce04846a97c309a0573037530a4b98225 100644 (file)
@@ -333,7 +333,7 @@ fn new(base: I) -> FilterToTraits<I> {
     }
 }
 
-impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
+impl<'tcx,I:Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
     type Item = ty::PolyTraitRef<'tcx>;
 
     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
index 409665e47774529149696bc7423e70df2f0bf0b0..05d9d4bc37d79f540e3c887feb5fcc82ae099be7 100644 (file)
@@ -2243,7 +2243,7 @@ pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
             Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
-            Generator, GeneratorWitness, Dynamic, Closure, Tuple,
+            Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
             Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
index 855983042c026cec3b38f9d37029e052c0b3c72b..4737c72b1ef0f75bcc2c0ca382ef69c4b769ea54 100644 (file)
@@ -212,7 +212,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> Cow<'static, str> {
             ty::Infer(ty::TyVar(_)) => "inferred type".into(),
             ty::Infer(ty::IntVar(_)) => "integral variable".into(),
             ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(),
-            ty::Infer(ty::BoundTy(_)) |
+            ty::Bound(_) |
             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
index e6aaf8b1bb20604a7046b991d1f520b0afccc27a..380f95993f8fbab345f51c0c1a93e55ec70b425b 100644 (file)
@@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::Foreign(def_id) => {
             Some(ForeignSimplifiedType(def_id))
         }
-        ty::Infer(_) | ty::Error => None,
+        ty::Bound(..) | ty::Infer(_) | ty::Error => None,
     }
 }
 
index a7b21688fbeb3ab1f0e3a4dc6db32a9da5318e39..0764f363250dd8be56b0b7d846ff529fa0b2caca 100644 (file)
@@ -115,15 +115,17 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) {
                 self.add_substs(&substs.substs);
             }
 
+            &ty::Bound(bound_ty) => {
+                self.add_binder(bound_ty.index);
+            }
+
             &ty::Infer(infer) => {
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
                 self.add_flags(TypeFlags::HAS_TY_INFER);
                 match infer {
                     ty::FreshTy(_) |
                     ty::FreshIntTy(_) |
-                    ty::FreshFloatTy(_) |
-                    ty::BoundTy(_) => {
-                        self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
+                    ty::FreshFloatTy(_) => {
                     }
 
                     ty::TyVar(_) |
@@ -141,7 +143,7 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) {
             &ty::Projection(ref data) => {
                 // currently we can't normalize projections that
                 // include bound regions, so track those separately.
-                if !data.has_escaping_regions() {
+                if !data.has_escaping_bound_vars() {
                     self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
                 }
                 self.add_flags(TypeFlags::HAS_PROJECTION);
index 80dfd263af9af99e6dfe8d6753dc70e10d94f47b..8c822adf7b0236bd39b829d1cae1335f7a8c7169 100644 (file)
@@ -67,18 +67,18 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     /// bound by `binder` or bound by some binder outside of `binder`.
     /// 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 })
+    fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
+        self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder })
     }
 
     /// True if this `self` has any regions that escape `binder` (and
     /// hence are not bound by it).
-    fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
-        self.has_regions_bound_at_or_above(binder.shifted_in(1))
+    fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
+        self.has_vars_bound_at_or_above(binder.shifted_in(1))
     }
 
-    fn has_escaping_regions(&self) -> bool {
-        self.has_regions_bound_at_or_above(ty::INNERMOST)
+    fn has_escaping_bound_vars(&self) -> bool {
+        self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
@@ -416,11 +416,10 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Late-bound region replacer
+// Bound vars replacer
 
-// Replaces the escaping regions in a type.
-
-struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+/// Replaces the escaping bound vars (late bound regions or bound types) in a type.
+struct BoundVarReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
     /// As with `RegionFolder`, represents the index of a binder *just outside*
@@ -428,7 +427,82 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     current_index: ty::DebruijnIndex,
 
     fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
-    map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>
+    fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> ty::Ty<'tcx> + 'a),
+}
+
+impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> {
+    fn new<F, G>(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        fld_r: &'a mut F,
+        fld_t: &'a mut G
+    ) -> Self
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>
+    {
+        BoundVarReplacer {
+            tcx,
+            current_index: ty::INNERMOST,
+            fld_r,
+            fld_t,
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
+
+    fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
+        self.current_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.current_index.shift_out(1);
+        t
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        match t.sty {
+            ty::Bound(bound_ty) => {
+                if bound_ty.index == self.current_index {
+                    let fld_t = &mut self.fld_t;
+                    let ty = fld_t(bound_ty);
+                    ty::fold::shift_vars(
+                        self.tcx,
+                        &ty,
+                        self.current_index.as_u32()
+                    )
+                } else {
+                    t
+                }
+            }
+            _ => {
+                if !t.has_vars_bound_at_or_above(self.current_index) {
+                    // Nothing more to substitute.
+                    t
+                } else {
+                    t.super_fold_with(self)
+                }
+            }
+        }
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match *r {
+            ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
+                let fld_r = &mut self.fld_r;
+                let region = fld_r(br);
+                if let ty::ReLateBound(debruijn1, br) = *region {
+                    // If the callback returns a late-bound region,
+                    // that region should always use the INNERMOST
+                    // debruijn index. Then we adjust it to the
+                    // correct depth.
+                    assert_eq!(debruijn1, ty::INNERMOST);
+                    self.tcx.mk_region(ty::ReLateBound(debruijn, br))
+                } else {
+                    region
+                }
+            }
+            _ => r
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// same `BoundRegion` will reuse the previous result.  A map is
     /// returned at the end with each bound region and the free region
     /// that replaced it.
-    pub fn replace_late_bound_regions<T,F>(self,
+    ///
+    /// This method only replaces late bound regions and the result may still
+    /// contain escaping bound types.
+    pub fn replace_late_bound_regions<T, F>(
+        self,
         value: &Binder<T>,
-        mut f: F)
-        -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
-        where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
-              T : TypeFoldable<'tcx>,
+        mut fld_r: F
+    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              T: TypeFoldable<'tcx>
     {
-        let mut replacer = RegionReplacer::new(self, &mut f);
+        let mut map = BTreeMap::new();
+        let mut real_fldr = |br| {
+            *map.entry(br).or_insert_with(|| fld_r(br))
+        };
+
+        // identity for bound types
+        let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
+
+        let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t);
         let result = value.skip_binder().fold_with(&mut replacer);
-        (result, replacer.map)
+        (result, map)
+    }
+
+    /// Replace all escaping bound vars. The `fld_r` closure replaces escaping
+    /// bound regions while the `fld_t` closure replaces escaping bound types.
+    pub fn replace_escaping_bound_vars<T, F, G>(
+        self,
+        value: &T,
+        mut fld_r: F,
+        mut fld_t: G
+    ) -> T
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
+              T: TypeFoldable<'tcx>
+    {
+        if !value.has_escaping_bound_vars() {
+            value.clone()
+        } else {
+            let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t);
+            let result = value.fold_with(&mut replacer);
+            result
+        }
+    }
+
+    /// Replace all types or regions bound by the given `Binder`. The `fld_r`
+    /// closure replaces bound regions while the `fld_t` closure replaces bound
+    /// types.
+    pub fn replace_bound_vars<T, F, G>(
+        self,
+        value: &Binder<T>,
+        fld_r: F,
+        fld_t: G
+    ) -> T
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
+              T: TypeFoldable<'tcx>
+    {
+        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
     }
 
     /// Replace any late-bound regions bound in `value` with
@@ -549,21 +672,33 @@ pub fn anonymize_late_bound_regions<T>(self, sig: &Binder<T>) -> Binder<T>
     }
 }
 
-impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> {
-    fn new<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fld_r: &'a mut F)
-              -> RegionReplacer<'a, 'gcx, 'tcx>
-        where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>
-    {
-        RegionReplacer {
+///////////////////////////////////////////////////////////////////////////
+// Shifter
+//
+// Shifts the De Bruijn indices on all escaping bound vars by a
+// fixed amount. Useful in substitution or when otherwise introducing
+// a binding level that is not intended to capture the existing bound
+// vars. See comment on `shift_vars_through_binders` method in
+// `subst.rs` for more details.
+
+struct Shifter<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+
+    current_index: ty::DebruijnIndex,
+    amount: u32,
+}
+
+impl Shifter<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, amount: u32) -> Self {
+        Shifter {
             tcx,
             current_index: ty::INNERMOST,
-            fld_r,
-            map: BTreeMap::default()
+            amount,
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
@@ -573,64 +708,48 @@ fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binde
         t
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.has_regions_bound_at_or_above(self.current_index) {
-            return t;
-        }
-
-        t.super_fold_with(self)
-    }
-
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
-                let fld_r = &mut self.fld_r;
-                let region = *self.map.entry(br).or_insert_with(|| fld_r(br));
-                if let ty::ReLateBound(debruijn1, br) = *region {
-                    // If the callback returns a late-bound region,
-                    // that region should always use the INNERMOST
-                    // debruijn index. Then we adjust it to the
-                    // correct depth.
-                    assert_eq!(debruijn1, ty::INNERMOST);
-                    self.tcx.mk_region(ty::ReLateBound(debruijn, br))
+            ty::ReLateBound(debruijn, br) => {
+                if self.amount == 0 || debruijn < self.current_index {
+                    r
                 } else {
-                    region
+                    let shifted = ty::ReLateBound(debruijn.shifted_in(self.amount), br);
+                    self.tcx.mk_region(shifted)
                 }
             }
             _ => r
         }
     }
-}
 
-///////////////////////////////////////////////////////////////////////////
-// Region shifter
-//
-// Shifts the De Bruijn indices on all escaping bound regions by a
-// fixed amount. Useful in substitution or when otherwise introducing
-// a binding level that is not intended to capture the existing bound
-// regions. See comment on `shift_regions_through_binders` method in
-// `subst.rs` for more details.
+    fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
+        match ty.sty {
+            ty::Bound(bound_ty) => {
+                if self.amount == 0 || bound_ty.index < self.current_index {
+                    ty
+                } else {
+                    let shifted = ty::BoundTy {
+                        index: bound_ty.index.shifted_in(self.amount),
+                        var: bound_ty.var,
+                        kind: bound_ty.kind,
+                    };
+                    self.tcx.mk_ty(ty::Bound(shifted))
+                }
+            }
 
-pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
-    match region {
-        ty::ReLateBound(debruijn, br) => {
-            ty::ReLateBound(debruijn.shifted_in(amount), br)
-        }
-        _ => {
-            region
+            _ => ty.super_fold_with(self),
         }
     }
 }
 
-pub fn shift_region_ref<'a, 'gcx, 'tcx>(
+pub fn shift_region<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     region: ty::Region<'tcx>,
-    amount: u32)
-    -> ty::Region<'tcx>
-{
+    amount: u32
+) -> ty::Region<'tcx> {
     match region {
-        &ty::ReLateBound(debruijn, br) if amount > 0 => {
-            tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
+        ty::ReLateBound(debruijn, br) if amount > 0 => {
+            tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br))
         }
         _ => {
             region
@@ -638,20 +757,19 @@ pub fn shift_region_ref<'a, 'gcx, 'tcx>(
     }
 }
 
-pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                        amount: u32,
-                                        value: &T) -> T
-    where T: TypeFoldable<'tcx>
-{
-    debug!("shift_regions(value={:?}, amount={})",
+pub fn shift_vars<'a, 'gcx, 'tcx, T>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    value: &T,
+    amount: u32
+) -> T where T: TypeFoldable<'tcx> {
+    debug!("shift_vars(value={:?}, amount={})",
            value, amount);
 
-    value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
-        shift_region_ref(tcx, region, amount)
-    }))
+    value.fold_with(&mut Shifter::new(tcx, amount))
 }
 
-/// An "escaping region" is a bound region whose binder is not part of `t`.
+/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
+/// bound region or a bound type.
 ///
 /// So, for example, consider a type like the following, which has two binders:
 ///
@@ -663,24 +781,24 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
 /// fn type*, that type has an escaping region: `'a`.
 ///
-/// Note that what I'm calling an "escaping region" is often just called a "free region". However,
-/// we already use the term "free region". It refers to the regions that we use to represent bound
-/// regions on a fn definition while we are typechecking its body.
+/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
+/// we already use the term "free var". It refers to the regions or types that we use to represent
+/// bound regions or type params on a fn definition while we are typechecking its body.
 ///
 /// To clarify, conceptually there is no particular difference between
-/// an "escaping" region and a "free" region. However, there is a big
+/// an "escaping" var and a "free" var. However, there is a big
 /// difference in practice. Basically, when "entering" a binding
 /// level, one is generally required to do some sort of processing to
-/// a bound region, such as replacing it with a fresh/placeholder
-/// region, or making an entry in the environment to represent the
-/// scope to which it is attached, etc. An escaping region represents
-/// a bound region for which this processing has not yet been done.
-struct HasEscapingRegionsVisitor {
+/// a bound var, such as replacing it with a fresh/placeholder
+/// var, or making an entry in the environment to represent the
+/// scope to which it is attached, etc. An escaping var represents
+/// a bound var for which this processing has not yet been done.
+struct HasEscapingVarsVisitor {
     /// Anything bound by `outer_index` or "above" is escaping
     outer_index: ty::DebruijnIndex,
 }
 
-impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
+impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
         self.outer_index.shift_in(1);
         let result = t.super_visit_with(self);
@@ -693,7 +811,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         // `outer_index`, that means that `t` contains some content
         // bound at `outer_index` or above (because
         // `outer_exclusive_binder` is always 1 higher than the
-        // content in `t`). Therefore, `t` has some escaping regions.
+        // content in `t`). Therefore, `t` has some escaping vars.
         t.outer_exclusive_binder > self.outer_index
     }
 
index 041565c8b5a07ba6834e2e5bebbabf52373adf44..b6691df39c120ccebeee7eef6692e609802447ab 100644 (file)
@@ -213,7 +213,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl<'a, 'b, 'tcx> Instance<'tcx> {
     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
                -> Instance<'tcx> {
-        assert!(!substs.has_escaping_regions(),
+        assert!(!substs.has_escaping_bound_vars(),
                 "substs of instance {:?} not normalized for codegen: {:?}",
                 def_id, substs);
         Instance { def: InstanceDef::Item(def_id), substs: substs }
@@ -400,7 +400,9 @@ fn resolve_associated_item<'a, 'tcx>(
                 None
             }
         }
-        traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
+        traits::VtableAutoImpl(..) |
+        traits::VtableParam(..) |
+        traits::VtableTraitAlias(..) => None
     }
 }
 
index 7153c729d1542b439d8dcec805ca5a8cccf0a37c..d44ba03084159ebe6a320e1e41d8f75a77f6b421 100644 (file)
@@ -519,6 +519,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         ty::Param(_) |
         ty::Opaque(..) |
         ty::Infer(_) |
+        ty::Bound(..) |
         ty::Error |
         ty::GeneratorWitness(..) |
         ty::Never |
index 05d4aeb6ddec4b0fa2964e409f52860a50d623bf..55005721617350f9ac9a1be12c3fc0cb98f4e6ce 100644 (file)
@@ -1124,9 +1124,14 @@ enum StructKind {
                 }
                 tcx.layout_raw(param_env.and(normalized))?
             }
-            ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
+
+            ty::Bound(..) |
+            ty::UnnormalizedProjection(..) |
+            ty::GeneratorWitness(..) |
+            ty::Infer(_) => {
                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
             }
+
             ty::Param(_) | ty::Error => {
                 return Err(LayoutError::Unknown(ty));
             }
@@ -1703,7 +1708,7 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                 }
             }
 
-            ty::Projection(_) | ty::UnnormalizedProjection(..) |
+            ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) |
             ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
index ad26383df6ac2d424f6a43288ba4dfe1b77eb41a..c7c197d11c03beb112b95d85933d45b9d6acc1ef 100644 (file)
@@ -63,7 +63,7 @@
 
 use hir;
 
-pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
+pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST};
 pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
@@ -463,13 +463,9 @@ pub struct TypeFlags: u32 {
         // Currently we can't normalize projections w/ bound regions.
         const HAS_NORMALIZABLE_PROJECTION = 1 << 12;
 
-        // Set if this includes a "canonical" type or region var --
-        // ought to be true only for the results of canonicalization.
-        const HAS_CANONICAL_VARS = 1 << 13;
-
         /// Does this have any `ReLateBound` regions? Used to check
         /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND = 1 << 14;
+        const HAS_RE_LATE_BOUND = 1 << 13;
 
         const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
                                    TypeFlags::HAS_SELF.bits |
@@ -490,7 +486,6 @@ pub struct TypeFlags: u32 {
                                   TypeFlags::HAS_TY_CLOSURE.bits |
                                   TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
                                   TypeFlags::KEEP_IN_LOCAL_TCX.bits |
-                                  TypeFlags::HAS_CANONICAL_VARS.bits |
                                   TypeFlags::HAS_RE_LATE_BOUND.bits;
     }
 }
@@ -1051,24 +1046,24 @@ pub enum Predicate<'tcx> {
     /// would be the type parameters.
     Trait(PolyTraitPredicate<'tcx>),
 
-    /// where 'a : 'b
+    /// where `'a : 'b`
     RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
 
-    /// where T : 'a
+    /// where `T : 'a`
     TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
 
-    /// where <T as TraitRef>::Name == X, approximately.
-    /// See `ProjectionPredicate` struct for details.
+    /// where `<T as TraitRef>::Name == X`, approximately.
+    /// See the `ProjectionPredicate` struct for details.
     Projection(PolyProjectionPredicate<'tcx>),
 
-    /// no syntax: T WF
+    /// no syntax: `T` well-formed
     WellFormed(Ty<'tcx>),
 
     /// trait must be object-safe
     ObjectSafe(DefId),
 
     /// No direct syntax. May be thought of as `where T : FnFoo<...>`
-    /// for some substitutions `...` and T being a closure type.
+    /// for some substitutions `...` and `T` being a closure type.
     /// Satisfied (or refuted) once we know the closure's kind.
     ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
 
@@ -2378,6 +2373,7 @@ fn sized_constraint_for_ty(&self,
                 }
             }
 
+            Bound(..) |
             Infer(..) => {
                 bug!("unexpected type `{:?}` in sized_constraint_for_ty",
                      ty)
@@ -2801,7 +2797,7 @@ pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
         }
     }
 
-    /// Determine whether an item is annotated with an attribute
+    /// Determine whether an item is annotated with an attribute.
     pub fn has_attr(self, did: DefId, attr: &str) -> bool {
         attr::contains_name(&self.get_attrs(did), attr)
     }
@@ -2815,14 +2811,14 @@ pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> {
         self.optimized_mir(def_id).generator_layout.as_ref().unwrap()
     }
 
-    /// Given the def_id of an impl, return the def_id of the trait it implements.
+    /// Given the def-id of an impl, return the def_id of the trait it implements.
     /// If it implements no trait, return `None`.
     pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
         self.impl_trait_ref(def_id).map(|tr| tr.def_id)
     }
 
-    /// If the given def ID describes a method belonging to an impl, return the
-    /// ID of the impl that the method belongs to. Otherwise, return `None`.
+    /// If the given defid describes a method belonging to an impl, return the
+    /// def-id of the impl that the method belongs to. Otherwise, return `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         let item = if def_id.krate != LOCAL_CRATE {
             if let Some(Def::Method(_)) = self.describe_def(def_id) {
@@ -2987,7 +2983,7 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
         })
 }
 
-/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition
+/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
 pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefId> {
     if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
         if let Node::Item(item) = tcx.hir.get(node_id) {
@@ -2999,7 +2995,19 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
     None
 }
 
-/// See `ParamEnv` struct def'n for details.
+/// Returns `true` if `def_id` is a trait alias.
+pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
+    if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
+        if let Node::Item(item) = tcx.hir.get(node_id) {
+            if let hir::ItemKind::TraitAlias(..) = item.node {
+                return true;
+            }
+        }
+    }
+    false
+}
+
+/// See `ParamEnv` struct definition for details.
 fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        def_id: DefId)
                        -> ParamEnv<'tcx>
index b49664b6247332a16e7c799a43428ad2fd6bd8ac..449730c9d0601d6c991e7705131b3eb71ed122fe 100644 (file)
@@ -106,7 +106,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
             ty::Projection(ref data) => {
-                if !data.has_escaping_regions() {
+                if !data.has_escaping_bound_vars() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
                     // constraints for Pi). This defers the choice between
@@ -156,6 +156,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             ty::FnDef(..) |       // OutlivesFunction (*)
             ty::FnPtr(_) |        // OutlivesFunction (*)
             ty::Dynamic(..) |       // OutlivesObject, OutlivesFragment (*)
+            ty::Bound(..) |
             ty::Error => {
                 // (*) Bare functions and traits are both binders. In the
                 // RFC, this means we would add the bound regions to the
index 05f5f923557ec7ea3dfcb1f07660dddb0971bb9f..59a66513eef0558a274c023b34e3169eeb183bd0 100644 (file)
@@ -734,9 +734,19 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 ty::UnnormalizedProjection(data.fold_with(folder))
             }
             ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
-            ty::Bool | ty::Char | ty::Str | ty::Int(_) |
-            ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
-            ty::Param(..) | ty::Never | ty::Foreign(..) => return self
+
+            ty::Bool |
+            ty::Char |
+            ty::Str |
+            ty::Int(_) |
+            ty::Uint(_) |
+            ty::Float(_) |
+            ty::Error |
+            ty::Infer(_) |
+            ty::Param(..) |
+            ty::Bound(..) |
+            ty::Never |
+            ty::Foreign(..) => return self
         };
 
         if self.sty == sty {
@@ -771,9 +781,19 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
                 data.visit_with(visitor)
             }
             ty::Opaque(_, ref substs) => substs.visit_with(visitor),
-            ty::Bool | ty::Char | ty::Str | ty::Int(_) |
-            ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
-            ty::Param(..) | ty::Never | ty::Foreign(..) => false,
+
+            ty::Bool |
+            ty::Char |
+            ty::Str |
+            ty::Int(_) |
+            ty::Uint(_) |
+            ty::Float(_) |
+            ty::Error |
+            ty::Infer(_) |
+            ty::Bound(..) |
+            ty::Param(..) |
+            ty::Never |
+            ty::Foreign(..) => false,
         }
     }
 
index 62e38ad9bfa662a84ecd25a2356fce2828332e74..28b58d62175bc21f270ef57a38d478c2df832c54 100644 (file)
@@ -77,6 +77,17 @@ pub fn is_named(&self) -> bool {
             _ => false,
         }
     }
+
+    /// When canonicalizing, we replace unbound inference variables and free
+    /// regions with anonymous late bound regions. This method asserts that
+    /// we have an anonymous late bound region, which hence may refer to
+    /// a canonical variable.
+    pub fn assert_bound_var(&self) -> BoundVar {
+        match *self {
+            BoundRegion::BrAnon(var) => BoundVar::from_u32(var),
+            _ => bug!("bound region is not anonymous"),
+        }
+    }
 }
 
 /// N.B., If you change this, you'll probably want to change the corresponding
@@ -188,6 +199,9 @@ pub enum TyKind<'tcx> {
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
     Param(ParamTy),
 
+    /// Bound type variable, used only when preparing a trait query.
+    Bound(BoundTy),
+
     /// A type variable used during type checking.
     Infer(InferTy),
 
@@ -636,7 +650,7 @@ pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
         TraitRef { def_id: def_id, substs: substs }
     }
 
-    /// Returns a TraitRef of the form `P0: Foo<P1..Pn>` where `Pi`
+    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
     /// are the parameters defined on trait.
     pub fn identity<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> TraitRef<'tcx> {
         TraitRef {
@@ -727,8 +741,8 @@ pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     /// or some placeholder type.
     pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
         -> ty::TraitRef<'tcx>  {
-        // otherwise the escaping regions would be captured by the binder
-        // debug_assert!(!self_ty.has_escaping_regions());
+        // otherwise the escaping vars would be captured by the binder
+        // debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::TraitRef {
             def_id: self.def_id,
@@ -755,11 +769,11 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>,
     }
 }
 
-/// Binder is a binder for higher-ranked lifetimes. It is part of the
+/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
 /// (which would be represented by the type `PolyTraitRef ==
 /// Binder<TraitRef>`). Note that when we instantiate,
-/// erase, or otherwise "discharge" these bound regions, we change the
+/// erase, or otherwise "discharge" these bound vars, we change the
 /// type from `Binder<T>` to just `T` (see
 /// e.g. `liberate_late_bound_regions`).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -767,29 +781,28 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>,
 
 impl<T> Binder<T> {
     /// Wraps `value` in a binder, asserting that `value` does not
-    /// contain any bound regions that would be bound by the
+    /// contain any bound vars that would be bound by the
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
     pub fn dummy<'tcx>(value: T) -> Binder<T>
         where T: TypeFoldable<'tcx>
     {
-        debug_assert!(!value.has_escaping_regions());
+        debug_assert!(!value.has_escaping_bound_vars());
         Binder(value)
     }
 
-    /// Wraps `value` in a binder, binding late-bound regions (if any).
-    pub fn bind<'tcx>(value: T) -> Binder<T>
-    {
+    /// Wraps `value` in a binder, binding higher-ranked vars (if any).
+    pub fn bind<'tcx>(value: T) -> Binder<T> {
         Binder(value)
     }
 
     /// Skips the binder and returns the "bound" value. This is a
     /// risky thing to do because it's easy to get confused about
     /// debruijn indices and the like. It is usually better to
-    /// discharge the binder using `no_late_bound_regions` or
+    /// discharge the binder using `no_bound_vars` or
     /// `replace_late_bound_regions` or something like
     /// that. `skip_binder` is only valid when you are either
-    /// extracting data that has nothing to do with bound regions, you
+    /// extracting data that has nothing to do with bound vars, you
     /// are doing some sort of test that does not involve bound
     /// regions, or you are being very careful about your depth
     /// accounting.
@@ -798,7 +811,7 @@ pub fn bind<'tcx>(value: T) -> Binder<T>
     ///
     /// - extracting the def-id from a PolyTraitRef;
     /// - comparing the self type of a PolyTraitRef to see if it is equal to
-    ///   a type parameter `X`, since the type `X`  does not reference any regions
+    ///   a type parameter `X`, since the type `X` does not reference any regions
     pub fn skip_binder(&self) -> &T {
         &self.0
     }
@@ -820,19 +833,19 @@ pub fn map_bound<F, U>(self, f: F) -> Binder<U>
     }
 
     /// Unwraps and returns the value within, but only if it contains
-    /// no bound regions at all. (In other words, if this binder --
+    /// no bound vars at all. (In other words, if this binder --
     /// and indeed any enclosing binder -- doesn't bind anything at
     /// all.) Otherwise, returns `None`.
     ///
     /// (One could imagine having a method that just unwraps a single
-    /// binder, but permits late-bound regions bound by enclosing
+    /// binder, but permits late-bound vars bound by enclosing
     /// binders, but that would require adjusting the debruijn
     /// indices, and given the shallow binding structure we often use,
     /// would not be that useful.)
-    pub fn no_late_bound_regions<'tcx>(self) -> Option<T>
-        where T : TypeFoldable<'tcx>
+    pub fn no_bound_vars<'tcx>(self) -> Option<T>
+        where T: TypeFoldable<'tcx>
     {
-        if self.skip_binder().has_escaping_regions() {
+        if self.skip_binder().has_escaping_bound_vars() {
             None
         } else {
             Some(self.skip_binder().clone())
@@ -1166,9 +1179,6 @@ pub enum RegionKind {
     /// `ClosureRegionRequirements` that are produced by MIR borrowck.
     /// See `ClosureRegionRequirements` for more details.
     ReClosureBound(RegionVid),
-
-    /// Canonicalized region, used only when preparing a trait query.
-    ReCanonical(BoundTyIndex),
 }
 
 impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
@@ -1219,22 +1229,37 @@ pub enum InferTy {
     FreshTy(u32),
     FreshIntTy(u32),
     FreshFloatTy(u32),
-
-    /// Bound type variable, used only when preparing a trait query.
-    BoundTy(BoundTy),
 }
 
 newtype_index! {
-    pub struct BoundTyIndex { .. }
+    pub struct BoundVar { .. }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct BoundTy {
-    pub level: DebruijnIndex,
-    pub var: BoundTyIndex,
+    pub index: DebruijnIndex,
+    pub var: BoundVar,
+    pub kind: BoundTyKind,
 }
 
-impl_stable_hash_for!(struct BoundTy { level, var });
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub enum BoundTyKind {
+    Anon,
+    Param(InternedString),
+}
+
+impl_stable_hash_for!(struct BoundTy { index, var, kind });
+impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) });
+
+impl BoundTy {
+    pub fn new(index: DebruijnIndex, var: BoundVar) -> Self {
+        BoundTy {
+            index,
+            var,
+            kind: BoundTyKind::Anon,
+        }
+    }
+}
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -1264,7 +1289,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         -> ty::ProjectionPredicate<'tcx>
     {
         // otherwise the escaping regions would be captured by the binders
-        debug_assert!(!self_ty.has_escaping_regions());
+        debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::ProjectionPredicate {
             projection_ty: ty::ProjectionTy {
@@ -1363,7 +1388,6 @@ pub fn has_name(&self) -> bool {
             RegionKind::ReEmpty => false,
             RegionKind::ReErased => false,
             RegionKind::ReClosureBound(..) => false,
-            RegionKind::ReCanonical(..) => false,
         }
     }
 
@@ -1450,10 +1474,6 @@ pub fn type_flags(&self) -> TypeFlags {
             }
             ty::ReErased => {
             }
-            ty::ReCanonical(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_CANONICAL_VARS;
-            }
             ty::ReClosureBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
@@ -1865,6 +1885,7 @@ pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
             Tuple(..) |
             Foreign(..) |
             Param(_) |
+            Bound(..) |
             Infer(_) |
             Error => {
                 vec![]
@@ -1930,7 +1951,7 @@ pub fn is_trivially_sized(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> bool {
 
             ty::Infer(ty::TyVar(_)) => false,
 
-            ty::Infer(ty::BoundTy(_)) |
+            ty::Bound(_) |
             ty::Infer(ty::FreshTy(_)) |
             ty::Infer(ty::FreshIntTy(_)) |
             ty::Infer(ty::FreshFloatTy(_)) =>
index 02b5d36ecce6ea0dab9088b61e202d5438116a64..c1aed36c92ddf3bfd60170781ea85bf88ff9bb82 100644 (file)
@@ -12,7 +12,7 @@
 
 use hir::def_id::DefId;
 use infer::canonical::Canonical;
-use ty::{self, BoundTyIndex, Lift, List, Ty, TyCtxt};
+use ty::{self, BoundVar, Lift, List, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 
 use serialize::{self, Encodable, Encoder, Decodable, Decoder};
@@ -355,7 +355,7 @@ fn subst_spanned<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                        span,
                                        root_ty: None,
                                        ty_stack_depth: 0,
-                                       region_binders_passed: 0 };
+                                       binders_passed: 0 };
         (*self).fold_with(&mut folder)
     }
 }
@@ -377,16 +377,16 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     ty_stack_depth: usize,
 
     // Number of region binders we have passed through while doing the substitution
-    region_binders_passed: u32,
+    binders_passed: u32,
 }
 
 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
-        self.region_binders_passed += 1;
+        self.binders_passed += 1;
         let t = t.super_fold_with(self);
-        self.region_binders_passed -= 1;
+        self.binders_passed -= 1;
         t
     }
 
@@ -471,12 +471,12 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
             }
         };
 
-        self.shift_regions_through_binders(ty)
+        self.shift_vars_through_binders(ty)
     }
 
     /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs
-    /// when we are substituting a type with escaping regions into a context where we have passed
-    /// through region binders. That's quite a mouthful. Let's see an example:
+    /// when we are substituting a type with escaping bound vars into a context where we have
+    /// passed through binders. That's quite a mouthful. Let's see an example:
     ///
     /// ```
     /// type Func<A> = fn(A);
@@ -516,25 +516,25 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
     /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
     /// first case we do not increase the Debruijn index and in the second case we do. The reason
     /// is that only in the second case have we passed through a fn binder.
-    fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        debug!("shift_regions(ty={:?}, region_binders_passed={:?}, has_escaping_regions={:?})",
-               ty, self.region_binders_passed, ty.has_escaping_regions());
+    fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
+               ty, self.binders_passed, ty.has_escaping_bound_vars());
 
-        if self.region_binders_passed == 0 || !ty.has_escaping_regions() {
+        if self.binders_passed == 0 || !ty.has_escaping_bound_vars() {
             return ty;
         }
 
-        let result = ty::fold::shift_regions(self.tcx(), self.region_binders_passed, &ty);
-        debug!("shift_regions: shifted result = {:?}", result);
+        let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed);
+        debug!("shift_vars: shifted result = {:?}", result);
 
         result
     }
 
     fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if self.region_binders_passed == 0 || !region.has_escaping_regions() {
+        if self.binders_passed == 0 || !region.has_escaping_bound_vars() {
             return region;
         }
-        self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed))
+        ty::fold::shift_region(self.tcx, region, self.binders_passed)
     }
 }
 
@@ -553,15 +553,23 @@ pub fn is_identity(&self) -> bool {
             return false;
         }
 
-        self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| {
+        self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
             match kind.unpack() {
                 UnpackedKind::Type(ty) => match ty.sty {
-                    ty::Infer(ty::BoundTy(ref b)) => cvar == b.var,
+                    ty::Bound(b) => {
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(b.index, ty::INNERMOST);
+                        cvar == b.var
+                    }
                     _ => false,
                 },
 
                 UnpackedKind::Lifetime(r) => match r {
-                    ty::ReCanonical(cvar1) => cvar == *cvar1,
+                    ty::ReLateBound(index, br) => {
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(*index, ty::INNERMOST);
+                        cvar == br.assert_bound_var()
+                    }
                     _ => false,
                 },
             }
index 00a1bfaacd781affb2dd9971d219f9052c97e2d7..9ba5bf9add110292760dd536f0b43b1157632aa5 100644 (file)
@@ -363,7 +363,7 @@ pub fn required_region_bounds(self,
                erased_self_ty,
                predicates);
 
-        assert!(!erased_self_ty.has_escaping_regions());
+        assert!(!erased_self_ty.has_escaping_bound_vars());
 
         traits::elaborate_predicates(self, predicates)
             .filter_map(|predicate| {
@@ -389,7 +389,7 @@ pub fn required_region_bounds(self,
                         // construct such an object, but this seems
                         // correct even if that code changes).
                         let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
-                        if t == &erased_self_ty && !r.has_escaping_regions() {
+                        if t == &erased_self_ty && !r.has_escaping_bound_vars() {
                             Some(*r)
                         } else {
                             None
@@ -527,7 +527,7 @@ pub fn is_closure(self, def_id: DefId) -> bool {
         self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
     }
 
-    /// True if `def_id` refers to a trait (e.g., `trait Foo { ... }`).
+    /// True if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
     pub fn is_trait(self, def_id: DefId) -> bool {
         if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data {
             true
@@ -951,7 +951,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Can refer to a type which may drop.
         // FIXME(eddyb) check this against a ParamEnv.
-        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
+        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) |
         ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
index 47fbfba87748ba073270d06b01e64e0db7ce2cb2..284c595ee2d965ed6177317bf611106f97725934 100644 (file)
@@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
     match parent_ty.sty {
         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
         ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error |
-        ty::Foreign(..) => {
+        ty::Bound(..) | ty::Foreign(..) => {
         }
         ty::Array(ty, len) => {
             push_const(stack, len);
index 27747970f76b2ca74caf955f9198ba8a85baa647..1336eac63f880514902cac8abb1e8b298beb40a7 100644 (file)
@@ -158,7 +158,7 @@ fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
         let infcx = &mut self.infcx;
         let param_env = self.param_env;
         self.out.iter()
-                .inspect(|pred| assert!(!pred.has_escaping_regions()))
+                .inspect(|pred| assert!(!pred.has_escaping_bound_vars()))
                 .flat_map(|pred| {
                     let mut selcx = traits::SelectionContext::new(infcx);
                     let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
@@ -190,7 +190,7 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
 
         self.out.extend(
             trait_ref.substs.types()
-                            .filter(|ty| !ty.has_escaping_regions())
+                            .filter(|ty| !ty.has_escaping_bound_vars())
                             .map(|ty| traits::Obligation::new(cause.clone(),
                                                               param_env,
                                                               ty::Predicate::WellFormed(ty))));
@@ -205,7 +205,7 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         let trait_ref = data.trait_ref(self.infcx.tcx);
         self.compute_trait_ref(&trait_ref, Elaborate::None);
 
-        if !data.has_escaping_regions() {
+        if !data.has_escaping_bound_vars() {
             let predicate = trait_ref.to_predicate();
             let cause = self.cause(traits::ProjectionWf(data));
             self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
@@ -229,7 +229,7 @@ fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
     }
 
     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
-        if !subty.has_escaping_regions() {
+        if !subty.has_escaping_bound_vars() {
             let cause = self.cause(cause);
             let trait_ref = ty::TraitRef {
                 def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
@@ -258,6 +258,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                 ty::GeneratorWitness(..) |
                 ty::Never |
                 ty::Param(_) |
+                ty::Bound(..) |
                 ty::Foreign(..) => {
                     // WfScalar, WfParameter, etc
                 }
@@ -299,7 +300,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
 
                 ty::Ref(r, rty, _) => {
                     // WfReference
-                    if !r.has_escaping_regions() && !rty.has_escaping_regions() {
+                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                         self.out.push(
                             traits::Obligation::new(
@@ -450,7 +451,7 @@ fn nominal_obligations(&mut self,
                   .map(|pred| traits::Obligation::new(cause.clone(),
                                                       self.param_env,
                                                       pred))
-                  .filter(|pred| !pred.has_escaping_regions())
+                  .filter(|pred| !pred.has_escaping_bound_vars())
                   .collect()
     }
 
@@ -489,7 +490,7 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>,
         // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
         // am looking forward to the future here.
 
-        if !data.has_escaping_regions() {
+        if !data.has_escaping_bound_vars() {
             let implicit_bounds =
                 object_region_bounds(self.infcx.tcx, data);
 
index abdd7fd8d40bf0d220ad2022d1fa47d6f12eb243..5ec4f55b142ebbfcac4c74ae4f0eb63de550c5dd 100644 (file)
@@ -16,7 +16,7 @@
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
 use ty::{Bool, Char, Adt};
 use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
-use ty::{Param, RawPtr, Ref, Never, Tuple};
+use ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
 use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
 use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
@@ -790,9 +790,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 ty::ReEarlyBound(ref data) => {
                     write!(f, "{}", data.name)
                 }
-                ty::ReCanonical(_) => {
-                    write!(f, "'_")
-                }
                 ty::ReLateBound(_, br) |
                 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
                 ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
@@ -860,10 +857,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     write!(f, "{:?}", vid)
                 }
 
-                ty::ReCanonical(c) => {
-                    write!(f, "'?{}", c.index())
-                }
-
                 ty::RePlaceholder(placeholder) => {
                     write!(f, "RePlaceholder({:?})", placeholder)
                 }
@@ -976,7 +969,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     ty::TyVar(_) => write!(f, "_"),
                     ty::IntVar(_) => write!(f, "{}", "{integer}"),
                     ty::FloatVar(_) => write!(f, "{}", "{float}"),
-                    ty::BoundTy(_) => write!(f, "_"),
                     ty::FreshTy(v) => write!(f, "FreshTy({})", v),
                     ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
                     ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
@@ -988,7 +980,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 ty::TyVar(ref v) => write!(f, "{:?}", v),
                 ty::IntVar(ref v) => write!(f, "{:?}", v),
                 ty::FloatVar(ref v) => write!(f, "{:?}", v),
-                ty::BoundTy(v) => write!(f, "?{:?}", v.var.index()),
                 ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
                 ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
                 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
@@ -1119,6 +1110,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 Infer(infer_ty) => write!(f, "{}", infer_ty),
                 Error => write!(f, "[type error]"),
                 Param(ref param_ty) => write!(f, "{}", param_ty),
+                Bound(bound_ty) => {
+                    match bound_ty.kind {
+                        ty::BoundTyKind::Anon => {
+                            if bound_ty.index == ty::INNERMOST {
+                                write!(f, "?{}", bound_ty.var.index())
+                            } else {
+                                write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index())
+                            }
+                        }
+
+                        ty::BoundTyKind::Param(p) => write!(f, "{}", p),
+                    }
+                }
                 Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
                 Dynamic(data, r) => {
                     let r = r.print_to_string(cx);
index 1fc9ee07a1ae49e03aac74689c59cfa858871359..a802729e3fbdbfe24317565dc98ffc9d35e51d80 100644 (file)
@@ -426,7 +426,6 @@ pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
 
             // These cannot exist in borrowck
             RegionKind::ReVar(..) |
-            RegionKind::ReCanonical(..) |
             RegionKind::RePlaceholder(..) |
             RegionKind::ReClosureBound(..) |
             RegionKind::ReErased => span_bug!(borrow_span,
index 1f83c30a3876a215b7a9c8fa584bc334bea2496a..78a31ed668fcae090b32f31f3fee1e1bd71fbeea 100644 (file)
@@ -363,7 +363,6 @@ fn guarantee_valid(&mut self,
 
                     ty::ReStatic => self.item_ub,
 
-                    ty::ReCanonical(_) |
                     ty::ReEmpty |
                     ty::ReClosureBound(..) |
                     ty::ReLateBound(..) |
index 30bf4c33cda6d94d8c3c39b979b2bdcefbd5c488..9736994fc07555ac4d93d30adfc780d19730c3d6 100644 (file)
@@ -556,7 +556,7 @@ fn create_entry_fn(
         // regions must appear in the argument
         // listing.
         let main_ret_ty = cx.tcx.erase_regions(
-            &main_ret_ty.no_late_bound_regions().unwrap(),
+            &main_ret_ty.no_bound_vars().unwrap(),
         );
 
         if declare::get_defined_value(cx, "main").is_some() {
index 7300bac96182b53bbdd6ddfc9e6d48e05dc9d1a4..c8c693257d52f410261bd223c7d2872dc50b475a 100644 (file)
@@ -44,7 +44,7 @@ pub fn get_fn(
     debug!("get_fn(instance={:?})", instance);
 
     assert!(!instance.substs.needs_infer());
-    assert!(!instance.substs.has_escaping_regions());
+    assert!(!instance.substs.has_escaping_bound_vars());
     assert!(!instance.substs.has_param_types());
 
     let sig = instance.fn_sig(cx.tcx);
index f5abb527e430fa91c41a6ce4f6c12c9c3a9b21d1..eb5ae81b2184024ad6191c52580dc348466a87a2 100644 (file)
@@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::Infer(_) |
         ty::UnnormalizedProjection(..) |
         ty::Projection(..) |
+        ty::Bound(..) |
         ty::Opaque(..) |
         ty::GeneratorWitness(..) |
         ty::Param(_) => {
index 03ded64e642355706e8c7b5471028a0ec8a5e30e..b01d7e3a776f7145b791bfe7670db6f55636f6f4 100644 (file)
@@ -285,7 +285,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
 
         debug!("llvm_type({:#?})", self);
 
-        assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty);
+        assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty);
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
index f18f40bf7a1448851a6bc44b398673d86a8eb76b..28b7c610a91c0f8a9d2ccf728c9d1f854d9b6ee9 100644 (file)
@@ -616,22 +616,22 @@ fn escaping() {
         // Theta = [A -> &'a foo]
         env.create_simple_region_hierarchy();
 
-        assert!(!env.t_nil().has_escaping_regions());
+        assert!(!env.t_nil().has_escaping_bound_vars());
 
         let t_rptr_free1 = env.t_rptr_free(1);
-        assert!(!t_rptr_free1.has_escaping_regions());
+        assert!(!t_rptr_free1.has_escaping_bound_vars());
 
         let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1());
-        assert!(t_rptr_bound1.has_escaping_regions());
+        assert!(t_rptr_bound1.has_escaping_bound_vars());
 
         let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
-        assert!(t_rptr_bound2.has_escaping_regions());
+        assert!(t_rptr_bound2.has_escaping_bound_vars());
 
         // t_fn = fn(A)
         let t_param = env.t_param(0);
-        assert!(!t_param.has_escaping_regions());
+        assert!(!t_param.has_escaping_bound_vars());
         let t_fn = env.t_fn(&[t_param], env.t_nil());
-        assert!(!t_fn.has_escaping_regions());
+        assert!(!t_fn.has_escaping_bound_vars());
     })
 }
 
index 5197876f921973ce7d38770eeea3beb2ede7e744..2e19b441d0e3915a0917577692eab39b1e9b8c5c 100644 (file)
@@ -718,6 +718,7 @@ fn check_type_for_ffi(&self,
 
             ty::Param(..) |
             ty::Infer(..) |
+            ty::Bound(..) |
             ty::Error |
             ty::Closure(..) |
             ty::Generator(..) |
index 9864c1f3d7c686dca4c69c3b88c2a68be731138f..0854df5d1269f36679846fd387347d1c1c59128b 100644 (file)
@@ -400,7 +400,7 @@ pub fn list_crate_metadata(&self,
         for (i, dep) in root.crate_deps
                             .decode(self)
                             .enumerate() {
-            write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?;
+            write!(out, "{} {}{}\n", i + 1, dep.name, dep.extra_filename)?;
         }
         write!(out, "\n")?;
         Ok(())
index 2b671891fca6dd00736c2b1257fda7f1b467300b..99372a511a9de5e2c2307b83255c68c7d38bff93 100644 (file)
@@ -277,8 +277,7 @@ fn give_name_from_error_region(
             | ty::RePlaceholder(..)
             | ty::ReEmpty
             | ty::ReErased
-            | ty::ReClosureBound(..)
-            | ty::ReCanonical(..) => None,
+            | ty::ReClosureBound(..) => None,
         }
     }
 
index 5904138ef603ac03df58ffe06f7df786c5425cb1..35ec478143546d90177a81c7f41efb2eebdcf5f8 100644 (file)
@@ -82,9 +82,9 @@ pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>)
         // when we move to universes, we will, and this assertion
         // will start to fail.
         let ty::OutlivesPredicate(k1, r2) =
-            query_constraint.no_late_bound_regions().unwrap_or_else(|| {
+            query_constraint.no_bound_vars().unwrap_or_else(|| {
                 bug!(
-                    "query_constraint {:?} contained bound regions",
+                    "query_constraint {:?} contained bound vars",
                     query_constraint,
                 );
             });
index aa9564bdcaf030f21b4e2c3451857b8ae4075e45..734ddbc3ab9a72af39babca2f7080aac3e3577c9 100644 (file)
@@ -359,7 +359,7 @@ fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if ty.has_escaping_regions() || ty.references_error() {
+        if ty.has_escaping_bound_vars() || ty.references_error() {
             span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
         } else {
             ty
@@ -2214,8 +2214,8 @@ fn prove_closure_bounds(
                     .enumerate()
                     .filter_map(|(idx, constraint)| {
                         let ty::OutlivesPredicate(k1, r2) =
-                            constraint.no_late_bound_regions().unwrap_or_else(|| {
-                                bug!("query_constraint {:?} contained bound regions", constraint,);
+                            constraint.no_bound_vars().unwrap_or_else(|| {
+                                bug!("query_constraint {:?} contained bound vars", constraint,);
                             });
 
                         match k1.unpack() {
index 8c6966691328a44029a83cf9378dec343482d07d..8e27635dee8c13868c3d5e9a04cd1bf3289a83f0 100644 (file)
@@ -905,12 +905,12 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                   trait_ty: Ty<'tcx>,
                                                   impl_ty: Ty<'tcx>,
                                                   output: &mut Vec<MonoItem<'tcx>>) {
-    assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
-            !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
+    assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_bound_vars() &&
+            !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
 
     if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
         let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty);
-        assert!(!poly_trait_ref.has_escaping_regions());
+        assert!(!poly_trait_ref.has_escaping_bound_vars());
 
         // Walk all methods of the trait, including those of its supertraits
         let methods = tcx.vtable_methods(poly_trait_ref);
@@ -1082,7 +1082,7 @@ fn push_extra_entry_roots(&mut self) {
         // regions must appear in the argument
         // listing.
         let main_ret_ty = self.tcx.erase_regions(
-            &main_ret_ty.no_late_bound_regions().unwrap(),
+            &main_ret_ty.no_bound_vars().unwrap(),
         );
 
         let start_instance = Instance::resolve(
index 4c4d56c8938386af83b716168b4c2ea82f12f9cf..9d69a5669b1c0a85cd8971579b93c849d359371a 100644 (file)
@@ -382,6 +382,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 self.push_type_params(substs, iter::empty(), output);
             }
             ty::Error |
+            ty::Bound(..) |
             ty::Infer(_) |
             ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
index 7061504cd0ae74b7708565116e645667d2dca047..76a8501fb177a89c4375e3c99fa175a8da097aaf 100644 (file)
@@ -844,7 +844,9 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     let param_env = gcx.param_env(def_id);
 
     // Normalize the sig.
-    let sig = gcx.fn_sig(def_id).no_late_bound_regions().expect("LBR in ADT constructor signature");
+    let sig = gcx.fn_sig(def_id)
+        .no_bound_vars()
+        .expect("LBR in ADT constructor signature");
     let sig = gcx.normalize_erasing_regions(param_env, sig);
 
     let (adt_def, substs) = match sig.output().sty {
index bd7d9d367618be73f1bc77ce12513fae40d64087..80072153167f3c2eb6115cbfaef6905cc4b66220 100644 (file)
@@ -143,7 +143,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
 {
     let did = tcx.require_lang_item(lang_item);
     let poly_sig = tcx.fn_sig(did);
-    let sig = poly_sig.no_late_bound_regions().unwrap();
+    let sig = poly_sig.no_bound_vars().unwrap();
     let lhs_ty = lhs.ty(local_decls, tcx);
     let rhs_ty = rhs.ty(local_decls, tcx);
     let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
index 0e9596244cd581cb818c89f33d681002edde192f..61861da62f759134b1c6858ab4167d169b70453c 100644 (file)
@@ -403,25 +403,6 @@ fn visit_item(&mut self, item: &'a Item) {
                     }
                 }
             }
-            ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
-                for param in params {
-                    match param.kind {
-                        GenericParamKind::Lifetime { .. } => {}
-                        GenericParamKind::Type { ref default, .. } => {
-                            if !param.bounds.is_empty() {
-                                self.err_handler()
-                                    .span_err(param.ident.span, "type parameters on the left \
-                                        side of a trait alias cannot be bounded");
-                            }
-                            if !default.is_none() {
-                                self.err_handler()
-                                    .span_err(param.ident.span, "type parameters on the left \
-                                        side of a trait alias cannot have defaults");
-                            }
-                        }
-                    }
-                }
-            }
             ItemKind::Mod(_) => {
                 // Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
                 attr::first_attr_value_str_by_name(&item.attrs, "path");
index 7b5e704f60f6e1919cd492361683b160563d4f1d..17ca8c275c3cb39e48c20be846f1914f11e09f10 100644 (file)
@@ -538,9 +538,9 @@ fn is_expected(self, def: Def) -> bool {
         match self {
             PathSource::Type => match def {
                 Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
-                Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
-                Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
-                Def::Existential(..) |
+                Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
+                Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
+                Def::SelfTy(..) | Def::Existential(..) |
                 Def::ForeignTy(..) => true,
                 _ => false,
             },
@@ -3122,7 +3122,10 @@ fn smart_resolve_path_fragment(&mut self,
                         return (err, candidates);
                     }
                     (Def::TyAlias(..), PathSource::Trait(_)) => {
-                        err.span_label(span, "type aliases cannot be used for traits");
+                        err.span_label(span, "type aliases cannot be used as traits");
+                        if nightly_options::is_nightly_build() {
+                            err.note("did you mean to use a trait alias?");
+                        }
                         return (err, candidates);
                     }
                     (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
@@ -3888,7 +3891,7 @@ fn adjust_local_def(&mut self,
                             // report an error.
                             if record_used {
                                 resolve_error(self, span,
-                                        ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
+                                    ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
                             }
                             return Def::Err;
                         }
@@ -3896,7 +3899,7 @@ fn adjust_local_def(&mut self,
                             // Still doesn't deal with upvars
                             if record_used {
                                 resolve_error(self, span,
-                                        ResolutionError::AttemptToUseNonConstantValueInConstant);
+                                    ResolutionError::AttemptToUseNonConstantValueInConstant);
                             }
                             return Def::Err;
                         }
index 5d6badf120286c42d5be864cae36f6efb33cc71c..bf252053199f8df143035e1b6bfa4c8dcfd4fe0d 100644 (file)
@@ -506,6 +506,7 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
                     ty::GeneratorWitness(..) |
                     ty::UnnormalizedProjection(..) |
                     ty::Infer(..) |
+                    ty::Bound(..) |
                     ty::Error => {
                         bug!("unexpected type {:?}", ty)
                     }
index 2ad7ab7c4d92753bb4c073f61933743cf3370980..af64522f18398a4a646f88d460e8489263380f41 100644 (file)
@@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
 
-        ty::Infer(..) | ty::Error => {
+        ty::Bound(..) | ty::Infer(..) | ty::Error => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
             Err(NoSolution)
index cde08f6832ace274442b89c18e51996c782ed491..7cc064f9c3d3d81906ad96caaa92a9e4c5e79a23 100644 (file)
@@ -108,7 +108,7 @@ fn compute_implied_outlives_bounds<'tcx>(
         // From the full set of obligations, just filter down to the
         // region relationships.
         implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
-            assert!(!obligation.has_escaping_regions());
+            assert!(!obligation.has_escaping_bound_vars());
             match obligation.predicate {
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Subtype(..) |
@@ -122,14 +122,14 @@ fn compute_implied_outlives_bounds<'tcx>(
                     vec![]
                 }
 
-                ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
+                ty::Predicate::RegionOutlives(ref data) => match data.no_bound_vars() {
                     None => vec![],
                     Some(ty::OutlivesPredicate(r_a, r_b)) => {
                         vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                     }
                 },
 
-                ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
+                ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() {
                     None => vec![],
                     Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                         let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
index c71898f73ecad69267aa9f0b395ba479d47f411a..052ca37b313717fa7123762068df759a37a3558c 100644 (file)
@@ -93,6 +93,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
             ty::GeneratorWitness(..) |
             ty::UnnormalizedProjection(..) |
             ty::Infer(..) |
+            ty::Bound(..) |
             ty::Error => {
                 bug!("unexpected type {:?}", ty);
             }
index afd8c251b76508c30a8620020e7ae13317061172..18f8473b5b56d7d88fb600878aaa16ff8fbbe0b3 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Conversion from AST representation of types to the ty.rs
+//! Conversion from AST representation of types to the `ty.rs`
 //! representation.  The main routine here is `ast_ty_to_ty()`: each use
 //! is parameterized by an instance of `AstConv`.
 
@@ -181,7 +181,6 @@ pub fn ast_path_substs_for_ty(&self,
         item_segment: &hir::PathSegment)
         -> &'tcx Substs<'tcx>
     {
-
         let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
             self.create_substs_for_ast_path(
                 span,
@@ -545,7 +544,7 @@ pub fn create_substs_for_generic_args<'a, 'b>(
     }
 
     /// Given the type/region arguments provided to some path (along with
-    /// an implicit Self, if this is a trait reference) returns the complete
+    /// an implicit `Self`, if this is a trait reference) returns the complete
     /// set of substitutions. This may involve applying defaulted type parameters.
     ///
     /// Note that the type listing given here is *exactly* what the user provided.
@@ -722,7 +721,7 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
     {
         let trait_def_id = self.trait_def_id(trait_ref);
 
-        debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
+        debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
 
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
 
@@ -739,11 +738,11 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
             let predicate: Result<_, ErrorReported> =
                 self.ast_type_binding_to_poly_projection_predicate(
                     trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
-            // ok to ignore Err() because ErrorReported (see above)
+            // ok to ignore Err because ErrorReported (see above)
             Some((predicate.ok()?, binding.span))
         }));
 
-        debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}",
+        debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}",
                trait_ref, poly_projections, poly_trait_ref);
         poly_trait_ref
     }
@@ -948,8 +947,8 @@ fn ast_path_to_ty(&self,
         )
     }
 
-    /// Transform a PolyTraitRef into a PolyExistentialTraitRef by
-    /// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
+    /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
+    /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
     fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
                                 -> ty::ExistentialTraitRef<'tcx> {
         assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
@@ -975,9 +974,10 @@ fn conv_object_ty_poly_trait_ref(&self,
         let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
                                                         dummy_self,
                                                         &mut projection_bounds);
+        debug!("principal: {:?}", principal);
 
         for trait_bound in trait_bounds[1..].iter() {
-            // Sanity check for non-principal trait bounds
+            // sanity check for non-principal trait bounds
             self.instantiate_poly_trait_ref(trait_bound,
                                             dummy_self,
                                             &mut vec![]);
@@ -1009,9 +1009,9 @@ fn conv_object_ty_poly_trait_ref(&self,
             })
         });
 
-        // check that there are no gross object safety violations,
+        // Check that there are no gross object safety violations;
         // most importantly, that the supertraits don't contain Self,
-        // to avoid ICE-s.
+        // to avoid ICEs.
         let object_safety_violations =
             tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
         if !object_safety_violations.is_empty() {
@@ -1021,7 +1021,7 @@ fn conv_object_ty_poly_trait_ref(&self,
             return tcx.types.err;
         }
 
-        // use a btreeset to keep output in a more consistent order
+        // Use a BTreeSet to keep output in a more consistent order.
         let mut associated_types = BTreeSet::default();
 
         for tr in traits::supertraits(tcx, principal) {
@@ -1060,7 +1060,7 @@ fn conv_object_ty_poly_trait_ref(&self,
         v.sort_by(|a, b| a.stable_cmp(tcx, b));
         let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
 
-        // Explicitly specified region bound. Use that.
+        // Use explicitly-specified region bound.
         let region_bound = if !lifetime.is_elided() {
             self.ast_region_to_region(lifetime, None)
         } else {
@@ -1347,7 +1347,7 @@ pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) {
         err.span_label(span, "associated type not allowed here").emit();
     }
 
-    // Check a type Path and convert it to a Ty.
+    // Check a type `Path` and convert it to a `Ty`.
     pub fn def_to_ty(&self,
                      opt_self_ty: Option<Ty<'tcx>>,
                      path: &hir::Path,
@@ -1442,8 +1442,8 @@ pub fn def_to_ty(&self,
     /// Parses the programmer's textual representation of a type into our
     /// internal notion of a type.
     pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
-        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
-               ast_ty.id, ast_ty);
+        debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})",
+               ast_ty.id, ast_ty, ast_ty.node);
 
         let tcx = self.tcx();
 
@@ -1748,7 +1748,7 @@ pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
             self.region_bounds.iter().map(|&(region_bound, span)| {
                 // account for the binder being introduced below; no need to shift `param_ty`
                 // because, at present at least, it can only refer to early-bound regions
-                let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
+                let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
                 let outlives = ty::OutlivesPredicate(param_ty, region_bound);
                 (ty::Binder::dummy(outlives).to_predicate(), span)
             }).chain(
index 3204ef556f5ddc3b1beac7f5e897407bf3ded8e7..40f2072079a5a1ba203536b642b3f3d14ea8c53c 100644 (file)
@@ -816,7 +816,7 @@ fn check_pat_tuple_struct(&self,
         }
         // Replace constructor type with constructed type for tuple struct patterns.
         let pat_ty = pat_ty.fn_sig(tcx).output();
-        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
+        let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
 
         self.demand_eqtype(pat.span, expected, pat_ty);
 
index e0ee26cba082842aab75d16aa133f5b5f0a903d3..3f0a3531244424c68a7e2b99e4adcb9e2f0ae564 100644 (file)
@@ -128,7 +128,7 @@ fn pointer_kind(&self, t: Ty<'tcx>, span: Span) ->
             ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
             ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
-            ty::Infer(_) => None,
+            ty::Bound(..) | ty::Infer(_) => None,
 
             ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
             ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) |
index fb7c237a536bdd70cb1be8fae07dd5a82f67d452..010561d1001e5ad61cc4cf0af5da187681e0a8a6 100644 (file)
@@ -460,7 +460,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::INNERMOST));
+        assert!(!expected_sig.sig.has_vars_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 da96d4f0cba42ce97df75969fcd74e060dd7d655..3156458b4aa4abe0690057c9cbfccfadb98e72a0 100644 (file)
@@ -419,7 +419,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let mut structural_to_nomimal = FxHashMap::default();
 
                     let sig = tcx.fn_sig(def_id);
-                    let sig = sig.no_late_bound_regions().unwrap();
+                    let sig = sig.no_bound_vars().unwrap();
                     if intr.inputs.len() != sig.inputs().len() {
                         span_err!(tcx.sess, it.span, E0444,
                                   "platform-specific intrinsic has invalid number of \
index 04c32fa88271ad24c7a4c45bafeac4c63c222951..11448750618e218252dd96cb040609c91127dac6 100644 (file)
@@ -331,7 +331,7 @@ pub fn lookup_method_in_trait(&self,
                 value
             }
         };
-        assert!(!bounds.has_escaping_regions());
+        assert!(!bounds.has_escaping_bound_vars());
 
         let cause = traits::ObligationCause::misc(span, self.body_id);
         obligations.extend(traits::predicates_for_generics(cause.clone(),
index 5a8a9632350f2621959bd8d811a3a36b98574c24..305efd0d75af6ed89b0fc26cbb2cac3d10733c48 100644 (file)
@@ -1374,7 +1374,7 @@ fn xform_method_sig(&self,
                fn_sig,
                substs);
 
-        assert!(!substs.has_escaping_regions());
+        assert!(!substs.has_escaping_bound_vars());
 
         // It is possible for type parameters or early-bound lifetimes
         // to appear in the signature of `self`. The substitutions we
index 9ac733b159ba66d6953810a70dc7915e1fd3e69f..791b5a0bdd92abebb5025afe718f7791612c8e68 100644 (file)
@@ -653,8 +653,8 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
 
     fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
         debug!("register_predicate({:?})", obligation);
-        if obligation.has_escaping_regions() {
-            span_bug!(obligation.cause.span, "escaping regions in predicate {:?}",
+        if obligation.has_escaping_bound_vars() {
+            span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}",
                       obligation);
         }
         self.fulfillment_cx
@@ -1928,7 +1928,7 @@ fn projected_ty_from_poly_trait_ref(&self,
     }
 
     fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if ty.has_escaping_regions() {
+        if ty.has_escaping_bound_vars() {
             ty // FIXME: normalization and escaping regions
         } else {
             self.normalize_associated_types_in(span, &ty)
@@ -2431,7 +2431,7 @@ pub fn add_obligations_for_parameters(&self,
                                           cause: traits::ObligationCause<'tcx>,
                                           predicates: &ty::InstantiatedPredicates<'tcx>)
     {
-        assert!(!predicates.has_escaping_regions());
+        assert!(!predicates.has_escaping_bound_vars());
 
         debug!("add_obligations_for_parameters(predicates={:?})",
                predicates);
@@ -5188,8 +5188,8 @@ pub fn instantiate_value_path(&self,
                 }
             },
         );
-        assert!(!substs.has_escaping_regions());
-        assert!(!ty.has_escaping_regions());
+        assert!(!substs.has_escaping_bound_vars());
+        assert!(!ty.has_escaping_bound_vars());
 
         // Write the "user substs" down first thing for later.
         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
index ea84e874b1a5b3b9dc6abb2a7f5bad9ff37f3bc5..527ba276de2732556ea7c4211facc15e06a6db0e 100644 (file)
@@ -153,6 +153,9 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def
         hir::ItemKind::Trait(..) => {
             check_trait(tcx, item);
         }
+        hir::ItemKind::TraitAlias(..) => {
+            check_trait(tcx, item);
+        }
         _ => {}
     }
 }
index 99c6ba457faa0a807c5e689cdc04ab338c63cf57..a5ad31e0b6b5f0de5e1abc1821522935186383ff 100644 (file)
@@ -99,7 +99,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:
 
     let span = tcx.hir.span(impl_node_id);
     let param_env = tcx.param_env(impl_did);
-    assert!(!self_type.has_escaping_regions());
+    assert!(!self_type.has_escaping_bound_vars());
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)",
            self_type);
@@ -176,7 +176,7 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
         let span = tcx.hir.span(impl_node_id);
 
         let source = tcx.type_of(impl_did);
-        assert!(!source.has_escaping_regions());
+        assert!(!source.has_escaping_bound_vars());
         let target = {
             let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
             assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
@@ -356,7 +356,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
 
     let span = gcx.hir.span(impl_node_id);
     let param_env = gcx.param_env(impl_did);
-    assert!(!source.has_escaping_regions());
+    assert!(!source.has_escaping_bound_vars());
 
     let err_info = CoerceUnsizedInfo { custom_kind: None };
 
index eb52a013b0566ef649d9b075596554e0e7f55f82..74dea7fe411ad0e710a016afd5fabc6bb39089e3 100644 (file)
@@ -58,6 +58,8 @@
 
 use std::iter;
 
+struct OnlySelfBounds(bool);
+
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
 
@@ -208,7 +210,7 @@ fn projected_ty_from_poly_trait_ref(
         item_def_id: DefId,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
-        if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() {
+        if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
             self.tcx().mk_projection(item_def_id, trait_ref.substs)
         } else {
             // no late-bound regions, we can just ignore the binder
@@ -245,8 +247,8 @@ fn type_param_predicates<'a, 'tcx>(
     use rustc::hir::*;
 
     // In the AST, bounds can derive from two places. Either
-    // written inline like `<T:Foo>` or in a where clause like
-    // `where T:Foo`.
+    // written inline like `<T : Foo>` or in a where clause like
+    // `where T : Foo`.
 
     let param_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let param_owner = tcx.hir.ty_param_owner(param_id);
@@ -317,12 +319,13 @@ fn type_param_predicates<'a, 'tcx>(
     let icx = ItemCtxt::new(tcx, item_def_id);
     result
         .predicates
-        .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty));
+        .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty,
+            OnlySelfBounds(true)));
     result
 }
 
 impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
-    /// Find bounds from hir::Generics. This requires scanning through the
+    /// Find bounds from `hir::Generics`. This requires scanning through the
     /// AST. We do this to avoid having to convert *all* the bounds, which
     /// would create artificial cycles. Instead we can only convert the
     /// bounds for a type parameter `X` if `X::Foo` is used.
@@ -331,6 +334,7 @@ fn type_parameter_bounds_in_generics(
         ast_generics: &hir::Generics,
         param_id: ast::NodeId,
         ty: Ty<'tcx>,
+        only_self_bounds: OnlySelfBounds,
     ) -> Vec<(ty::Predicate<'tcx>, Span)> {
         let from_ty_params = ast_generics
             .params
@@ -350,9 +354,17 @@ fn type_parameter_bounds_in_generics(
                 hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
                 _ => None,
             })
-            .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id))
-            .flat_map(|bp| bp.bounds.iter())
-            .flat_map(|b| predicates_from_bound(self, ty, b));
+            .flat_map(|bp| {
+                let bt = if is_param(self.tcx, &bp.bounded_ty, param_id) {
+                    Some(ty)
+                } else if !only_self_bounds.0 {
+                    Some(self.to_ty(&bp.bounded_ty))
+                } else {
+                    None
+                };
+                bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
+            })
+            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -419,12 +431,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.predicates_of(def_id);
         }
         hir::ItemKind::TraitAlias(..) => {
-            span_err!(
-                tcx.sess,
-                it.span,
-                E0645,
-                "trait aliases are not yet implemented (see issue #41517)"
-            );
+            tcx.generics_of(def_id);
+            tcx.at(it.span).super_predicates_of(def_id);
+            tcx.predicates_of(def_id);
         }
         hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
             tcx.generics_of(def_id);
@@ -693,15 +702,20 @@ fn super_predicates_of<'a, 'tcx>(
 
     let icx = ItemCtxt::new(tcx, trait_def_id);
 
-    // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
+    // Convert the bounds that follow the colon, e.g. `Bar + Zed` in `trait Foo : Bar + Zed`.
     let self_param_ty = tcx.mk_self_type();
     let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
 
     let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
 
     // Convert any explicit superbounds in the where clause,
-    // e.g. `trait Foo where Self : Bar`:
-    let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty);
+    // e.g. `trait Foo where Self : Bar`.
+    // In the case of trait aliases, however, we include all bounds in the where clause,
+    // so e.g. `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
+    // as one of its "superpredicates".
+    let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
+    let superbounds2 = icx.type_parameter_bounds_in_generics(
+        generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
 
     // Combine the two lists to form the complete set of superbounds:
     let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect();
@@ -709,6 +723,7 @@ fn super_predicates_of<'a, 'tcx>(
     // Now require that immediate supertraits are converted,
     // which will, in turn, reach indirect supertraits.
     for &(pred, span) in &superbounds {
+        debug!("superbound: {:?}", pred);
         if let ty::Predicate::Trait(bound) = pred {
             tcx.at(span).super_predicates_of(bound.def_id());
         }
@@ -1678,6 +1693,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
 
     let icx = ItemCtxt::new(tcx, def_id);
     let no_generics = hir::Generics::empty();
+    let empty_trait_items = HirVec::new();
 
     let mut predicates = UniquePredicates::new();
 
@@ -1722,6 +1738,10 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                     is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
                     generics
                 }
+                ItemKind::TraitAlias(ref generics, _) => {
+                    is_trait = Some((ty::TraitRef::identity(tcx, def_id), &empty_trait_items));
+                    generics
+                }
                 ItemKind::Existential(ExistTy {
                     ref bounds,
                     impl_trait_fn,
@@ -2010,10 +2030,10 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
     }
 }
 
-/// Converts a specific GenericBound from the AST into a set of
+/// Converts a specific `GenericBound` from the AST into a set of
 /// predicates that apply to the self-type. A vector is returned
-/// because this can be anywhere from 0 predicates (`T:?Sized` adds no
-/// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
+/// because this can be anywhere from zero predicates (`T : ?Sized` adds no
+/// predicates) to one (`T : Foo`) to many (`T : Bar<X=i32>` adds `T : Bar`
 /// and `<T as Bar>::X == i32`).
 fn predicates_from_bound<'tcx>(
     astconv: &dyn AstConv<'tcx, 'tcx>,
index 96b75c4792d759486f8966789592149271d3a2d3..d748d93d8988e63470b142ac6381cf7f01f9285b 100644 (file)
@@ -167,7 +167,6 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool
         RegionKind::ReEmpty
         | RegionKind::ReErased
         | RegionKind::ReClosureBound(..)
-        | RegionKind::ReCanonical(..)
         | RegionKind::ReScope(..)
         | RegionKind::ReVar(..)
         | RegionKind::RePlaceholder(..)
index 3e523c0c7f559c1481e400ea98c9c2f4a72fa011..47d34c909961e16e53a4a0d79e12a40b4a2e5aac 100644 (file)
@@ -338,6 +338,7 @@ fn add_constraints_from_ty(&mut self,
 
             ty::UnnormalizedProjection(..) |
             ty::GeneratorWitness(..) |
+            ty::Bound(..) |
             ty::Infer(..) => {
                 bug!("unexpected type encountered in \
                       variance inference: {}",
@@ -426,7 +427,6 @@ fn add_constraints_from_region(&mut self,
                 // way early-bound regions do, so we skip them here.
             }
 
-            ty::ReCanonical(_) |
             ty::ReFree(..) |
             ty::ReClosureBound(..) |
             ty::ReScope(..) |
index 88240e844edc23887fb5f66d4b4416854b8937f4..9f68fd56c5e04512d023436a9f7b0f5c47479914 100644 (file)
@@ -552,6 +552,14 @@ pub fn generics(&self) -> Option<&Generics> {
             _ => return None,
         })
     }
+
+    pub fn is_associated(&self) -> bool {
+        match *self {
+            ItemEnum::TypedefItem(_, _) |
+            ItemEnum::AssociatedTypeItem(_, _) => true,
+            _ => false,
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -1260,7 +1268,6 @@ fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
             ty::RePlaceholder(..) |
             ty::ReEmpty |
             ty::ReClosureBound(_) |
-            ty::ReCanonical(_) |
             ty::ReErased => None
         }
     }
@@ -2733,6 +2740,7 @@ fn clean(&self, cx: &DocContext) -> Type {
 
             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
+            ty::Bound(..) => panic!("Bound"),
             ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
             ty::Infer(..) => panic!("Infer"),
index 3f0ef61f375c09d2f21cf723be7ff1ad3353f110..8ba299d229885932e10da7ca1be49c3891178f7e 100644 (file)
@@ -2322,8 +2322,8 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
     }
-    document_stability(w, cx, item)?;
-    document_full(w, item, cx, "")?;
+    document_stability(w, cx, item, false)?;
+    document_full(w, item, cx, "", false)?;
     Ok(())
 }
 
@@ -2332,15 +2332,19 @@ fn render_markdown(w: &mut fmt::Formatter,
                    cx: &Context,
                    md_text: &str,
                    links: Vec<(String, String)>,
-                   prefix: &str)
+                   prefix: &str,
+                   is_hidden: bool)
                    -> fmt::Result {
     let mut ids = cx.id_map.borrow_mut();
-    write!(w, "<div class='docblock'>{}{}</div>",
-        prefix, Markdown(md_text, &links, RefCell::new(&mut ids), cx.codes))
+    write!(w, "<div class='docblock{}'>{}{}</div>",
+           if is_hidden { " hidden" } else { "" },
+           prefix,
+           Markdown(md_text, &links, RefCell::new(&mut ids),
+           cx.codes))
 }
 
 fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink,
-                  prefix: &str) -> fmt::Result {
+                  prefix: &str, is_hidden: bool) -> fmt::Result {
     if let Some(s) = item.doc_value() {
         let markdown = if s.contains('\n') {
             format!("{} [Read more]({})",
@@ -2348,28 +2352,33 @@ fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link
         } else {
             plain_summary_line(Some(s))
         };
-        render_markdown(w, cx, &markdown, item.links(), prefix)?;
+        render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden)?;
     } else if !prefix.is_empty() {
-        write!(w, "<div class='docblock'>{}</div>", prefix)?;
+        write!(w, "<div class='docblock{}'>{}</div>",
+               if is_hidden { " hidden" } else { "" },
+               prefix)?;
     }
     Ok(())
 }
 
 fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
-                 cx: &Context, prefix: &str) -> fmt::Result {
+                 cx: &Context, prefix: &str, is_hidden: bool) -> fmt::Result {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, cx, &*s, item.links(), prefix)?;
+        render_markdown(w, cx, &*s, item.links(), prefix, is_hidden)?;
     } else if !prefix.is_empty() {
-        write!(w, "<div class='docblock'>{}</div>", prefix)?;
+        write!(w, "<div class='docblock{}'>{}</div>",
+               if is_hidden { " hidden" } else { "" },
+               prefix)?;
     }
     Ok(())
 }
 
-fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
+fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
+                      is_hidden: bool) -> fmt::Result {
     let stabilities = short_stability(item, cx, true);
     if !stabilities.is_empty() {
-        write!(w, "<div class='stability'>")?;
+        write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" })?;
         for stability in stabilities {
             write!(w, "{}", stability)?;
         }
@@ -3934,14 +3943,21 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             RenderMode::ForDeref { mut_: deref_mut_ } => should_render_item(&item, deref_mut_),
         };
 
+        let (is_hidden, extra_class) = if trait_.is_none() ||
+                                          item.doc_value().is_some() ||
+                                          item.inner.is_associated() {
+            (false, "")
+        } else {
+            (true, " hidden")
+        };
         match item.inner {
             clean::MethodItem(clean::Method { ref decl, .. }) |
-            clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => {
+            clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
                     let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                    write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                    write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                     write!(w, "{}", spotlight_decl(decl)?)?;
                     write!(w, "<span id='{}' class='invisible'>", ns_id)?;
                     write!(w, "<table class='table-display'><tbody><tr><td><code>")?;
@@ -3963,7 +3979,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::TypedefItem(ref tydef, _) => {
                 let id = cx.derive_id(format!("{}.{}", ItemType::AssociatedType, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
                 write!(w, "</code></span></h4>\n")?;
@@ -3971,7 +3987,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::AssociatedConstItem(ref ty, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
                 let src = if let Some(l) = (Item { cx, item }).src_href() {
@@ -3985,7 +4001,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::AssociatedTypeItem(ref bounds, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
                 write!(w, "</code></span></h4>\n")?;
@@ -4002,25 +4018,25 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
                     if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
                         // We need the stability of the item from the trait
                         // because impls can't have a stability.
-                        document_stability(w, cx, it)?;
+                        document_stability(w, cx, it, is_hidden)?;
                         if item.doc_value().is_some() {
-                            document_full(w, item, cx, "")?;
+                            document_full(w, item, cx, "", is_hidden)?;
                         } else if show_def_docs {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(w, cx, it, link, "")?;
+                            document_short(w, cx, it, link, "", is_hidden)?;
                         }
                     }
                 } else {
-                    document_stability(w, cx, item)?;
+                    document_stability(w, cx, item, is_hidden)?;
                     if show_def_docs {
-                        document_full(w, item, cx, "")?;
+                        document_full(w, item, cx, "", is_hidden)?;
                     }
                 }
             } else {
-                document_stability(w, cx, item)?;
+                document_stability(w, cx, item, is_hidden)?;
                 if show_def_docs {
-                    document_short(w, cx, item, link, "")?;
+                    document_short(w, cx, item, link, "", is_hidden)?;
                 }
             }
         }
index b31100716397b81e581e0b94ac195a82967953b4..4425712eed7a15aaf9fecc4ae761453769f31aac 100644 (file)
     onEach(document.getElementsByClassName('method'), func);
     onEach(document.getElementsByClassName('associatedconstant'), func);
     onEach(document.getElementsByClassName('impl'), func);
+    onEach(document.getElementsByClassName('impl-items'), function(e) {
+        onEach(e.getElementsByClassName('associatedconstant'), func);
+        var hiddenElems = e.getElementsByClassName('hidden');
+        var needToggle = false;
+
+        for (var i = 0; i < hiddenElems.length; ++i) {
+            if (hasClass(hiddenElems[i], "content") === false &&
+                hasClass(hiddenElems[i], "docblock") === false) {
+                needToggle = true;
+                break;
+            }
+        }
+        if (needToggle === true) {
+            var newToggle = document.createElement('a');
+            newToggle.href = 'javascript:void(0)';
+            newToggle.className = 'collapse-toggle hidden-default collapsed';
+            newToggle.innerHTML = "[<span class='inner'>" + labelForToggleButton(true) + "</span>" +
+                                  "] Show hidden undocumented items";
+            newToggle.onclick = function() {
+                if (hasClass(this, "collapsed")) {
+                    removeClass(this, "collapsed");
+                    onEach(this.parentNode.getElementsByClassName("hidden"), function(x) {
+                        if (hasClass(x, "content") === false) {
+                            removeClass(x, "hidden");
+                            addClass(x, "x");
+                        }
+                    }, true);
+                    this.innerHTML = "[<span class='inner'>" + labelForToggleButton(false) +
+                                     "</span>] Hide undocumented items"
+                } else {
+                    addClass(this, "collapsed");
+                    onEach(this.parentNode.getElementsByClassName("x"), function(x) {
+                        if (hasClass(x, "content") === false) {
+                            addClass(x, "hidden");
+                            removeClass(x, "x");
+                        }
+                    }, true);
+                    this.innerHTML = "[<span class='inner'>" + labelForToggleButton(true) +
+                                     "</span>] Show hidden undocumented items";
+                }
+            };
+            e.insertBefore(newToggle, e.firstChild);
+        }
+    });
 
     function createToggle(otherMessage, fontSize, extraClass, show) {
         var span = document.createElement('span');
index ad6cdfd3e733b131b13f7c9891629f490c40ebbc..8f679b4d22b25d51f292e0b278f7ae7578e66e2f 100644 (file)
@@ -479,17 +479,6 @@ h4 > code, h3 > code, .invisible > code {
        margin-bottom: 15px;
 }
 
-.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
-       margin-left: 20px;
-}
-.content .impl-items .docblock, .content .impl-items .stability {
-       margin-bottom: .6em;
-}
-
-.content .impl-items > .stability {
-       margin-left: 40px;
-}
-
 .content .docblock > .impl-items {
        margin-left: 20px;
        margin-top: -34px;
@@ -531,7 +520,20 @@ h4 > code, h3 > code, .invisible > code {
        top: -9px;
        left: -13px;
 }
-.methods > .stability {
+
+.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
+       margin-left: 20px;
+}
+
+.content .impl-items .docblock, .content .impl-items .stability {
+       margin-bottom: .6em;
+}
+
+.content .impl-items > .stability {
+       margin-left: 40px;
+}
+
+.methods > .stability, .content .impl-items > .stability {
        margin-top: -8px;
 }
 
@@ -839,6 +841,11 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
        text-align: center;
 }
 
+.collapse-toggle.hidden-default {
+       position: relative;
+       margin-left: 20px;
+}
+
 .ghost {
        display: none;
 }
index e10e330402f5edf3ca56fae7f527ab7bad8cdcb2..5f7a8c75d3c5f6973775c2a09fd98b1af6e4693c 100644 (file)
@@ -15,11 +15,19 @@ var mainTheme = document.getElementById("mainThemeStyle");
 
 var savedHref = [];
 
-function onEach(arr, func) {
+function onEach(arr, func, reversed) {
     if (arr && arr.length > 0 && func) {
-        for (var i = 0; i < arr.length; i++) {
-            if (func(arr[i]) === true) {
-                return true;
+        if (reversed !== true) {
+            for (var i = 0; i < arr.length; ++i) {
+                if (func(arr[i]) === true) {
+                    return true;
+                }
+            }
+        } else {
+            for (var i = arr.length - 1; i >= 0; --i) {
+                if (func(arr[i]) === true) {
+                    return true;
+                }
             }
         }
     }
index 2e6e76b5a4039ea4a0b1fe2c3aacf4cb243c2364..06cb4fbd71602787933804c4a9375caa888723bd 100644 (file)
@@ -378,7 +378,7 @@ pub fn make_test(s: &str,
                  dont_insert_main: bool,
                  opts: &TestOptions)
                  -> (String, usize) {
-    let (crate_attrs, everything_else) = partition_source(s);
+    let (crate_attrs, everything_else, crates) = partition_source(s);
     let everything_else = everything_else.trim();
     let mut line_offset = 0;
     let mut prog = String::new();
@@ -402,10 +402,84 @@ pub fn make_test(s: &str,
     // are intended to be crate attributes.
     prog.push_str(&crate_attrs);
 
+    // Uses libsyntax to parse the doctest and find if there's a main fn and the extern
+    // crate already is included.
+    let (already_has_main, already_has_extern_crate) = crate::syntax::with_globals(|| {
+        use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
+        use crate::syntax_pos::FileName;
+        use errors::emitter::EmitterWriter;
+        use errors::Handler;
+
+        let filename = FileName::Anon;
+        let source = crates + &everything_else;
+
+        // any errors in parsing should also appear when the doctest is compiled for real, so just
+        // send all the errors that libsyntax emits directly into a Sink instead of stderr
+        let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+        let emitter = EmitterWriter::new(box io::sink(), None, false, false);
+        let handler = Handler::with_emitter(false, false, box emitter);
+        let sess = ParseSess::with_span_handler(handler, cm);
+
+        debug!("about to parse: \n{}", source);
+
+        let mut found_main = false;
+        let mut found_extern_crate = cratename.is_none();
+
+        let mut parser = match parse::maybe_new_parser_from_source_str(&sess, filename, source) {
+            Ok(p) => p,
+            Err(errs) => {
+                for mut err in errs {
+                    err.cancel();
+                }
+
+                return (found_main, found_extern_crate);
+            }
+        };
+
+        loop {
+            match parser.parse_item() {
+                Ok(Some(item)) => {
+                    if !found_main {
+                        if let ast::ItemKind::Fn(..) = item.node {
+                            if item.ident.as_str() == "main" {
+                                found_main = true;
+                            }
+                        }
+                    }
+
+                    if !found_extern_crate {
+                        if let ast::ItemKind::ExternCrate(original) = item.node {
+                            // This code will never be reached if `cratename` is none because
+                            // `found_extern_crate` is initialized to `true` if it is none.
+                            let cratename = cratename.unwrap();
+
+                            match original {
+                                Some(name) => found_extern_crate = name.as_str() == cratename,
+                                None => found_extern_crate = item.ident.as_str() == cratename,
+                            }
+                        }
+                    }
+
+                    if found_main && found_extern_crate {
+                        break;
+                    }
+                }
+                Ok(None) => break,
+                Err(mut e) => {
+                    e.cancel();
+                    break;
+                }
+            }
+        }
+
+        (found_main, found_extern_crate)
+    });
+
     // Don't inject `extern crate std` because it's already injected by the
     // compiler.
-    if !s.contains("extern crate") && !opts.no_crate_inject && cratename != Some("std") {
+    if !already_has_extern_crate && !opts.no_crate_inject && cratename != Some("std") {
         if let Some(cratename) = cratename {
+            // Make sure its actually used if not included.
             if s.contains(cratename) {
                 prog.push_str(&format!("extern crate {};\n", cratename));
                 line_offset += 1;
@@ -413,19 +487,6 @@ pub fn make_test(s: &str,
         }
     }
 
-    // FIXME (#21299): prefer libsyntax or some other actual parser over this
-    // best-effort ad hoc approach
-    let already_has_main = s.lines()
-        .map(|line| {
-            let comment = line.find("//");
-            if let Some(comment_begins) = comment {
-                &line[0..comment_begins]
-            } else {
-                line
-            }
-        })
-        .any(|code| code.contains("fn main"));
-
     if dont_insert_main || already_has_main {
         prog.push_str(everything_else);
     } else {
@@ -441,9 +502,10 @@ pub fn make_test(s: &str,
 }
 
 // FIXME(aburka): use a real parser to deal with multiline attributes
-fn partition_source(s: &str) -> (String, String) {
+fn partition_source(s: &str) -> (String, String, String) {
     let mut after_header = false;
     let mut before = String::new();
+    let mut crates = String::new();
     let mut after = String::new();
 
     for line in s.lines() {
@@ -457,12 +519,17 @@ fn partition_source(s: &str) -> (String, String) {
             after.push_str(line);
             after.push_str("\n");
         } else {
+            if trimline.starts_with("#[macro_use] extern crate")
+                || trimline.starts_with("extern crate") {
+                crates.push_str(line);
+                crates.push_str("\n");
+            }
             before.push_str(line);
             before.push_str("\n");
         }
     }
 
-    (before, after)
+    (before, after, crates)
 }
 
 pub trait Tester {
@@ -1014,4 +1081,38 @@ fn make_test_display_warnings() {
         let output = make_test(input, None, false, &opts);
         assert_eq!(output, (expected, 1));
     }
+
+    #[test]
+    fn make_test_issues_21299_33731() {
+        let opts = TestOptions::default();
+
+        let input =
+"// fn main
+assert_eq!(2+2, 4);";
+
+        let expected =
+"#![allow(unused)]
+fn main() {
+// fn main
+assert_eq!(2+2, 4);
+}".to_string();
+
+        let output = make_test(input, None, false, &opts);
+        assert_eq!(output, (expected, 2));
+
+        let input =
+"extern crate hella_qwop;
+assert_eq!(asdf::foo, 4);";
+
+        let expected =
+"#![allow(unused)]
+extern crate hella_qwop;
+extern crate asdf;
+fn main() {
+assert_eq!(asdf::foo, 4);
+}".to_string();
+
+        let output = make_test(input, Some("asdf"), false, &opts);
+        assert_eq!(output, (expected, 3));
+    }
 }
index a9acc70d1a5b982f421a7047c13b2412ee2e8a1a..cfedda18a7e22886e2e972cc30d82a36157976a5 100644 (file)
@@ -288,9 +288,9 @@ pub enum TraitBoundModifier {
 }
 
 /// The AST represents all type param bounds as types.
-/// typeck::collect::compute_bounds matches these against
-/// the "special" built-in traits (see middle::lang_items) and
-/// detects Copy, Send and Sync.
+/// `typeck::collect::compute_bounds` matches these against
+/// the "special" built-in traits (see `middle::lang_items`) and
+/// detects `Copy`, `Send` and `Sync`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum GenericBound {
     Trait(PolyTraitRef, TraitBoundModifier),
index 41ed90fb94eedfc25a7d5ad0ca1ba1168f80e84d..a148a6496656a4a13047a03836ea14c14e48c742 100644 (file)
@@ -252,7 +252,7 @@ pub fn span(&self) -> Span {
 
 pub struct MacroExpander<'a, 'b:'a> {
     pub cx: &'a mut ExtCtxt<'b>,
-    monotonic: bool, // c.f. `cx.monotonic_expander()`
+    monotonic: bool, // cf. `cx.monotonic_expander()`
 }
 
 impl<'a, 'b> MacroExpander<'a, 'b> {
index da0ec33030e06ace43192685dd84c34670fa6e3a..6abc506c07b736d08059d390626f7a78fcf86ae7 100644 (file)
@@ -1635,19 +1635,13 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                             if name == "packed" {
                                 gate_feature_post!(&self, repr_packed, attr.span,
                                                    "the `#[repr(packed(n))]` attribute \
-                                                   is experimental");
+                                                    is experimental");
                             }
                         }
                     }
                 }
             }
 
-            ast::ItemKind::TraitAlias(..) => {
-                gate_feature_post!(&self, trait_alias,
-                                   i.span,
-                                   "trait aliases are not yet fully implemented");
-            }
-
             ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(&self, optin_builtin_traits,
@@ -1669,6 +1663,15 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                    "auto traits are experimental and possibly buggy");
             }
 
+            ast::ItemKind::TraitAlias(..) => {
+                gate_feature_post!(
+                    &self,
+                    trait_alias,
+                    i.span,
+                    "trait aliases are experimental"
+                );
+            }
+
             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate_feature_post!(&self, decl_macro, i.span, msg);
index 9077eca18215c0010d3e57a52570f97b3e44a1bd..e9a6535cba1d231460068d3bbc4c0a33ae5cdb0b 100644 (file)
@@ -70,6 +70,23 @@ macro_rules! panictry {
     })
 }
 
+// A variant of 'panictry!' that works on a Vec<Diagnostic> instead of a single DiagnosticBuilder.
+macro_rules! panictry_buffer {
+    ($handler:expr, $e:expr) => ({
+        use std::result::Result::{Ok, Err};
+        use errors::{FatalError, DiagnosticBuilder};
+        match $e {
+            Ok(e) => e,
+            Err(errs) => {
+                for e in errs {
+                    DiagnosticBuilder::new_diagnostic($handler, e).emit();
+                }
+                FatalError.raise()
+            }
+        }
+    })
+}
+
 #[macro_export]
 macro_rules! unwrap_or {
     ($opt:expr, $default:expr) => {
index 465ce73e01de20d6dc0097eab8c6db41f8bfc342..590506566dd5f0d40baa1fbb83c95c955a6c6f0c 100644 (file)
@@ -11,7 +11,7 @@
 use ast::{self, Ident};
 use syntax_pos::{self, BytePos, CharPos, Pos, Span, NO_EXPANSION};
 use source_map::{SourceMap, FilePathMapping};
-use errors::{Applicability, FatalError, DiagnosticBuilder};
+use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder};
 use parse::{token, ParseSess};
 use str::char_at;
 use symbol::{Symbol, keywords};
@@ -175,6 +175,16 @@ pub fn emit_fatal_errors(&mut self) {
         self.fatal_errs.clear();
     }
 
+    pub fn buffer_fatal_errors(&mut self) -> Vec<Diagnostic> {
+        let mut buffer = Vec::new();
+
+        for err in self.fatal_errs.drain(..) {
+            err.buffer(&mut buffer);
+        }
+
+        buffer
+    }
+
     pub fn peek(&self) -> TokenAndSpan {
         // FIXME(pcwalton): Bad copy!
         TokenAndSpan {
@@ -251,6 +261,17 @@ pub fn new_without_err(sess: &'a ParseSess,
         Ok(sr)
     }
 
+    pub fn new_or_buffered_errs(sess: &'a ParseSess,
+                                source_file: Lrc<syntax_pos::SourceFile>,
+                                override_span: Option<Span>) -> Result<Self, Vec<Diagnostic>> {
+        let mut sr = StringReader::new_raw(sess, source_file, override_span);
+        if sr.advance_token().is_err() {
+            Err(sr.buffer_fatal_errors())
+        } else {
+            Ok(sr)
+        }
+    }
+
     pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
         let begin = sess.source_map().lookup_byte_offset(span.lo());
         let end = sess.source_map().lookup_byte_offset(span.hi());
index ce32520b8e74603e3f58a25cbe4fb34e4ba1b5f7..fd66bf55a74be8b8d53a0ec4df50260c7198ff3c 100644 (file)
@@ -15,7 +15,7 @@
 use early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
 use source_map::{SourceMap, FilePathMapping};
 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
-use errors::{Handler, ColorConfig, DiagnosticBuilder};
+use errors::{Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
 use feature_gate::UnstableFeatures;
 use parse::parser::Parser;
 use ptr::P;
@@ -174,12 +174,21 @@ pub fn parse_stream_from_source_str(name: FileName, source: String, sess: &Parse
     source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span)
 }
 
-// Create a new parser from a source string
+/// Create a new parser from a source string
 pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String)
                                       -> Parser {
-    let mut parser = source_file_to_parser(sess, sess.source_map().new_source_file(name, source));
+    panictry_buffer!(&sess.span_diagnostic, maybe_new_parser_from_source_str(sess, name, source))
+}
+
+/// Create a new parser from a source string. Returns any buffered errors from lexing the initial
+/// token stream.
+pub fn maybe_new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String)
+    -> Result<Parser, Vec<Diagnostic>>
+{
+    let mut parser = maybe_source_file_to_parser(sess,
+                                                 sess.source_map().new_source_file(name, source))?;
     parser.recurse_into_file_modules = false;
-    parser
+    Ok(parser)
 }
 
 /// Create a new parser, handling errors as appropriate
@@ -204,14 +213,23 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a>
 
 /// Given a source_file and config, return a parser
 fn source_file_to_parser(sess: & ParseSess, source_file: Lrc<SourceFile>) -> Parser {
+    panictry_buffer!(&sess.span_diagnostic,
+                     maybe_source_file_to_parser(sess, source_file))
+}
+
+/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the
+/// initial token stream.
+fn maybe_source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>)
+    -> Result<Parser, Vec<Diagnostic>>
+{
     let end_pos = source_file.end_pos;
-    let mut parser = stream_to_parser(sess, source_file_to_stream(sess, source_file, None));
+    let mut parser = stream_to_parser(sess, maybe_file_to_stream(sess, source_file, None)?);
 
     if parser.token == token::Eof && parser.span.is_dummy() {
         parser.span = Span::new(end_pos, end_pos, parser.span.ctxt());
     }
 
-    parser
+    Ok(parser)
 }
 
 // must preserve old name for now, because quote! from the *existing*
@@ -243,9 +261,25 @@ fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
 pub fn source_file_to_stream(sess: &ParseSess,
                              source_file: Lrc<SourceFile>,
                              override_span: Option<Span>) -> TokenStream {
-    let mut srdr = lexer::StringReader::new(sess, source_file, override_span);
+    panictry_buffer!(&sess.span_diagnostic, maybe_file_to_stream(sess, source_file, override_span))
+}
+
+/// Given a source file, produce a sequence of token-trees. Returns any buffered errors from
+/// parsing the token tream.
+pub fn maybe_file_to_stream(sess: &ParseSess,
+                            source_file: Lrc<SourceFile>,
+                            override_span: Option<Span>) -> Result<TokenStream, Vec<Diagnostic>> {
+    let mut srdr = lexer::StringReader::new_or_buffered_errs(sess, source_file, override_span)?;
     srdr.real_token();
-    panictry!(srdr.parse_all_token_trees())
+
+    match srdr.parse_all_token_trees() {
+        Ok(stream) => Ok(stream),
+        Err(err) => {
+            let mut buffer = Vec::with_capacity(1);
+            err.buffer(&mut buffer);
+            Err(buffer)
+        }
+    }
 }
 
 /// Given stream and the `ParseSess`, produce a parser
index be448f960df3fd105310cbe657195a0bb7b5fe70..c453b4b5597ffc4ff82bac9429221e7cc4dbd99f 100644 (file)
@@ -611,6 +611,7 @@ fn token_descr(&self) -> Option<&'static str> {
             t if t.is_special_ident() => "reserved identifier",
             t if t.is_used_keyword() => "keyword",
             t if t.is_unused_keyword() => "reserved keyword",
+            token::DocComment(..) => "doc comment",
             _ => return None,
         })
     }
@@ -644,8 +645,8 @@ pub fn expect(&mut self, t: &token::Token) -> PResult<'a,  ()> {
                 Ok(())
             } else {
                 let token_str = pprust::token_to_string(t);
-                let this_token_str = self.this_token_to_string();
-                let mut err = self.fatal(&format!("expected `{}`, found `{}`",
+                let this_token_str = self.this_token_descr();
+                let mut err = self.fatal(&format!("expected `{}`, found {}",
                                                   token_str,
                                                   this_token_str));
 
@@ -1295,7 +1296,7 @@ fn token_is_bare_fn_keyword(&mut self) -> bool {
             self.check_keyword(keywords::Extern) && self.is_extern_non_path()
     }
 
-    /// parse a TyKind::BareFn type:
+    /// parse a `TyKind::BareFn` type:
     fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
         /*
 
@@ -1444,8 +1445,8 @@ fn parse_trait_item_(&mut self,
                             Some(body)
                         }
                         _ => {
-                            let token_str = self.this_token_to_string();
-                            let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`",
+                            let token_str = self.this_token_descr();
+                            let mut err = self.fatal(&format!("expected `;` or `{{`, found {}",
                                                               token_str));
                             err.span_label(self.span, "expected `;` or `{`");
                             return Err(err);
@@ -1453,8 +1454,8 @@ fn parse_trait_item_(&mut self,
                     }
                 }
                 _ => {
-                    let token_str = self.this_token_to_string();
-                    let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`",
+                    let token_str = self.this_token_descr();
+                    let mut err = self.fatal(&format!("expected `;` or `{{`, found {}",
                                                       token_str));
                     err.span_label(self.span, "expected `;` or `{`");
                     return Err(err);
@@ -1532,7 +1533,7 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
                             if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
                         let path = match bounds[0] {
                             GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
-                            _ => self.bug("unexpected lifetime bound"),
+                            GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
                         };
                         self.parse_remaining_bounds(Vec::new(), path, lo, true)?
                     }
@@ -3917,8 +3918,8 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::Fiel
                     etc_span = Some(etc_sp);
                     break;
                 }
-                let token_str = self.this_token_to_string();
-                let mut err = self.fatal(&format!("expected `}}`, found `{}`", token_str));
+                let token_str = self.this_token_descr();
+                let mut err = self.fatal(&format!("expected `}}`, found {}", token_str));
 
                 err.span_label(self.span, "expected `}`");
                 let mut comma_sp = None;
@@ -4680,8 +4681,8 @@ fn parse_stmt_without_recovery(&mut self,
                     } else {
                         ""
                     };
-                    let tok_str = self.this_token_to_string();
-                    let mut err = self.fatal(&format!("expected {}`(` or `{{`, found `{}`",
+                    let tok_str = self.this_token_descr();
+                    let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}",
                                                       ident_str,
                                                       tok_str));
                     err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str));
@@ -4817,8 +4818,8 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
 
         if !self.eat(&token::OpenDelim(token::Brace)) {
             let sp = self.span;
-            let tok = self.this_token_to_string();
-            let mut e = self.span_fatal(sp, &format!("expected `{{`, found `{}`", tok));
+            let tok = self.this_token_descr();
+            let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
             let do_not_suggest_help =
                 self.token.is_keyword(keywords::In) || self.token == token::Colon;
 
@@ -4880,6 +4881,7 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
                 }
                 _ => ()
             }
+            e.span_label(sp, "expected `{`");
             return Err(e);
         }
 
@@ -4975,7 +4977,7 @@ fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Blo
 
     fn warn_missing_semicolon(&self) {
         self.diagnostic().struct_span_warn(self.span, {
-            &format!("expected `;`, found `{}`", self.this_token_to_string())
+            &format!("expected `;`, found {}", self.this_token_descr())
         }).note({
             "This was erroneously allowed and will become a hard error in a future release"
         }).emit();
@@ -5779,7 +5781,7 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
                              ast::ImplItemKind)> {
         // code copied from parse_macro_use_or_failure... abstraction!
         if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
-            // Method macro.
+            // method macro
             Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
                 ast::ImplItemKind::Macro(mac)))
         } else {
@@ -6014,9 +6016,9 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
             self.expect(&token::Semi)?;
             body
         } else {
-            let token_str = self.this_token_to_string();
+            let token_str = self.this_token_descr();
             let mut err = self.fatal(&format!(
-                "expected `where`, `{{`, `(`, or `;` after struct name, found `{}`",
+                "expected `where`, `{{`, `(`, or `;` after struct name, found {}",
                 token_str
             ));
             err.span_label(self.span, "expected `where`, `{`, `(`, or `;` after struct name");
@@ -6038,9 +6040,9 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
         } else if self.token == token::OpenDelim(token::Brace) {
             VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
         } else {
-            let token_str = self.this_token_to_string();
+            let token_str = self.this_token_descr();
             let mut err = self.fatal(&format!(
-                "expected `where` or `{{` after union name, found `{}`", token_str));
+                "expected `where` or `{{` after union name, found {}", token_str));
             err.span_label(self.span, "expected `where` or `{` after union name");
             return Err(err);
         };
@@ -6088,9 +6090,9 @@ fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
             }
             self.eat(&token::CloseDelim(token::Brace));
         } else {
-            let token_str = self.this_token_to_string();
+            let token_str = self.this_token_descr();
             let mut err = self.fatal(&format!(
-                    "expected `where`, or `{{` after struct name, found `{}`", token_str));
+                    "expected `where`, or `{{` after struct name, found {}", token_str));
             err.span_label(self.span, "expected `where`, or `{` after struct name");
             return Err(err);
         }
@@ -6166,8 +6168,8 @@ fn parse_single_struct_field(&mut self,
             }
             _ => {
                 let sp = self.sess.source_map().next_point(self.prev_span);
-                let mut err = self.struct_span_err(sp, &format!("expected `,`, or `}}`, found `{}`",
-                                                                self.this_token_to_string()));
+                let mut err = self.struct_span_err(sp, &format!("expected `,`, or `}}`, found {}",
+                                                                self.this_token_descr()));
                 if self.token.is_ident() {
                     // This is likely another field; emit the diagnostic and keep going
                     err.span_suggestion_with_applicability(
@@ -6303,9 +6305,9 @@ fn parse_mod_items(&mut self, term: &token::Token, inner_lo: Span) -> PResult<'a
         }
 
         if !self.eat(term) {
-            let token_str = self.this_token_to_string();
-            let mut err = self.fatal(&format!("expected item, found `{}`", token_str));
-            if token_str == ";" {
+            let token_str = self.this_token_descr();
+            let mut err = self.fatal(&format!("expected item, found {}", token_str));
+            if self.token == token::Semi {
                 let msg = "consider removing this semicolon";
                 err.span_suggestion_short_with_applicability(
                     self.span, msg, String::new(), Applicability::MachineApplicable
@@ -6792,11 +6794,11 @@ fn parse_item_foreign_mod(&mut self,
         Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs))
     }
 
-    /// Parse type Foo = Bar;
+    /// Parse `type Foo = Bar;`
     /// or
-    /// existential type Foo: Bar;
+    /// `existential type Foo: Bar;`
     /// or
-    /// return None without modifying the parser state
+    /// `return None` without modifying the parser state
     fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
         // This parses the grammar:
         //     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
diff --git a/src/test/run-pass/traits/trait-alias-bounds.rs b/src/test/run-pass/traits/trait-alias-bounds.rs
new file mode 100644 (file)
index 0000000..d8ac1a8
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+use std::marker::PhantomData;
+
+trait Empty {}
+trait EmptyAlias = Empty;
+trait CloneDefault = Clone + Default;
+trait SendSyncAlias = Send + Sync;
+trait WhereSendAlias = where Self: Send;
+trait SendEqAlias<T> = Send where T: PartialEq<Self>;
+trait I32Iterator = Iterator<Item = i32>;
+
+#[allow(dead_code)]
+struct Foo<T: SendSyncAlias>(PhantomData<T>);
+#[allow(dead_code)]
+struct Bar<T>(PhantomData<T>) where T: SendSyncAlias;
+
+impl EmptyAlias {}
+
+impl<T: SendSyncAlias> Empty for T {}
+
+fn a<T: CloneDefault>() -> (T, T) {
+    let one = T::default();
+    let two = one.clone();
+    (one, two)
+}
+
+fn b(x: &impl SendEqAlias<i32>) -> bool {
+    22_i32 == *x
+}
+
+fn c<T: I32Iterator>(x: &mut T) -> Option<i32> {
+    x.next()
+}
+
+fn d<T: SendSyncAlias>() {
+    is_send_and_sync::<T>();
+}
+
+fn is_send_and_sync<T: Send + Sync>() {}
+
+fn main() {
+    let both = a::<i32>();
+    assert_eq!(both.0, 0);
+    assert_eq!(both.1, 0);
+    let both: (i32, i32) = a();
+    assert_eq!(both.0, 0);
+    assert_eq!(both.1, 0);
+
+    assert!(b(&22));
+
+    assert_eq!(c(&mut vec![22].into_iter()), Some(22));
+
+    d::<i32>();
+}
diff --git a/src/test/run-pass/traits/trait-alias-object-type.rs b/src/test/run-pass/traits/trait-alias-object-type.rs
new file mode 100644 (file)
index 0000000..17e3092
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+trait Foo = PartialEq<i32> + Send;
+trait Bar = Foo + Sync;
+
+trait I32Iterator = Iterator<Item = i32>;
+
+pub fn main() {
+    let a: &dyn Bar = &123;
+    assert!(*a == 123);
+    let b = Box::new(456) as Box<dyn Foo>;
+    assert!(*b == 456);
+
+    // FIXME(alexreg): associated type should be gotten from trait alias definition
+    // let c: &dyn I32Iterator = &vec![123].into_iter();
+    // assert_eq!(c.next(), Some(123));
+}
diff --git a/src/test/run-pass/traits/trait-alias-syntax.rs b/src/test/run-pass/traits/trait-alias-syntax.rs
new file mode 100644 (file)
index 0000000..a9b7afb
--- /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.
+
+#![feature(trait_alias)]
+
+trait SimpleAlias = Default;
+trait GenericAlias<T> = Iterator<Item = T>;
+trait Partial<T> = IntoIterator<Item = T>;
+trait SpecificAlias = GenericAlias<i32>;
+trait PartialEqRef<'a, T: 'a> = PartialEq<&'a T>;
+trait StaticAlias = 'static;
+
+trait Things<T> {}
+trait Romeo {}
+#[allow(dead_code)]
+struct The<T>(T);
+#[allow(dead_code)]
+struct Fore<T>(T);
+impl<T, U> Things<T> for The<U> {}
+impl<T> Romeo for Fore<T> {}
+
+trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo;
+trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>;
+
+fn main() {}
index cbb2a00214a5a30458589108ebba6ad49bc05323..9ace8714918248c619b2c7c8a46be0e4f01540dc 100644 (file)
@@ -75,8 +75,8 @@ pub trait Qux {
     /// Docs for QUX1 in trait.
     const QUX1: i8;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
-    // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait."
-    /// Docs for QUX_DEFAULT0 in trait.
+    // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT12 in trait."
+    /// Docs for QUX_DEFAULT12 in trait.
     const QUX_DEFAULT0: u16 = 1;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
     // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in trait."
@@ -99,7 +99,7 @@ impl Qux for Bar {
     /// Docs for QUX1 in impl.
     const QUX1: i8 = 5;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
-    // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait."
+    // @has - '//*[@class="docblock hidden"]' "Docs for QUX_DEFAULT12 in trait."
     const QUX_DEFAULT0: u16 = 6;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
     // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in impl."
diff --git a/src/test/rustdoc/auxiliary/enum_primitive.rs b/src/test/rustdoc/auxiliary/enum_primitive.rs
new file mode 100644 (file)
index 0000000..c265ae4
--- /dev/null
@@ -0,0 +1,210 @@
+// Copyright (c) 2015 Anders Kaseorg <andersk@mit.edu>
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// “Software”), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+//! This crate exports a macro `enum_from_primitive!` that wraps an
+//! `enum` declaration and automatically adds an implementation of
+//! `num::FromPrimitive` (reexported here), to allow conversion from
+//! primitive integers to the enum.  It therefore provides an
+//! alternative to the built-in `#[derive(FromPrimitive)]`, which
+//! requires the unstable `std::num::FromPrimitive` and is disabled in
+//! Rust 1.0.
+//!
+//! # Example
+//!
+//! ```
+//! #[macro_use] extern crate enum_primitive;
+//! extern crate num_traits;
+//! use num_traits::FromPrimitive;
+//!
+//! enum_from_primitive! {
+//! #[derive(Debug, PartialEq)]
+//! enum FooBar {
+//!     Foo = 17,
+//!     Bar = 42,
+//!     Baz,
+//! }
+//! }
+//!
+//! fn main() {
+//!     assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
+//!     assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
+//!     assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
+//!     assert_eq!(FooBar::from_i32(91), None);
+//! }
+//! ```
+
+
+pub mod num_traits {
+    pub trait FromPrimitive: Sized {
+        fn from_i64(n: i64) -> Option<Self>;
+        fn from_u64(n: u64) -> Option<Self>;
+    }
+}
+
+pub use std::option::Option;
+pub use num_traits::FromPrimitive;
+
+/// Helper macro for internal use by `enum_from_primitive!`.
+#[macro_export]
+macro_rules! enum_from_primitive_impl_ty {
+    ($meth:ident, $ty:ty, $name:ident, $( $variant:ident )*) => {
+        #[allow(non_upper_case_globals, unused)]
+        fn $meth(n: $ty) -> $crate::Option<Self> {
+            $( if n == $name::$variant as $ty {
+                $crate::Option::Some($name::$variant)
+            } else )* {
+                $crate::Option::None
+            }
+        }
+    };
+}
+
+/// Helper macro for internal use by `enum_from_primitive!`.
+#[macro_export]
+#[macro_use(enum_from_primitive_impl_ty)]
+macro_rules! enum_from_primitive_impl {
+    ($name:ident, $( $variant:ident )*) => {
+        impl $crate::FromPrimitive for $name {
+            enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant )* }
+            enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant )* }
+        }
+    };
+}
+
+/// Wrap this macro around an `enum` declaration to get an
+/// automatically generated implementation of `num::FromPrimitive`.
+#[macro_export]
+#[macro_use(enum_from_primitive_impl)]
+macro_rules! enum_from_primitive {
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
+    };
+}
+
index db48a6525230cb8e9cf9a0ff3f4df63801274bee..949ef1182889730f580ce65f67a7e77f6ab818e9 100644 (file)
@@ -73,7 +73,7 @@ fn c_method(&self) -> usize {
 // @has manual_impl/struct.S3.html '//*[@class="trait"]' 'T'
 // @has  - '//*[@class="docblock"]' 'Docs associated with the S3 trait implementation.'
 // @has  - '//*[@class="docblock"]' 'Docs associated with the S3 trait b_method implementation.'
-// @has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.'
+// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait a_method definition.'
 pub struct S3(usize);
 
 /// Docs associated with the S3 trait implementation.
diff --git a/src/test/rustdoc/no-stack-overflow-25295.rs b/src/test/rustdoc/no-stack-overflow-25295.rs
new file mode 100644 (file)
index 0000000..37b0aca
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// ensure this code doesn't stack overflow
+// aux-build:enum_primitive.rs
+
+#[macro_use] extern crate enum_primitive;
+
+enum_from_primitive! {
+    pub enum Test {
+        A1,A2,A3,A4,A5,A6,
+        B1,B2,B3,B4,B5,B6,
+        C1,C2,C3,C4,C5,C6,
+        D1,D2,D3,D4,D5,D6,
+        E1,E2,E3,E4,E5,E6,
+        F1,F2,F3,F4,F5,F6,
+        G1,G2,G3,G4,G5,G6,
+        H1,H2,H3,H4,H5,H6,
+        I1,I2,I3,I4,I5,I6,
+        J1,J2,J3,J4,J5,J6,
+        K1,K2,K3,K4,K5,K6,
+        L1,L2,L3,L4,L5,L6,
+        M1,M2,M3,M4,M5,M6,
+        N1,N2,N3,N4,N5,N6,
+        O1,O2,O3,O4,O5,O6,
+        P1,P2,P3,P4,P5,P6,
+        Q1,Q2,Q3,Q4,Q5,Q6,
+        R1,R2,R3,R4,R5,R6,
+        S1,S2,S3,S4,S5,S6,
+        T1,T2,T3,T4,T5,T6,
+        U1,U2,U3,U4,U5,U6,
+        V1,V2,V3,V4,V5,V6,
+        W1,W2,W3,W4,W5,W6,
+        X1,X2,X3,X4,X5,X6,
+        Y1,Y2,Y3,Y4,Y5,Y6,
+        Z1,Z2,Z3,Z4,Z5,Z6,
+    }
+}
+
index e247e86fbcb2281ecf67e9aa5bad6b73617a321e..f60f1dfcf3772e0979c224d3a9e5e40fc2416472 100644 (file)
@@ -2,7 +2,9 @@ error[E0404]: expected trait, found type alias `Bar`
   --> $DIR/two_files.rs:15:6
    |
 LL | impl Bar for Baz { } //~ ERROR expected trait, found type alias
-   |      ^^^ type aliases cannot be used for traits
+   |      ^^^ type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/derive-uninhabited-enum-38885.rs b/src/test/ui/derive-uninhabited-enum-38885.rs
new file mode 100644 (file)
index 0000000..dc7f5d6
--- /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.
+
+// compile-pass
+// compile-flags: -Wunused
+
+// ensure there are no special warnings about uninhabited types
+// when deriving Debug on an empty enum
+
+#[derive(Debug)]
+enum Void {} //~ WARN never used
+
+#[derive(Debug)]
+enum Foo { //~ WARN never used
+    Bar(u8),
+    Void(Void),
+}
+
+fn main() {}
+
diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr
new file mode 100644 (file)
index 0000000..11032ab
--- /dev/null
@@ -0,0 +1,14 @@
+warning: enum is never used: `Void`
+  --> $DIR/derive-uninhabited-enum-38885.rs:18:1
+   |
+LL | enum Void {} //~ WARN never used
+   | ^^^^^^^^^
+   |
+   = note: `-W dead-code` implied by `-W unused`
+
+warning: enum is never used: `Foo`
+  --> $DIR/derive-uninhabited-enum-38885.rs:21:1
+   |
+LL | enum Foo { //~ WARN never used
+   | ^^^^^^^^
+
index db3478116cbfdd37270b312a5d01cba019cf4b5f..8b6e34c585f9d8daefffbcb265b206fae8b7a3fc 100644 (file)
@@ -28,7 +28,7 @@ error: expected `{`, found `;`
 LL |     if not  // lack of braces is [sic]
    |     -- this `if` statement has a condition, but no block
 LL |         println!("Then when?");
-   |                               ^
+   |                               ^ expected `{`
 
 error: unexpected `2` after identifier
   --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:36:24
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.rs b/src/test/ui/feature-gates/feature-gate-trait-alias.rs
new file mode 100644 (file)
index 0000000..a2a183f
--- /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.
+
+trait Foo = Default;
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
new file mode 100644 (file)
index 0000000..e02dfe2
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: trait aliases are experimental (see issue #41517)
+  --> $DIR/feature-gate-trait-alias.rs:11:1
+   |
+LL | trait Foo = Default;
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trait_alias)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index ce3de3b302dd3678e52d41dec61fddeb660cb66c..db81f00a9e364ab5ed11458dc10e5cefb3ff353f 100644 (file)
@@ -16,3 +16,4 @@ fn main() {
     }
 }
 //~^ ERROR expected `{`, found `}`
+//~| NOTE expected `{`
index bc8e7310ce37198eed4f852a03ef3ede5d01c3dc..c94dac8871dabbfb3d8a0eee37bd1e94270ae687 100644 (file)
@@ -5,7 +5,7 @@ LL |     if 5 == {
    |     -- this `if` statement has a condition, but no block
 ...
 LL | }
-   | ^
+   | ^ expected `{`
 
 error: aborting due to previous error
 
index ac079b452c5eb4647b8be348617a7653dcf57e2a..d50ee64cf52904b77522e592021e59d73e758044 100644 (file)
@@ -1,4 +1,4 @@
-error: expected `{`, found `in`
+error: expected `{`, found keyword `in`
   --> $DIR/issue-51602.rs:12:10
    |
 LL |     if i in 1..10 {
index 9ca39dbaa3436729ca55d64ae0721e1f4d016b28..a5d30b8561ab15daecbd48ad804d85f577aeaa54 100644 (file)
@@ -7,7 +7,7 @@ LL |         if $tgt.has_$field() {}
    |         this `if` statement has a condition, but no block
 ...
 LL |     get_opt!(bar, foo);
-   |                   ^^^
+   |                   ^^^ expected `{`
 
 error: aborting due to previous error
 
index 0ab1ad2c24200360595147b43f83da6a71ffeb79..756648f5658e49bc62a265fcbeea8619780202c6 100644 (file)
@@ -10,6 +10,7 @@ error: expected `{`, found `'b`
 LL |     if true 'b: {} //~ ERROR expected `{`, found `'b`
    |     --      ^^----
    |     |       |
+   |     |       expected `{`
    |     |       help: try placing this code inside a block: `{ 'b: { } }`
    |     this `if` statement has a condition, but no block
 
@@ -19,6 +20,7 @@ error: expected `{`, found `'b`
 LL |     if true {} else 'b: {} //~ ERROR expected `{`, found `'b`
    |                     ^^----
    |                     |
+   |                     expected `{`
    |                     help: try placing this code inside a block: `{ 'b: { } }`
 
 error: expected one of `.`, `?`, `{`, or an operator, found `'b`
index a48eff890b331448750f525310b98f1341d2e44e..dbbfd10b79526994ce21b78d25948a33a324040d 100644 (file)
@@ -2,7 +2,7 @@ error: expected `{`, found `=>`
   --> $DIR/missing-block-hint.rs:13:18
    |
 LL |         if (foo) => {} //~ ERROR expected `{`, found `=>`
-   |         --       ^^
+   |         --       ^^ expected `{`
    |         |
    |         this `if` statement has a condition, but no block
 
@@ -14,6 +14,7 @@ LL |         if (foo)
 LL |             bar; //~ ERROR expected `{`, found `bar`
    |             ^^^-
    |             |
+   |             expected `{`
    |             help: try placing this code inside a block: `{ bar; }`
 
 error: aborting due to 2 previous errors
index 72319a257d85d9501d2a2eb1e300cc9fed4f116f..b4427565a8649162336462c800f6f2994bfff2bb 100644 (file)
@@ -1,4 +1,4 @@
-warning: expected `;`, found `let`
+warning: expected `;`, found keyword `let`
   --> $DIR/missing-semicolon-warning.rs:16:12
    |
 LL |         $( let x = $e1 )*; //~ WARN expected `;`
index 2882364081a1301cb4c1edfd0fc93cbeee325aa2..a321d0e29b276431771a36f138456828045cf3c3 100644 (file)
@@ -12,7 +12,7 @@
 
 fn /// document
 foo() {}
-//~^^ ERROR expected identifier, found `/// document`
+//~^^ ERROR expected identifier, found doc comment `/// document`
 
 fn main() {
     foo();
index f93ab634c28c91cb6aa26c109fab76e76b15349a..73b169ce8e58518f960a3189f266ed4d3af7999b 100644 (file)
@@ -1,8 +1,8 @@
-error: expected identifier, found `/// document`
+error: expected identifier, found doc comment `/// document`
   --> $DIR/doc-before-identifier.rs:13:4
    |
 LL | fn /// document
-   |    ^^^^^^^^^^^^ expected identifier
+   |    ^^^^^^^^^^^^ expected identifier, found doc comment
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.rs b/src/test/ui/parser/doc-comment-in-if-statement.rs
new file mode 100644 (file)
index 0000000..c85fe25
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    if true /*!*/ {}
+    //~^ ERROR expected `{`, found doc comment `/*!*/`
+}
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.stderr b/src/test/ui/parser/doc-comment-in-if-statement.stderr
new file mode 100644 (file)
index 0000000..6bcb773
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected `{`, found doc comment `/*!*/`
+  --> $DIR/doc-comment-in-if-statement.rs:2:13
+   |
+LL |     if true /*!*/ {}
+   |     --      ^^^^^ expected `{`
+   |     |
+   |     this `if` statement has a condition, but no block
+
+error: aborting due to previous error
+
index 6fdc7972a8856647bad1c7c2baeeb0ec8bd01252..f00bfcb45b17f39b7aa87a8adcb64c0724c143b6 100644 (file)
@@ -1,4 +1,4 @@
-error: expected `;`, found `as`
+error: expected `;`, found keyword `as`
   --> $DIR/import-from-rename.rs:15:16
    |
 LL | use foo::{bar} as baz;
index c36a946fd63067a98b5978b99694c6683c628f50..0b124a32df32c1116f8060809ef41d1d0196d3bd 100644 (file)
@@ -1,4 +1,4 @@
-error: expected `;`, found `as`
+error: expected `;`, found keyword `as`
   --> $DIR/import-glob-rename.rs:15:12
    |
 LL | use foo::* as baz;
index 3f41c0edd2e6feed384e4d6ad8bec116f7c628d9..749cb7fcc0b1970d7ea25be23b74b9cb57eeaca2 100644 (file)
@@ -10,6 +10,6 @@
 
 // compile-flags: -Z parse-only -Z continue-parse-after-error
 
-struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
+struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found keyword `where`
 
 fn main() {}
index 65ddadb011d0f0c769276b546d3a9124ab455115..ff9e1215f103ed55ec7ea12dc55313d4b01f400e 100644 (file)
@@ -1,7 +1,7 @@
-error: expected item, found `where`
+error: expected item, found keyword `where`
   --> $DIR/issue-17904-2.rs:13:24
    |
-LL | struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
+LL | struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found keyword `where`
    |                        ^^^^^ expected item
 
 error: aborting due to previous error
index 1bcb5208d7610f5dbe0af7d665e8494809fa3b34..533b947b79ae9914d2b1d2e334eb97ff57b6668d 100644 (file)
@@ -12,7 +12,8 @@
 
 // Test syntax checks for `type` keyword.
 
-struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for`
+struct S1 for type;
+//~^ ERROR expected `where`, `{`, `(`, or `;` after struct name, found keyword `for`
 
 pub fn main() {
 }
index 89de7ee875856dbf1cde19d567565649f8eb3e5a..cc35c2035eae88aa8a700baf24b6cad928b2e9c7 100644 (file)
@@ -1,7 +1,7 @@
-error: expected `where`, `{`, `(`, or `;` after struct name, found `for`
+error: expected `where`, `{`, `(`, or `;` after struct name, found keyword `for`
   --> $DIR/unsized.rs:15:11
    |
-LL | struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for`
+LL | struct S1 for type;
    |           ^^^ expected `where`, `{`, `(`, or `;` after struct name
 
 error: aborting due to previous error
index f34eddc93c570595d5bf188de6586b59655bf89e..b7426140d8ac5c142fdc99b4b0b5255029891a57 100644 (file)
@@ -12,7 +12,8 @@
 
 // Test diagnostics for the removed struct inheritance feature.
 
-virtual struct SuperStruct { //~ ERROR expected item, found `virtual`
+virtual struct SuperStruct {
+//~^ ERROR expected item, found reserved keyword `virtual`
     f1: isize,
 }
 
index 6af9922a698c433bffb4144ae6fc95ba84ce7821..659c7701c00d688e218b711244168613642cec60 100644 (file)
@@ -1,7 +1,7 @@
-error: expected item, found `virtual`
+error: expected item, found reserved keyword `virtual`
   --> $DIR/virtual-structs.rs:15:1
    |
-LL | virtual struct SuperStruct { //~ ERROR expected item, found `virtual`
+LL | virtual struct SuperStruct {
    | ^^^^^^^ expected item
 
 error: aborting due to previous error
index 3627c09b28fd9dac873e23b298065ae20d3cc91c..3e330f9de6547a668b193379b029b9e8b0c47f4e 100644 (file)
@@ -2,7 +2,9 @@ error[E0404]: expected trait, found type alias `Foo`
   --> $DIR/issue-3907.rs:20:6
    |
 LL | impl Foo for S { //~ ERROR expected trait, found type alias `Foo`
-   |      ^^^ type aliases cannot be used for traits
+   |      ^^^ type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
 help: possible better candidate is found in another module, you can import it into scope
    |
 LL | use issue_3907::Foo;
index 353a0b1c3d9d09f322af8900053f4d643b2f95be..0acc5c8a93ec689c1e2fc5ef56d9d06207ddb825 100644 (file)
@@ -11,7 +11,9 @@ LL | impl K for isize {} //~ ERROR expected trait, found type alias `K`
    |      ^
    |      |
    |      did you mean `I`?
-   |      type aliases cannot be used for traits
+   |      type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
 
 error: aborting due to 2 previous errors
 
index f32c5e9b2c6bd2e2f5214315d6dd3271340de899..d293a77392e8997b80458653ce86b26259d5511f 100644 (file)
@@ -8,7 +8,9 @@ error[E0404]: expected trait, found type alias `Typedef`
   --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:16:8
    |
 LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used for traits
+   |        ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
+   |
+   = note: did you mean to use a trait alias?
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.fixed b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.fixed
new file mode 100644 (file)
index 0000000..fd9b10e
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+// run-rustfix
+
+#![feature(in_band_lifetimes)]
+#![deny(single_use_lifetimes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+// Test that we DO warn when lifetime name is used only
+// once in a fn argument, even with in band lifetimes.
+
+fn a(x: &u32, y: &u32) {
+    //~^ ERROR `'a` only used once
+    //~| ERROR `'b` only used once
+    //~| HELP elide the single-use lifetime
+    //~| HELP elide the single-use lifetime
+}
+
+fn main() { }
index 1aad3265cbe0af54f541d7d5f7a5607b199ef258..0d5f65e6d1b53e8bacef13e9f8907f9b67ea0a44 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 #![feature(in_band_lifetimes)]
 #![deny(single_use_lifetimes)]
 #![allow(dead_code)]
@@ -19,6 +21,8 @@
 fn a(x: &'a u32, y: &'b u32) {
     //~^ ERROR `'a` only used once
     //~| ERROR `'b` only used once
+    //~| HELP elide the single-use lifetime
+    //~| HELP elide the single-use lifetime
 }
 
 fn main() { }
index 6d18075ba37cf1174e56e34afe268672d0a38d7d..a9f8411d4110315ccde004cd23af9d45664ac5b4 100644 (file)
@@ -1,26 +1,26 @@
 error: lifetime parameter `'a` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:19:10
+  --> $DIR/one-use-in-fn-argument-in-band.rs:21:10
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |          ^^
+   |          ^^-
    |          |
-   |          this lifetime...
-   |          ...is used only here
+   |          this lifetime is only used here
+   |          help: elide the single-use lifetime
    |
 note: lint level defined here
-  --> $DIR/one-use-in-fn-argument-in-band.rs:12:9
+  --> $DIR/one-use-in-fn-argument-in-band.rs:14:9
    |
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: lifetime parameter `'b` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:19:22
+  --> $DIR/one-use-in-fn-argument-in-band.rs:21:22
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |                      ^^
+   |                      ^^-
    |                      |
-   |                      this lifetime...
-   |                      ...is used only here
+   |                      this lifetime is only used here
+   |                      help: elide the single-use lifetime
 
 error: aborting due to 2 previous errors
 
index 9ac813a24ded3cb07597e11a388ee41a071eabab..a1b8866c8c455741c2eae27d5914f7d9ee9e62df 100644 (file)
@@ -16,6 +16,7 @@
 // once in a fn argument.
 
 fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once
+    //~^ HELP elide the single-use lifetime
 }
 
 fn main() { }
index 4c13133581bb4d156433031f8ce36404b257a6d1..0a23ecaf458ad965db0107da1db87769275eea25 100644 (file)
@@ -11,6 +11,10 @@ note: lint level defined here
    |
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL | fn a(x: &u32) { //~ ERROR `'a` only used once
+   |    --   --
 
 error: aborting due to previous error
 
index a862bbbe30c09e4ebb32e45e27fd6c830e4ab0ed..b392f7a51746f07457964bd2a75bf3ea1b787449 100644 (file)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-// Test that we DO warn for a lifetime used only once in an impl.
-//
-// (Actually, until #15872 is fixed, you can't use `'_` here, but
-// hopefully that will come soon.)
+// Test that we DO warn for a lifetime used only once in an impl, and that we
+// don't warn for the anonymous lifetime.
 
 struct Foo<'f> {
     data: &'f u32
@@ -26,4 +24,9 @@ fn inherent_a(&self) {
     }
 }
 
+impl Foo<'_> {
+    fn inherent_b(&self) {}
+}
+
+
 fn main() { }
index 2509366f9696fb080dbe1d2b21b5740c89d51e9b..40dfa677d0ab2cc27c1372bb41aef44d4721ea4d 100644 (file)
@@ -1,5 +1,5 @@
 error: lifetime parameter `'f` only used once
-  --> $DIR/one-use-in-inherent-impl-header.rs:24:6
+  --> $DIR/one-use-in-inherent-impl-header.rs:22:6
    |
 LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
    |      ^^      -- ...is used only here
index 863d8faef6ea17ea964a091408dd4014840a4519..63c3bbdfe4a113e9cb497db18d55d03796140f04 100644 (file)
@@ -20,6 +20,7 @@ struct Foo<'f> {
 
 impl<'f> Foo<'f> { //~ ERROR `'f` only used once
     fn inherent_a<'a>(&self, data: &'a u32) { //~ ERROR `'a` only used once
+        //~^ HELP elide the single-use lifetime
     }
 }
 
index cfc8dbf18dc01d02c07045acf6eeacad050a748e..d0651a437b0919836f1b4d5547a0b3596329e241 100644 (file)
@@ -11,6 +11,10 @@ note: lint level defined here
    |
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL |     fn inherent_a(&self, data: &u32) { //~ ERROR `'a` only used once
+   |                 --             --
 
 error: lifetime parameter `'f` only used once
   --> $DIR/one-use-in-inherent-method-argument.rs:21:6
index 389ba5c873ad8e3681a794f5c8d92dd2392de90d..c36e9ef2b223740d3a42255d3cec8cbd42ca980c 100644 (file)
@@ -23,6 +23,7 @@ impl<'f> Iterator for Foo<'f> {
     type Item = &'f u32;
 
     fn next<'g>(&'g mut self) -> Option<Self::Item> { //~ ERROR `'g` only used once
+        //~^ HELP elide the single-use lifetime
         None
     }
 }
index 4a796d83242fd91570718d2a72c8e77b8ecf5bae..e054d0ad9349bc148ef4aaec561ad00ddaae01d7 100644 (file)
@@ -11,6 +11,10 @@ note: lint level defined here
    |
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: elide the single-use lifetime
+   |
+LL |     fn next(&mut self) -> Option<Self::Item> { //~ ERROR `'g` only used once
+   |           ----
 
 error: aborting due to previous error
 
index 5ba7df8a1e61fa3430cacf317da8e04165826ff0..89607af260a5258e795576acac33b085c34204fd 100644 (file)
@@ -7,17 +7,17 @@
 
 fn september() {}
 //~^ ERROR lifetime parameter `'a` never used
-//~| HELP remove it
+//~| HELP elide the unused lifetime
 
 fn october<'b, T>(s: &'b T) -> &'b T {
     //~^ ERROR lifetime parameter `'a` never used
-    //~| HELP remove it
+    //~| HELP elide the unused lifetime
     s
 }
 
 fn november<'a>(s: &'a str) -> (&'a str) {
     //~^ ERROR lifetime parameter `'b` never used
-    //~| HELP remove it
+    //~| HELP elide the unused lifetime
     s
 }
 
index a56d7fa8abc0275f40b323c8afc47bf2c948f6ae..be0bdb9b6285102ea40b2d906e6eec041595ef95 100644 (file)
@@ -7,17 +7,17 @@
 
 fn september<'a>() {}
 //~^ ERROR lifetime parameter `'a` never used
-//~| HELP remove it
+//~| HELP elide the unused lifetime
 
 fn october<'a, 'b, T>(s: &'b T) -> &'b T {
     //~^ ERROR lifetime parameter `'a` never used
-    //~| HELP remove it
+    //~| HELP elide the unused lifetime
     s
 }
 
 fn november<'a, 'b>(s: &'a str) -> (&'a str) {
     //~^ ERROR lifetime parameter `'b` never used
-    //~| HELP remove it
+    //~| HELP elide the unused lifetime
     s
 }
 
index 566c841cfa96984e853341f0fcc7c866b10e34d5..2ccba796d4229ebe319526d3280ee26057a72bea 100644 (file)
@@ -2,7 +2,7 @@ error: lifetime parameter `'a` never used
   --> $DIR/zero-uses-in-fn.rs:8:14
    |
 LL | fn september<'a>() {}
-   |             -^^- help: remove it
+   |             -^^- help: elide the unused lifetime
    |
 note: lint level defined here
   --> $DIR/zero-uses-in-fn.rs:5:9
@@ -16,7 +16,7 @@ error: lifetime parameter `'a` never used
 LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T {
    |            ^^--
    |            |
-   |            help: remove it
+   |            help: elide the unused lifetime
 
 error: lifetime parameter `'b` never used
   --> $DIR/zero-uses-in-fn.rs:18:17
@@ -24,7 +24,7 @@ error: lifetime parameter `'b` never used
 LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) {
    |               --^^
    |               |
-   |               help: remove it
+   |               help: elide the unused lifetime
 
 error: aborting due to 3 previous errors
 
index 1b77ebdec99c6af0986e62cfea945893261dc773..3f9d907ade6799dc324e1fd433a4395ef27b34ea 100644 (file)
@@ -2,7 +2,7 @@ error: lifetime parameter `'a` never used
   --> $DIR/zero-uses-in-impl.rs:8:6
    |
 LL | impl<'a> Foo {} //~ ERROR `'a` never used
-   |     -^^- help: remove it
+   |     -^^- help: elide the unused lifetime
    |
 note: lint level defined here
   --> $DIR/zero-uses-in-impl.rs:3:9
diff --git a/src/test/ui/trait-alias-fail.rs b/src/test/ui/trait-alias-fail.rs
deleted file mode 100644 (file)
index 7aca227..0000000
+++ /dev/null
@@ -1,27 +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.
-
-// gate-test-trait_alias
-
-trait Alias1<T> = Default where T: Clone; // ok
-    //~^ERROR trait aliases are not yet fully implemented
-trait Alias2<T: Clone = ()> = Default;
-    //~^ERROR type parameters on the left side of a trait alias cannot be bounded
-    //~^^ERROR type parameters on the left side of a trait alias cannot have defaults
-    //~^^^ERROR trait aliases are not yet fully implemented
-
-impl Alias1 { //~ERROR expected type, found trait alias
-}
-
-impl Alias1 for () { //~ERROR expected trait, found trait alias
-}
-
-fn main() {}
-
diff --git a/src/test/ui/trait-alias-fail.stderr b/src/test/ui/trait-alias-fail.stderr
deleted file mode 100644 (file)
index f7b144c..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error: type parameters on the left side of a trait alias cannot be bounded
-  --> $DIR/trait-alias-fail.rs:15:14
-   |
-LL | trait Alias2<T: Clone = ()> = Default;
-   |              ^
-
-error: type parameters on the left side of a trait alias cannot have defaults
-  --> $DIR/trait-alias-fail.rs:15:14
-   |
-LL | trait Alias2<T: Clone = ()> = Default;
-   |              ^
-
-error[E0573]: expected type, found trait alias `Alias1`
-  --> $DIR/trait-alias-fail.rs:20:6
-   |
-LL | impl Alias1 { //~ERROR expected type, found trait alias
-   |      ^^^^^^ not a type
-
-error[E0404]: expected trait, found trait alias `Alias1`
-  --> $DIR/trait-alias-fail.rs:23:6
-   |
-LL | impl Alias1 for () { //~ERROR expected trait, found trait alias
-   |      ^^^^^^ not a trait
-
-error[E0658]: trait aliases are not yet fully implemented (see issue #41517)
-  --> $DIR/trait-alias-fail.rs:13:1
-   |
-LL | trait Alias1<T> = Default where T: Clone; // ok
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(trait_alias)] to the crate attributes to enable
-
-error[E0658]: trait aliases are not yet fully implemented (see issue #41517)
-  --> $DIR/trait-alias-fail.rs:15:1
-   |
-LL | trait Alias2<T: Clone = ()> = Default;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(trait_alias)] to the crate attributes to enable
-
-error: aborting due to 6 previous errors
-
-Some errors occurred: E0404, E0573, E0658.
-For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/traits/trait-alias-impl.rs b/src/test/ui/traits/trait-alias-impl.rs
new file mode 100644 (file)
index 0000000..bf34830
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+trait DefaultAlias = Default;
+
+impl DefaultAlias for () {}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias-impl.stderr b/src/test/ui/traits/trait-alias-impl.stderr
new file mode 100644 (file)
index 0000000..9ad6251
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found trait alias `DefaultAlias`
+  --> $DIR/trait-alias-impl.rs:15:6
+   |
+LL | impl DefaultAlias for () {}
+   |      ^^^^^^^^^^^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/traits/trait-alias-objects.rs b/src/test/ui/traits/trait-alias-objects.rs
new file mode 100644 (file)
index 0000000..3adcd84
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+trait EqAlias = Eq;
+trait IteratorAlias = Iterator;
+
+fn main() {
+    let _: &dyn EqAlias = &123;
+    let _: &dyn IteratorAlias = &vec![123].into_iter();
+}
diff --git a/src/test/ui/traits/trait-alias-objects.stderr b/src/test/ui/traits/trait-alias-objects.stderr
new file mode 100644 (file)
index 0000000..8f9681e
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0038]: the trait `EqAlias` cannot be made into an object
+  --> $DIR/trait-alias-objects.rs:17:13
+   |
+LL |     let _: &dyn EqAlias = &123;
+   |             ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
+  --> $DIR/trait-alias-objects.rs:18:13
+   |
+LL |     let _: &dyn IteratorAlias = &vec![123].into_iter();
+   |             ^^^^^^^^^^^^^^^^^ missing associated type `Item` value
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0038, E0191.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-alias-wf.rs b/src/test/ui/traits/trait-alias-wf.rs
new file mode 100644 (file)
index 0000000..8c8ce12
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+trait Foo {}
+trait A<T: Foo> {}
+trait B<T> = A<T>; // T cannot be unbounded
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias-wf.stderr
new file mode 100644 (file)
index 0000000..e8c81c8
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `T: Foo` is not satisfied
+  --> $DIR/trait-alias-wf.rs:15:1
+   |
+LL | trait B<T> = A<T>; // T cannot be unbounded
+   | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Foo` bound
+note: required by `A`
+  --> $DIR/trait-alias-wf.rs:14:1
+   |
+LL | trait A<T: Foo> {}
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/trait-alias.rs b/src/test/ui/traits/trait-alias.rs
deleted file mode 100644 (file)
index 9ea211b..0000000
+++ /dev/null
@@ -1,43 +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.
-
-#![feature(trait_alias)]
-
-trait SimpleAlias = Default; //~ERROR E0645
-trait GenericAlias<T> = Iterator<Item=T>; //~ERROR E0645
-trait Partial<T> = IntoIterator<Item=T>; //~ERROR E0645
-
-trait Things<T> {}
-trait Romeo {}
-struct The<T>(T);
-struct Fore<T>(T);
-impl<T, U> Things<T> for The<U> {}
-impl<T> Romeo for Fore<T> {}
-
-trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645
-trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>; //~ERROR E0645
-
-trait CD = Clone + Default; //~ERROR E0645
-
-fn foo<T: CD>() -> (T, T) {
-    let one = T::default();
-    let two = one.clone();
-    (one, two)
-}
-
-fn main() {
-    let both = foo();
-    assert_eq!(both.0, 0);
-    assert_eq!(both.1, 0);
-    let both: (i32, i32) = foo();
-    assert_eq!(both.0, 0);
-    assert_eq!(both.1, 0);
-}
-
diff --git a/src/test/ui/traits/trait-alias.stderr b/src/test/ui/traits/trait-alias.stderr
deleted file mode 100644 (file)
index 5d290e5..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0645]: trait aliases are not yet implemented (see issue #41517)
-  --> $DIR/trait-alias.rs:13:1
-   |
-LL | trait SimpleAlias = Default; //~ERROR E0645
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0645]: trait aliases are not yet implemented (see issue #41517)
-  --> $DIR/trait-alias.rs:14:1
-   |
-LL | trait GenericAlias<T> = Iterator<Item=T>; //~ERROR E0645
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0645]: trait aliases are not yet implemented (see issue #41517)
-  --> $DIR/trait-alias.rs:15:1
-   |
-LL | trait Partial<T> = IntoIterator<Item=T>; //~ERROR E0645
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0645]: trait aliases are not yet implemented (see issue #41517)
-  --> $DIR/trait-alias.rs:24:1
-   |
-LL | trait WithWhere<Art, Thou> = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; //~ERROR E0645
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0645]: trait aliases are not yet implemented (see issue #41517)
-  --> $DIR/trait-alias.rs:25:1
-   |
-LL | trait BareWhere<Wild, Are> = where The<Wild>: Things<Are>; //~ERROR E0645
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0645]: trait aliases are not yet implemented (see issue #41517)
-  --> $DIR/trait-alias.rs:27:1
-   |
-LL | trait CD = Clone + Default; //~ERROR E0645
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0645`.
index a20599ab57d08bb61cd177f9c0c98ec395376dd8..71ec4ff636b9315cfaadd30e45338a077ed98a9b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a20599ab57d08bb61cd177f9c0c98ec395376dd8
+Subproject commit 71ec4ff636b9315cfaadd30e45338a077ed98a9b
index 40917cc5db0d5f6eba8086615706c1774d4d9793..a5556e1d570eb89e6f04ffb258bd8f1f7ff9bfc8 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(rustc_private)]
 
+extern crate env_logger;
 extern crate syntax;
 extern crate rustdoc;
 extern crate serialize as rustc_serialize;
@@ -264,6 +265,7 @@ fn parse_args() -> (OutputFormat, PathBuf) {
 }
 
 fn main() {
+    env_logger::init();
     PLAYGROUND.with(|slot| {
         *slot.borrow_mut() = Some((None, String::from("https://play.rust-lang.org/")));
     });
index c794e169fca3322f58ac72e99ca5fb34f34d823c..4ade87f5d65bd2c167175bcf27ca178a28df1b50 100755 (executable)
@@ -26,7 +26,7 @@ except ImportError:
 MAINTAINERS = {
     'miri': '@oli-obk @RalfJung @eddyb',
     'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk',
-    'rls': '@nrc',
+    'rls': '@nrc @Xanewok',
     'rustfmt': '@nrc',
     'book': '@carols10cents @steveklabnik',
     'nomicon': '@frewsxcv @Gankro',
@@ -81,8 +81,8 @@ def update_latest(
                 status[os] = new
                 if new > old:
                     changed = True
-                    message += '🎉 {} on {}: {} → {}.\n' \
-                        .format(tool, os, old, new)
+                    message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
+                        .format(tool, os, old, new, MAINTAINERS.get(tool))
                 elif new < old:
                     changed = True
                     message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \