]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #73905 - matthewjasper:projection-bounds-2, r=nikomatsakis
authorbors <bors@rust-lang.org>
Tue, 6 Oct 2020 12:26:54 +0000 (12:26 +0000)
committerbors <bors@rust-lang.org>
Tue, 6 Oct 2020 12:26:54 +0000 (12:26 +0000)
Separate projection bounds and predicates

Follow up to #72788.

- Rename `projection_predicates` to `item_bounds`
- Separate bounds on associated types (the things after the `:` in `type X: ...`) and opaque types (the things after `impl`)  from predicates.
- Projection candidates now have the correct nested obligations
- Trait object candidates now check that the associated types on the trait object satisfy their bounds as nested obligations
- Type alias impl trait types are now checked (#73035)
- `feature(generic_associated_types)` no longer changes how we handle bounds (#73816)

Opening for a perf and crater runs.

r? `@nikomatsakis`

261 files changed:
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_error_codes/src/error_codes/E0284.md
compiler/rustc_infer/src/infer/higher_ranked/mod.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/outlives/verify.rs
compiler/rustc_infer/src/traits/util.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/select.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/db.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/implied_outlives_bounds.rs
compiler/rustc_ty/src/ty.rs
compiler/rustc_typeck/src/bounds.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/item_bounds.rs [new file with mode: 0644]
compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/html/render/mod.rs
src/test/incremental/issue-54242.rs
src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs [new file with mode: 0644]
src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs
src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr
src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs
src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs
src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr [new file with mode: 0644]
src/test/ui/associated-type-bounds/duplicate.stderr
src/test/ui/associated-types/associate-type-bound-normalization.rs [new file with mode: 0644]
src/test/ui/associated-types/associated-types-bound-ambiguity.rs [new file with mode: 0644]
src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs [new file with mode: 0644]
src/test/ui/associated-types/associated-types-unconstrained.stderr
src/test/ui/associated-types/defaults-cyclic-fail-1.rs
src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
src/test/ui/associated-types/defaults-cyclic-fail-2.rs
src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
src/test/ui/associated-types/defaults-suitability.rs
src/test/ui/associated-types/defaults-suitability.stderr
src/test/ui/associated-types/defaults-unsound-62211-1.rs
src/test/ui/associated-types/defaults-unsound-62211-1.stderr
src/test/ui/associated-types/defaults-unsound-62211-2.rs
src/test/ui/associated-types/defaults-unsound-62211-2.stderr
src/test/ui/associated-types/defaults-wf.rs [new file with mode: 0644]
src/test/ui/associated-types/defaults-wf.stderr [new file with mode: 0644]
src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr
src/test/ui/associated-types/issue-43924.rs
src/test/ui/associated-types/issue-43924.stderr
src/test/ui/associated-types/issue-63593.stderr
src/test/ui/associated-types/issue-65774-1.rs
src/test/ui/associated-types/issue-65774-1.stderr
src/test/ui/associated-types/issue-65774-2.rs
src/test/ui/associated-types/issue-65774-2.stderr
src/test/ui/associated-types/issue-72806.rs
src/test/ui/associated-types/issue-72806.stderr
src/test/ui/associated-types/object-normalization.rs [new file with mode: 0644]
src/test/ui/associated-types/param-env-normalize-cycle.rs [new file with mode: 0644]
src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs
src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
src/test/ui/associated-types/point-at-type-on-obligation-failure.rs
src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr
src/test/ui/associated-types/wf-cycle-2.rs [new file with mode: 0644]
src/test/ui/associated-types/wf-cycle.rs [new file with mode: 0644]
src/test/ui/async-await/async-error-span.stderr
src/test/ui/async-await/issue-61076.stderr
src/test/ui/async-await/issue-64130-4-async-move.stderr
src/test/ui/async-await/issue-67765-async-diagnostic.stderr
src/test/ui/async-await/issue-70818.stderr
src/test/ui/chalkify/impl_wf.rs
src/test/ui/chalkify/impl_wf.stderr
src/test/ui/chalkify/impl_wf_2.rs [new file with mode: 0644]
src/test/ui/chalkify/impl_wf_2.stderr [new file with mode: 0644]
src/test/ui/closures/issue-41366.rs
src/test/ui/closures/issue-41366.stderr
src/test/ui/conservative_impl_trait.stderr
src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
src/test/ui/for/for-c-in-str.rs
src/test/ui/for/for-c-in-str.stderr
src/test/ui/for/for-loop-bogosity.stderr
src/test/ui/generator/sized-yield.stderr
src/test/ui/generator/type-mismatch-signature-deduction.stderr
src/test/ui/generic-associated-types/auxiliary/foo_defn.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/cross-crate-bounds.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/cross-crate-bounds.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/generic-associated-types-where.rs
src/test/ui/generic-associated-types/generic-associated-types-where.stderr
src/test/ui/generic-associated-types/impl_bounds.rs
src/test/ui/generic-associated-types/impl_bounds.stderr
src/test/ui/generic-associated-types/impl_bounds_ok.rs
src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr
src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr
src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr
src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr
src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/projection-bound-cycle.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/projection-bound-cycle.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs
src/test/ui/impl-trait/bound-normalization-fail.stderr
src/test/ui/impl-trait/issue-55872-1.stderr
src/test/ui/impl-trait/issue-55872-2.stderr
src/test/ui/impl-trait/wf-eval-order.rs [new file with mode: 0644]
src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
src/test/ui/inference/cannot-infer-async.stderr
src/test/ui/inference/cannot-infer-closure.stderr
src/test/ui/issues-71798.stderr
src/test/ui/issues/issue-20605.stderr
src/test/ui/issues/issue-20831-debruijn.rs
src/test/ui/issues/issue-20831-debruijn.stderr
src/test/ui/issues/issue-21946.rs
src/test/ui/issues/issue-21946.stderr
src/test/ui/issues/issue-23122-1.rs
src/test/ui/issues/issue-23122-1.stderr
src/test/ui/issues/issue-23122-2.rs
src/test/ui/issues/issue-23122-2.stderr
src/test/ui/issues/issue-24204.rs
src/test/ui/issues/issue-24204.stderr [deleted file]
src/test/ui/issues/issue-28098.stderr
src/test/ui/issues/issue-33941.stderr
src/test/ui/issues/issue-38091.rs [deleted file]
src/test/ui/issues/issue-38091.stderr [deleted file]
src/test/ui/issues/issue-41139.rs
src/test/ui/issues/issue-41139.stderr
src/test/ui/issues/issue-43784-associated-type.stderr
src/test/ui/issues/issue-43784-supertrait.stderr
src/test/ui/issues/issue-58344.rs
src/test/ui/issues/issue-58344.stderr [deleted file]
src/test/ui/issues/issue-60283.rs
src/test/ui/issues/issue-60283.stderr
src/test/ui/issues/issue-65673.stderr
src/test/ui/iterators/array-of-ranges.stderr
src/test/ui/iterators/array.stderr
src/test/ui/iterators/integral.stderr
src/test/ui/iterators/ranges.stderr
src/test/ui/iterators/string.stderr
src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
src/test/ui/never_type/feature-gate-never_type_fallback.stderr
src/test/ui/never_type/issue-51506.stderr
src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs
src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
src/test/ui/object-safety/object-safety-bounds.rs [new file with mode: 0644]
src/test/ui/object-safety/object-safety-bounds.stderr [new file with mode: 0644]
src/test/ui/parser/struct-literal-in-for.stderr
src/test/ui/privacy/private-in-public-assoc-ty.rs
src/test/ui/privacy/private-in-public-assoc-ty.stderr
src/test/ui/privacy/private-in-public-warn.rs
src/test/ui/privacy/private-in-public-warn.stderr
src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr
src/test/ui/question-mark-type-infer.stderr
src/test/ui/range/range-1.stderr
src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs
src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs
src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
src/test/ui/regions/regions-enum-not-wf.rs
src/test/ui/regions/regions-enum-not-wf.stderr
src/test/ui/regions/regions-normalize-in-where-clause-list.rs
src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
src/test/ui/regions/regions-trait-1.rs
src/test/ui/regions/regions-trait-1.stderr [deleted file]
src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs
src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
src/test/ui/specialization/deafult-associated-type-bound-1.stderr
src/test/ui/specialization/deafult-associated-type-bound-2.stderr
src/test/ui/specialization/deafult-generic-associated-type-bound.rs
src/test/ui/specialization/deafult-generic-associated-type-bound.stderr
src/test/ui/specialization/issue-38091-2.rs [new file with mode: 0644]
src/test/ui/specialization/issue-38091-2.stderr [new file with mode: 0644]
src/test/ui/specialization/issue-38091.rs [new file with mode: 0644]
src/test/ui/specialization/issue-38091.stderr [new file with mode: 0644]
src/test/ui/specialization/issue-44861.stderr
src/test/ui/specialization/issue-59435.stderr
src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr
src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs
src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr [deleted file]
src/test/ui/suggestions/suggest-remove-refs-1.stderr
src/test/ui/suggestions/suggest-remove-refs-2.stderr
src/test/ui/suggestions/suggest-remove-refs-3.stderr
src/test/ui/traits/check-trait-object-bounds-1.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-1.stderr [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-2-ok.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-2.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-2.stderr [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-3.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-3.stderr [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-4.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-4.stderr [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-5.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-5.stderr [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-6.rs [new file with mode: 0644]
src/test/ui/traits/check-trait-object-bounds-6.stderr [new file with mode: 0644]
src/test/ui/traits/cycle-cache-err-60010.rs
src/test/ui/traits/cycle-cache-err-60010.stderr
src/test/ui/traits/trait-object-bounds-cycle-1.rs [new file with mode: 0644]
src/test/ui/traits/trait-object-bounds-cycle-2.rs [new file with mode: 0644]
src/test/ui/traits/trait-object-bounds-cycle-3.rs [new file with mode: 0644]
src/test/ui/traits/trait-object-bounds-cycle-4.rs [new file with mode: 0644]
src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs [new file with mode: 0644]
src/test/ui/traits/traits-inductive-overflow-two-traits.rs
src/test/ui/traits/traits-inductive-overflow-two-traits.stderr
src/test/ui/try-block/try-block-bad-type.rs
src/test/ui/try-block/try-block-bad-type.stderr
src/test/ui/try-block/try-block-in-while.stderr
src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/bounds-are-checked.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs
src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
src/test/ui/type-alias-impl-trait/issue-60371.stderr
src/test/ui/type-alias-impl-trait/issue-63279.stderr
src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/utils/mod.rs

index c97f80cf09ba17ceeddf36937ecbe75c2117e9f8..4676ad5c31fca360b1b3478b5b3a87c1f131c36c 100644 (file)
@@ -432,17 +432,25 @@ fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
         self.with_catch_scope(body.id, |this| {
             let mut block = this.lower_block_noalloc(body, true);
 
-            let try_span = this.mark_span_with_reason(
-                DesugaringKind::TryBlock,
-                body.span,
-                this.allow_try_trait.clone(),
-            );
-
             // Final expression of the block (if present) or `()` with span at the end of block
-            let tail_expr = block
-                .expr
-                .take()
-                .unwrap_or_else(|| this.expr_unit(this.sess.source_map().end_point(try_span)));
+            let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
+                (
+                    this.mark_span_with_reason(
+                        DesugaringKind::TryBlock,
+                        expr.span,
+                        this.allow_try_trait.clone(),
+                    ),
+                    expr,
+                )
+            } else {
+                let try_span = this.mark_span_with_reason(
+                    DesugaringKind::TryBlock,
+                    this.sess.source_map().end_point(body.span),
+                    this.allow_try_trait.clone(),
+                );
+
+                (try_span, this.expr_unit(try_span))
+            };
 
             let ok_wrapped_span =
                 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
@@ -1553,7 +1561,7 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                 hir::LangItem::TryFromError,
                 unstable_span,
                 from_expr,
-                try_span,
+                unstable_span,
             );
             let thin_attrs = ThinVec::from(attrs);
             let catch_scope = self.catch_scopes.last().copied();
index a1ffa2bda0050c267a917ef365e9dcaa8fc048e1..82598aeec021598fa55e61164d209e28867d552f 100644 (file)
@@ -5,37 +5,29 @@ as the `collect` method for `Iterator`s.
 For example:
 
 ```compile_fail,E0284
-fn foo() -> Result<bool, ()> {
-    let results = [Ok(true), Ok(false), Err(())].iter().cloned();
-    let v: Vec<bool> = results.collect()?;
-    // Do things with v...
-    Ok(true)
+fn main() {
+    let n: u32 = 1;
+    let mut d: u64 = 2;
+    d = d + n.into();
 }
 ```
 
-Here we have an iterator `results` over `Result<bool, ()>`.
-Hence, `results.collect()` can return any type implementing
-`FromIterator<Result<bool, ()>>`. On the other hand, the
-`?` operator can accept any type implementing `Try`.
+Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return
+any type `T` where `u64: Add<T>`. On the other hand, the `into` method can
+return any type where `u32: Into<T>`.
 
-The author of this code probably wants `collect()` to return a
-`Result<Vec<bool>, ()>`, but the compiler can't be sure
-that there isn't another type `T` implementing both `Try` and
-`FromIterator<Result<bool, ()>>` in scope such that
-`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
-is returned.
+The author of this code probably wants `into()` to return a `u64`, but the
+compiler can't be sure that there isn't another type `T` where both
+`u32: Into<T>` and `u64: Add<T>`.
 
 To resolve this error, use a concrete type for the intermediate expression:
 
 ```
-fn foo() -> Result<bool, ()> {
-    let results = [Ok(true), Ok(false), Err(())].iter().cloned();
-    let v = {
-        let temp: Result<Vec<bool>, ()> = results.collect();
-        temp?
-    };
-    // Do things with v...
-    Ok(true)
+fn main() {
+    let n: u32 = 1;
+    let mut d: u64 = 2;
+    let m: u64 = n.into();
+    d = d + m;
 }
 ```
 
index ea19dff7db125098ba4b1ad85f765af989cf64aa..e3365e8590b5edecf7d25beb7e04ee9fe2a46e10 100644 (file)
@@ -2,7 +2,7 @@
 //! the end of the file for details.
 
 use super::combine::CombineFields;
-use super::{HigherRankedType, InferCtxt, PlaceholderMap};
+use super::{HigherRankedType, InferCtxt};
 
 use crate::infer::CombinedSnapshot;
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
@@ -33,7 +33,7 @@ pub fn higher_ranked_sub<T>(
         self.infcx.commit_if_ok(|_| {
             // First, we instantiate each bound region in the supertype with a
             // fresh placeholder region.
-            let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b);
+            let b_prime = self.infcx.replace_bound_vars_with_placeholders(&b);
 
             // Next, we instantiate each bound region in the subtype
             // with a fresh region variable. These region variables --
@@ -66,10 +66,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// the [rustc dev guide].
     ///
     /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-    pub fn replace_bound_vars_with_placeholders<T>(
-        &self,
-        binder: &ty::Binder<T>,
-    ) -> (T, PlaceholderMap<'tcx>)
+    pub fn replace_bound_vars_with_placeholders<T>(&self, binder: &ty::Binder<T>) -> T
     where
         T: TypeFoldable<'tcx>,
     {
@@ -122,7 +119,7 @@ pub fn replace_bound_vars_with_placeholders<T>(
             next_universe, binder, result, map,
         );
 
-        (result, map)
+        result
     }
 
     /// See `infer::region_constraints::RegionConstraintCollector::leak_check`.
index 07a55c7f859c34f08dc6ee173edebbf92550baf0..9742f5e2346516339033b96264b0ed9ef362b6d1 100644 (file)
@@ -351,11 +351,6 @@ pub struct InferCtxt<'a, 'tcx> {
     universe: Cell<ty::UniverseIndex>,
 }
 
-/// A map returned by `replace_bound_vars_with_placeholders()`
-/// indicating the placeholder region that each late-bound region was
-/// replaced with.
-pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
-
 /// See the `error_reporting` module for more details.
 #[derive(Clone, Debug, PartialEq, Eq, TypeFoldable)]
 pub enum ValuePairs<'tcx> {
@@ -992,7 +987,7 @@ pub fn subtype_predicate(
         }
 
         Some(self.commit_if_ok(|_snapshot| {
-            let (ty::SubtypePredicate { a_is_expected, a, b }, _) =
+            let ty::SubtypePredicate { a_is_expected, a, b } =
                 self.replace_bound_vars_with_placeholders(&predicate);
 
             let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@@ -1007,7 +1002,7 @@ pub fn region_outlives_predicate(
         predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
     ) -> UnitResult<'tcx> {
         self.commit_if_ok(|_snapshot| {
-            let (ty::OutlivesPredicate(r_a, r_b), _) =
+            let ty::OutlivesPredicate(r_a, r_b) =
                 self.replace_bound_vars_with_placeholders(&predicate);
             let origin = SubregionOrigin::from_obligation_cause(cause, || {
                 RelateRegionParamBound(cause.span)
index 07924298c241bc67adcbfcf64836c917df347a4f..2b827f4f4eddc43411296d763d75c4cd3995b1cc 100644 (file)
@@ -328,8 +328,8 @@ fn region_bounds_declared_on_associated_item(
         assoc_item_def_id: DefId,
     ) -> impl Iterator<Item = ty::Region<'tcx>> {
         let tcx = self.tcx;
-        let predicates = tcx.projection_predicates(assoc_item_def_id);
-        predicates
+        let bounds = tcx.item_bounds(assoc_item_def_id);
+        bounds
             .into_iter()
             .filter_map(|p| p.to_opt_type_outlives())
             .filter_map(|p| p.no_bound_vars())
index 9c0d934a03529a75c39e2fac97710f4a4d02f9c0..1b7269706a7583f61b1e880290249c8a62614a33 100644 (file)
@@ -4,7 +4,6 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::ty::outlives::Component;
 use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
-use rustc_span::Span;
 
 pub fn anonymize_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -94,7 +93,11 @@ pub fn elaborate_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
 ) -> Elaborator<'tcx> {
-    let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect();
+    let obligations = predicates
+        .map(|predicate| {
+            predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy())
+        })
+        .collect();
     elaborate_obligations(tcx, obligations)
 }
 
@@ -109,15 +112,10 @@ pub fn elaborate_obligations<'tcx>(
 
 fn predicate_obligation<'tcx>(
     predicate: ty::Predicate<'tcx>,
-    span: Option<Span>,
+    param_env: ty::ParamEnv<'tcx>,
+    cause: ObligationCause<'tcx>,
 ) -> PredicateObligation<'tcx> {
-    let cause = if let Some(span) = span {
-        ObligationCause::dummy_with_span(span)
-    } else {
-        ObligationCause::dummy()
-    };
-
-    Obligation { cause, param_env: ty::ParamEnv::empty(), recursion_depth: 0, predicate }
+    Obligation { cause, param_env, recursion_depth: 0, predicate }
 }
 
 impl Elaborator<'tcx> {
@@ -133,10 +131,11 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                 // Get predicates declared on the trait.
                 let predicates = tcx.super_predicates_of(data.def_id());
 
-                let obligations = predicates.predicates.iter().map(|&(pred, span)| {
+                let obligations = predicates.predicates.iter().map(|&(pred, _)| {
                     predicate_obligation(
                         pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
-                        Some(span),
+                        obligation.param_env,
+                        obligation.cause.clone(),
                     )
                 });
                 debug!("super_predicates: data={:?}", data);
@@ -233,7 +232,13 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                         })
                         .map(|predicate_kind| predicate_kind.to_predicate(tcx))
                         .filter(|&predicate| visited.insert(predicate))
-                        .map(|predicate| predicate_obligation(predicate, None)),
+                        .map(|predicate| {
+                            predicate_obligation(
+                                predicate,
+                                obligation.param_env,
+                                obligation.cause.clone(),
+                            )
+                        }),
                 );
             }
             ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
index 1e8c30071e762aecb5f1c06fb1c120498d58c422..3abd9a6325d6ee0e1a061546693efd4a69ed536f 100644 (file)
@@ -200,7 +200,7 @@ fn check_must_use_ty<'tcx>(
                 ty::Adt(def, _) => check_must_use_def(cx, def.did, span, descr_pre, descr_post),
                 ty::Opaque(def, _) => {
                     let mut has_emitted = false;
-                    for (predicate, _) in cx.tcx.predicates_of(def).predicates {
+                    for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
                         // We only look at the `DefId`, so it is safe to skip the binder here.
                         if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) =
                             predicate.skip_binders()
index 8b11d2c913ac2e0fe45856ebf7a115b4a00c03fe..2662f6b6ed65cec9781549636b480ea35045e207 100644 (file)
@@ -937,7 +937,7 @@ fn get_inferred_outlives(
             .tables
             .inferred_outlives
             .get(self, item_id)
-            .map(|predicates| predicates.decode((self, tcx)))
+            .map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx))))
             .unwrap_or_default()
     }
 
@@ -949,6 +949,19 @@ fn get_super_predicates(
         self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
     }
 
+    fn get_explicit_item_bounds(
+        &self,
+        item_id: DefIndex,
+        tcx: TyCtxt<'tcx>,
+    ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+        self.root
+            .tables
+            .explicit_item_bounds
+            .get(self, item_id)
+            .map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx))))
+            .unwrap_or_default()
+    }
+
     fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
         self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess))
     }
index 578ce382912f0a25c357b8f94bcf0a01f1f82847..60705f68681a1d6170a600ff5a05533695f3af7e 100644 (file)
@@ -89,6 +89,7 @@ fn into_args(self) -> (DefId, DefId) {
     explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) }
     inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) }
     super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
+    explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
     trait_def => { cdata.get_trait_def(def_id.index, tcx.sess) }
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
     adt_destructor => {
index 4350ac5c27a88813ec9919b900548b5d103412ff..f0911928e81c9cf97e5d1782a8bbc6dc77fb6083 100644 (file)
@@ -965,6 +965,14 @@ fn encode_super_predicates(&mut self, def_id: DefId) {
         record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
     }
 
+    fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
+        debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
+        let bounds = self.tcx.explicit_item_bounds(def_id);
+        if !bounds.is_empty() {
+            record!(self.tables.explicit_item_bounds[def_id] <- bounds);
+        }
+    }
+
     fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
@@ -1017,7 +1025,10 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
                     has_self: trait_item.fn_has_self_parameter,
                 }))
             }
-            ty::AssocKind::Type => EntryKind::AssocType(container),
+            ty::AssocKind::Type => {
+                self.encode_explicit_item_bounds(def_id);
+                EntryKind::AssocType(container)
+            }
         });
         record!(self.tables.visibility[def_id] <- trait_item.vis);
         record!(self.tables.span[def_id] <- ast_item.span);
@@ -1255,7 +1266,10 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
             hir::ItemKind::TyAlias(..) => EntryKind::Type,
-            hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy,
+            hir::ItemKind::OpaqueTy(..) => {
+                self.encode_explicit_item_bounds(def_id);
+                EntryKind::OpaqueTy
+            }
             hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr),
             hir::ItemKind::Struct(ref struct_def, _) => {
                 let adt_def = self.tcx.adt_def(def_id);
index 9e26d02e4e16d7c1e19397ea6f3096e55cbca0a9..2bd2019d3cdb529b617f00d274ee4db57e7470bc 100644 (file)
@@ -295,13 +295,11 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
     generics: Table<DefIndex, Lazy<ty::Generics>>,
     explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
     expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
-    // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
-    // doesn't handle shorthands in its own (de)serialization impls,
-    // as it's an `enum` for which we want to derive (de)serialization,
-    // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
-    // Also, as an optimization, a missing entry indicates an empty `&[]`.
-    inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
+    // As an optimization, a missing entry indicates an empty `&[]`.
+    inferred_outlives: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
     super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
+    // As an optimization, a missing entry indicates an empty `&[]`.
+    explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
     mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
index fe115bbb9c334896f6a273c28bac2f8bbe436669..fc4c343372a425d980d065e660f3db5a2459aa72 100644 (file)
@@ -156,12 +156,11 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             cache_on_disk_if { key.is_local() }
         }
 
-        /// Returns the list of predicates that can be used for
-        /// `SelectionCandidate::ProjectionCandidate` and
+        /// Returns the list of bounds that can be used for
+        /// `SelectionCandidate::ProjectionCandidate(_)` and
         /// `ProjectionTyCandidate::TraitDef`.
-        /// Specifically this is the bounds (equivalent to) those
-        /// written on the trait's type definition, or those
-        /// after the `impl` keyword
+        /// Specifically this is the bounds written on the trait's type
+        /// definition, or those after the `impl` keyword
         ///
         /// type X: Bound + 'lt
         ///         ^^^^^^^^^^^
@@ -169,8 +168,30 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         ///      ^^^^^^^^^^^^^^^
         ///
         /// `key` is the `DefId` of the associated type or opaque type.
-        query projection_predicates(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
-            desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
+        ///
+        /// Bounds from the parent (e.g. with nested impl trait) are not included.
+        query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+            desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
+        }
+
+        /// Elaborated version of the predicates from `explicit_item_bounds`.
+        ///
+        /// Example for
+        ///
+        /// trait MyTrait {
+        ///     type MyAType: Eq + ?Sized`
+        /// }
+        ///
+        /// `explicit_item_bounds` returns `[<Self as MyTrait>::MyAType: Eq]`,
+        /// and `item_bounds` returns
+        /// [
+        ///     <Self as Trait>::MyAType: Eq,
+        ///     <Self as Trait>::MyAType: PartialEq<<Self as Trait>::MyAType>
+        /// ]
+        ///
+        /// Bounds from the parent (e.g. with nested impl trait) are not included.
+        query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+            desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
         }
 
         query projection_ty_from_predicates(key: (DefId, DefId)) -> Option<ty::ProjectionTy<'tcx>> {
@@ -370,6 +391,24 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) }
         }
 
+        /// Returns everything that looks like a predicate written explicitly
+        /// by the user on a trait item.
+        ///
+        /// Traits are unusual, because predicates on associated types are
+        /// converted into bounds on that type for backwards compatibility:
+        ///
+        /// trait X where Self::U: Copy { type U; }
+        ///
+        /// becomes
+        ///
+        /// trait X { type U: Copy; }
+        ///
+        /// `explicit_predicates_of` and `explicit_item_bounds` will then take
+        /// the appropriate subsets of the predicates here.
+        query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> {
+            desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
         /// Returns the predicates written explicitly by the user.
         query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
             desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
index 6ad514c6be21b93dd79c3ef546ae2636ed980096..358ead507b4d0465f590081913acb6e517569f54 100644 (file)
@@ -105,9 +105,10 @@ pub enum SelectionCandidate<'tcx> {
     ImplCandidate(DefId),
     AutoImplCandidate(DefId),
 
-    /// This is a trait matching with a projected type as `Self`, and
-    /// we found an applicable bound in the trait definition.
-    ProjectionCandidate,
+    /// This is a trait matching with a projected type as `Self`, and we found
+    /// an applicable bound in the trait definition. The `usize` is an index
+    /// into the list returned by `tcx.item_bounds`.
+    ProjectionCandidate(usize),
 
     /// Implementation of a `Fn`-family trait by one of the anonymous types
     /// generated for a `||` expression.
index 238bce94cf50529bdd5ae2f38a144d6749c2bfbc..e1f02d0f70418547704cb820a7613ded670ed572 100644 (file)
@@ -607,12 +607,13 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                     }
                     // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                     // by looking up the projections associated with the def_id.
-                    let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+                    let bounds = self.tcx().explicit_item_bounds(def_id);
 
                     let mut first = true;
                     let mut is_sized = false;
                     p!("impl");
-                    for predicate in bounds.predicates {
+                    for (predicate, _) in bounds {
+                        let predicate = predicate.subst(self.tcx(), substs);
                         // Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
                         // may contain unbound variables. We therefore do this manually.
                         //
index 5cba451ea6e3c7071462b48b41da5d637c73a8f7..1af56972ad083b0e67531f916ef4d39b822a7c07 100644 (file)
@@ -1513,6 +1513,9 @@ impl<'tcx> ExistentialProjection<'tcx> {
     /// then this function would return a `exists T. T: Iterator` existential trait
     /// reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::ExistentialTraitRef<'tcx> {
+        // FIXME(generic_associated_types): substs is the substs of the
+        // associated type, which should be truncated to get the correct substs
+        // for the trait.
         let def_id = tcx.associated_item(self.item_def_id).container.id();
         ty::ExistentialTraitRef { def_id, substs: self.substs }
     }
index b145e1d5fa33310ede6a24cc184bcbc29dd0e9f9..e22dab0151703ee160ea32973927df498adae61e 100644 (file)
@@ -6,6 +6,7 @@
     error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin,
 };
 use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
@@ -585,14 +586,14 @@ fn add_static_impl_trait_suggestion(
                 //
                 // eg. check for `impl Trait + 'static` instead of `impl Trait`.
                 let has_static_predicate = {
-                    let predicates_of = self.infcx.tcx.predicates_of(did);
-                    let bounds = predicates_of.instantiate(self.infcx.tcx, substs);
+                    let bounds = self.infcx.tcx.explicit_item_bounds(did);
 
                     let mut found = false;
-                    for predicate in bounds.predicates {
+                    for (bound, _) in bounds {
                         if let ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_, r)) =
-                            predicate.skip_binders()
+                            bound.skip_binders()
                         {
+                            let r = r.subst(self.infcx.tcx, substs);
                             if let ty::RegionKind::ReStatic = r {
                                 found = true;
                                 break;
index 8d1b826ea3595e5251acc05f5e2e7dbee5a8a5e3..8f93bce6e99237dd344e6a0d572848e9c4df8759 100644 (file)
@@ -194,11 +194,14 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                     // The intent is to treat `impl Trait1 + Trait2` identically to
                     // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
                     // (it either has no visibility, or its visibility is insignificant, like
-                    // visibilities of type aliases) and recurse into predicates instead to go
+                    // visibilities of type aliases) and recurse into bounds instead to go
                     // through the trait list (default type visitor doesn't visit those traits).
                     // All traits in the list are considered the "primary" part of the type
                     // and are visited by shallow visitors.
-                    if self.visit_predicates(tcx.predicates_of(def_id)) {
+                    if self.visit_predicates(ty::GenericPredicates {
+                        parent: None,
+                        predicates: tcx.explicit_item_bounds(def_id),
+                    }) {
                         return true;
                     }
                 }
@@ -1800,6 +1803,14 @@ fn predicates(&mut self) -> &mut Self {
         self
     }
 
+    fn bounds(&mut self) -> &mut Self {
+        self.visit_predicates(ty::GenericPredicates {
+            parent: None,
+            predicates: self.tcx.explicit_item_bounds(self.item_def_id),
+        });
+        self
+    }
+
     fn ty(&mut self) -> &mut Self {
         self.visit(self.tcx.type_of(self.item_def_id));
         self
@@ -1975,7 +1986,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::OpaqueTy(..) => {
                 // `ty()` for opaque types is the underlying type,
                 // it's not a part of interface, so we skip it.
-                self.check(item.hir_id, item_visibility).generics().predicates();
+                self.check(item.hir_id, item_visibility).generics().bounds();
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
                 self.check(item.hir_id, item_visibility).generics().predicates();
@@ -1987,6 +1998,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                         trait_item_ref.defaultness,
                         item_visibility,
                     );
+
+                    if let AssocItemKind::Type = trait_item_ref.kind {
+                        self.check(trait_item_ref.id.hir_id, item_visibility).bounds();
+                    }
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
index 618f3e045e7125c8f448b54a03540523dbb80601..610c6fd7e35f8450cffb64ff0744638244797ada 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{self, InferCtxt, InferOk};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config::nightly_options;
 use rustc_span::Span;
@@ -428,14 +428,15 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
 
         // If there are required region bounds, we can use them.
         if opaque_defn.has_required_region_bounds {
-            let predicates_of = tcx.predicates_of(def_id);
-            debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
-            let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
+            let bounds = tcx.explicit_item_bounds(def_id);
+            debug!("constrain_opaque_type: predicates: {:#?}", bounds);
+            let bounds: Vec<_> =
+                bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect();
             debug!("constrain_opaque_type: bounds={:#?}", bounds);
             let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
 
             let required_region_bounds =
-                required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter());
+                required_region_bounds(tcx, opaque_type, bounds.into_iter());
             debug_assert!(!required_region_bounds.is_empty());
 
             for required_region in required_region_bounds {
@@ -1112,9 +1113,10 @@ fn fold_opaque_ty(
         let ty_var = infcx
             .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
 
-        let predicates_of = tcx.predicates_of(def_id);
-        debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
-        let bounds = predicates_of.instantiate(tcx, substs);
+        let item_bounds = tcx.explicit_item_bounds(def_id);
+        debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
+        let bounds: Vec<_> =
+            item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
 
         let param_env = tcx.param_env(def_id);
         let InferOk { value: bounds, obligations } =
@@ -1123,8 +1125,7 @@ fn fold_opaque_ty(
 
         debug!("instantiate_opaque_types: bounds={:?}", bounds);
 
-        let required_region_bounds =
-            required_region_bounds(tcx, ty, bounds.predicates.iter().cloned());
+        let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied());
         debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
 
         // Make sure that we are in fact defining the *entire* type
@@ -1153,7 +1154,7 @@ fn fold_opaque_ty(
         );
         debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
 
-        for predicate in &bounds.predicates {
+        for predicate in &bounds {
             if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() {
                 if projection.ty.references_error() {
                     // No point on adding these obligations since there's a type error involved.
@@ -1162,14 +1163,14 @@ fn fold_opaque_ty(
             }
         }
 
-        self.obligations.reserve(bounds.predicates.len());
-        for predicate in bounds.predicates {
+        self.obligations.reserve(bounds.len());
+        for predicate in bounds {
             // Change the predicate to refer to the type variable,
             // which will be the concrete type instead of the opaque type.
             // This also instantiates nested instances of `impl Trait`.
             let predicate = self.instantiate_opaque_types_in_map(&predicate);
 
-            let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType);
+            let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation);
 
             // Require that the predicate holds for the concrete type.
             debug!("instantiate_opaque_types: predicate={:?}", predicate);
index 8586a550230f9ae03cbe03929fd5e1887d6f989f..27751eb554d3c4dddf42dd74f526e8f9ad2ef9e6 100644 (file)
@@ -376,7 +376,7 @@ fn progress_changed_obligations(
                 | ty::PredicateAtom::Subtype(_)
                 | ty::PredicateAtom::ConstEvaluatable(..)
                 | ty::PredicateAtom::ConstEquate(..) => {
-                    let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder);
+                    let pred = infcx.replace_bound_vars_with_placeholders(binder);
                     ProcessResult::Changed(mk_pending(vec![
                         obligation.with(pred.to_predicate(self.selcx.tcx())),
                     ]))
@@ -449,6 +449,7 @@ fn progress_changed_obligations(
                         self.selcx.infcx(),
                         obligation.param_env,
                         obligation.cause.body_id,
+                        obligation.recursion_depth + 1,
                         arg,
                         obligation.cause.span,
                     ) {
@@ -672,7 +673,7 @@ fn process_projection_obligation(
             Ok(Ok(None)) => {
                 *stalled_on = trait_ref_infer_vars(
                     self.selcx,
-                    project_obligation.predicate.to_poly_trait_ref(self.selcx.tcx()),
+                    project_obligation.predicate.to_poly_trait_ref(tcx),
                 );
                 ProcessResult::Unchanged
             }
index 8fc14cb29971d1c1c698bc91bcd94e8c5fcb03f4..0e43f1655ddb2f0c23a1d532344f3254f1230174 100644 (file)
@@ -160,6 +160,10 @@ fn object_safety_violations_for_trait(
     if !spans.is_empty() {
         violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
     }
+    let spans = bounds_reference_self(tcx, trait_def_id);
+    if !spans.is_empty() {
+        violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
+    }
 
     violations.extend(
         tcx.associated_items(trait_def_id)
@@ -239,51 +243,70 @@ fn predicates_reference_self(
     } else {
         tcx.predicates_of(trait_def_id)
     };
-    let self_ty = tcx.types.self_param;
-    let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
     predicates
         .predicates
         .iter()
-        .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
-        .filter_map(|(predicate, &sp)| {
-            match predicate.skip_binders() {
-                ty::PredicateAtom::Trait(ref data, _) => {
-                    // In the case of a trait predicate, we can skip the "self" type.
-                    if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
-                }
-                ty::PredicateAtom::Projection(ref data) => {
-                    // And similarly for projections. This should be redundant with
-                    // the previous check because any projection should have a
-                    // matching `Trait` predicate with the same inputs, but we do
-                    // the check to be safe.
-                    //
-                    // Note that we *do* allow projection *outputs* to contain
-                    // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
-                    // we just require the user to specify *both* outputs
-                    // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
-                    //
-                    // This is ALT2 in issue #56288, see that for discussion of the
-                    // possible alternatives.
-                    if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) {
-                        Some(sp)
-                    } else {
-                        None
-                    }
-                }
-                ty::PredicateAtom::WellFormed(..)
-                | ty::PredicateAtom::ObjectSafe(..)
-                | ty::PredicateAtom::TypeOutlives(..)
-                | ty::PredicateAtom::RegionOutlives(..)
-                | ty::PredicateAtom::ClosureKind(..)
-                | ty::PredicateAtom::Subtype(..)
-                | ty::PredicateAtom::ConstEvaluatable(..)
-                | ty::PredicateAtom::ConstEquate(..)
-                | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
-            }
-        })
+        .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp))
+        .filter_map(|predicate| predicate_references_self(tcx, predicate))
+        .collect()
+}
+
+fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
+    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
+    tcx.associated_items(trait_def_id)
+        .in_definition_order()
+        .filter(|item| item.kind == ty::AssocKind::Type)
+        .flat_map(|item| tcx.explicit_item_bounds(item.def_id))
+        .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp))
+        .filter_map(|predicate| predicate_references_self(tcx, predicate))
         .collect()
 }
 
+fn predicate_references_self(
+    tcx: TyCtxt<'tcx>,
+    (predicate, sp): (ty::Predicate<'tcx>, Span),
+) -> Option<Span> {
+    let self_ty = tcx.types.self_param;
+    let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
+    match predicate.skip_binders() {
+        ty::PredicateAtom::Trait(ref data, _) => {
+            // In the case of a trait predicate, we can skip the "self" type.
+            if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+        }
+        ty::PredicateAtom::Projection(ref data) => {
+            // And similarly for projections. This should be redundant with
+            // the previous check because any projection should have a
+            // matching `Trait` predicate with the same inputs, but we do
+            // the check to be safe.
+            //
+            // It's also won't be redundant if we allow type-generic associated
+            // types for trait objects.
+            //
+            // Note that we *do* allow projection *outputs* to contain
+            // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
+            // we just require the user to specify *both* outputs
+            // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
+            //
+            // This is ALT2 in issue #56288, see that for discussion of the
+            // possible alternatives.
+            if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) {
+                Some(sp)
+            } else {
+                None
+            }
+        }
+        ty::PredicateAtom::WellFormed(..)
+        | ty::PredicateAtom::ObjectSafe(..)
+        | ty::PredicateAtom::TypeOutlives(..)
+        | ty::PredicateAtom::RegionOutlives(..)
+        | ty::PredicateAtom::ClosureKind(..)
+        | ty::PredicateAtom::Subtype(..)
+        | ty::PredicateAtom::ConstEvaluatable(..)
+        | ty::PredicateAtom::ConstEquate(..)
+        | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
+    }
+}
+
 fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
     generics_require_sized_self(tcx, trait_def_id)
 }
index ef8f7b69b5d6067a27e04bbd01ca468be47b4e95..de42aa0e6b764ca69ae2930879729920ebc99562 100644 (file)
@@ -1,6 +1,5 @@
 //! Code for projecting associated types out of trait references.
 
-use super::elaborate_predicates;
 use super::specialization_graph;
 use super::translate_substs;
 use super::util;
@@ -29,7 +28,6 @@
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
 
 pub use rustc_middle::traits::Reveal;
 
@@ -53,13 +51,16 @@ pub enum ProjectionTyError<'tcx> {
 
 #[derive(PartialEq, Eq, Debug)]
 enum ProjectionTyCandidate<'tcx> {
-    // from a where-clause in the env or object type
+    /// From a where-clause in the env or object type
     ParamEnv(ty::PolyProjectionPredicate<'tcx>),
 
-    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
+    /// From the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
     TraitDef(ty::PolyProjectionPredicate<'tcx>),
 
-    // from a "impl" (or a "pseudo-impl" returned by select)
+    /// Bounds specified on an object type
+    Object(ty::PolyProjectionPredicate<'tcx>),
+
+    /// From a "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
 }
 
@@ -167,7 +168,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
 
     let infcx = selcx.infcx();
     infcx.commit_if_ok(|_snapshot| {
-        let (placeholder_predicate, _) =
+        let placeholder_predicate =
             infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
 
         let placeholder_obligation = obligation.with(placeholder_predicate);
@@ -561,14 +562,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             } else {
                 obligations.extend(ty.obligations);
             }
-
-            obligations.push(get_paranoid_cache_value_obligation(
-                infcx,
-                param_env,
-                projection_ty,
-                cause,
-                depth,
-            ));
             return Ok(Some(ty.value));
         }
         Err(ProjectionCacheEntry::Error) => {
@@ -703,45 +696,6 @@ fn prune_cache_value_obligations<'a, 'tcx>(
     NormalizedTy { value: result.value, obligations }
 }
 
-/// Whenever we give back a cache result for a projection like `<T as
-/// Trait>::Item ==> X`, we *always* include the obligation to prove
-/// that `T: Trait` (we may also include some other obligations). This
-/// may or may not be necessary -- in principle, all the obligations
-/// that must be proven to show that `T: Trait` were also returned
-/// when the cache was first populated. But there are some vague concerns,
-/// and so we take the precautionary measure of including `T: Trait` in
-/// the result:
-///
-/// Concern #1. The current setup is fragile. Perhaps someone could
-/// have failed to prove the concerns from when the cache was
-/// populated, but also not have used a snapshot, in which case the
-/// cache could remain populated even though `T: Trait` has not been
-/// shown. In this case, the "other code" is at fault -- when you
-/// project something, you are supposed to either have a snapshot or
-/// else prove all the resulting obligations -- but it's still easy to
-/// get wrong.
-///
-/// Concern #2. Even within the snapshot, if those original
-/// obligations are not yet proven, then we are able to do projections
-/// that may yet turn out to be wrong. This *may* lead to some sort
-/// of trouble, though we don't have a concrete example of how that
-/// can occur yet. But it seems risky at best.
-fn get_paranoid_cache_value_obligation<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> PredicateObligation<'tcx> {
-    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(infcx.tcx),
-    }
-}
-
 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
 /// hold. In various error cases, we cannot generate a valid
 /// normalized projection. Therefore, we create an inference variable
@@ -848,12 +802,21 @@ fn project_type<'cx, 'tcx>(
 
     assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
 
-    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+    assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates);
+
+    if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates {
+        // Avoid normalization cycle from selection (see
+        // `assemble_candidates_from_object_ty`).
+        // FIXME(lazy_normalization): Lazy normalization should save us from
+        // having to do special case this.
+    } else {
+        assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
+    };
 
     match candidates {
-        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
-            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
-        )),
+        ProjectionTyCandidateSet::Single(candidate) => {
+            Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate)))
+        }
         ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
             selcx
                 .tcx()
@@ -884,6 +847,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>(
         candidate_set,
         ProjectionTyCandidate::ParamEnv,
         obligation.param_env.caller_bounds().iter(),
+        false,
     );
 }
 
@@ -909,10 +873,8 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation_trait_ref.self_ty().kind() {
-        ty::Projection(ref data) => {
-            tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
-        }
-        ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
+        ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs),
+        ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs),
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -929,9 +891,57 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
         candidate_set,
         ProjectionTyCandidate::TraitDef,
         bounds.iter(),
+        true,
     )
 }
 
+/// In the case of a trait object like
+/// `<dyn Iterator<Item = ()> as Iterator>::Item` we can use the existential
+/// predicate in the trait object.
+///
+/// We don't go through the select candidate for these bounds to avoid cycles:
+/// In the above case, `dyn Iterator<Item = ()>: Iterator` would create a
+/// nested obligation of `<dyn Iterator<Item = ()> as Iterator>::Item: Sized`,
+/// this then has to be normalized without having to prove
+/// `dyn Iterator<Item = ()>: Iterator` again.
+fn assemble_candidates_from_object_ty<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &ty::TraitRef<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+) {
+    debug!("assemble_candidates_from_object_ty(..)");
+
+    let tcx = selcx.tcx();
+
+    let self_ty = obligation_trait_ref.self_ty();
+    let object_ty = selcx.infcx().shallow_resolve(self_ty);
+    let data = match object_ty.kind() {
+        ty::Dynamic(data, ..) => data,
+        ty::Infer(ty::TyVar(_)) => {
+            // If the self-type is an inference variable, then it MAY wind up
+            // being an object type, so induce an ambiguity.
+            candidate_set.mark_ambiguous();
+            return;
+        }
+        _ => return,
+    };
+    let env_predicates = data
+        .projection_bounds()
+        .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+        .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
+
+    assemble_candidates_from_predicates(
+        selcx,
+        obligation,
+        obligation_trait_ref,
+        candidate_set,
+        ProjectionTyCandidate::Object,
+        env_predicates,
+        false,
+    );
+}
+
 fn assemble_candidates_from_predicates<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
@@ -939,6 +949,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
     ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
     env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
+    potentially_unnormalized_candidates: bool,
 ) {
     debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
     let infcx = selcx.infcx();
@@ -950,16 +961,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
 
             let is_match = same_def_id
                 && infcx.probe(|_| {
-                    let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
-                    let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-                    infcx
-                        .at(&obligation.cause, obligation.param_env)
-                        .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                        .map(|InferOk { obligations: _, value: () }| {
-                            // FIXME(#32730) -- do we need to take obligations
-                            // into account in any way? At the moment, no.
-                        })
-                        .is_ok()
+                    selcx.match_projection_projections(
+                        obligation,
+                        obligation_trait_ref,
+                        &data,
+                        potentially_unnormalized_candidates,
+                    )
                 });
 
             debug!(
@@ -970,6 +977,15 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
 
             if is_match {
                 candidate_set.push_candidate(ctor(data));
+
+                if potentially_unnormalized_candidates
+                    && !obligation.predicate.has_infer_types_or_consts()
+                {
+                    // HACK: Pick the first trait def candidate for a fully
+                    // inferred predicate. This is to allow duplicates that
+                    // differ only in normalization.
+                    return;
+                }
             }
         }
     }
@@ -1003,7 +1019,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
             super::ImplSource::Closure(_)
             | super::ImplSource::Generator(_)
             | super::ImplSource::FnPointer(_)
-            | super::ImplSource::Object(_)
             | super::ImplSource::TraitAlias(_) => {
                 debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source);
                 true
@@ -1128,6 +1143,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // in `assemble_candidates_from_param_env`.
                 false
             }
+            super::ImplSource::Object(_) => {
+                // Handled by the `Object` projection candidate. See
+                // `assemble_candidates_from_object_ty` for an explanation of
+                // why we special case object types.
+                false
+            }
             super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => {
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
@@ -1153,19 +1174,22 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
 fn confirm_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate: ProjectionTyCandidate<'tcx>,
 ) -> Progress<'tcx> {
     debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
 
     let mut progress = match candidate {
         ProjectionTyCandidate::ParamEnv(poly_projection)
-        | ProjectionTyCandidate::TraitDef(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection)
+        | ProjectionTyCandidate::Object(poly_projection) => {
+            confirm_param_env_candidate(selcx, obligation, poly_projection, false)
+        }
+
+        ProjectionTyCandidate::TraitDef(poly_projection) => {
+            confirm_param_env_candidate(selcx, obligation, poly_projection, true)
         }
 
         ProjectionTyCandidate::Select(impl_source) => {
-            confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source)
+            confirm_select_candidate(selcx, obligation, impl_source)
         }
     };
     // When checking for cycle during evaluation, we compare predicates with
@@ -1182,7 +1206,6 @@ fn confirm_candidate<'cx, 'tcx>(
 fn confirm_select_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
     impl_source: Selection<'tcx>,
 ) -> Progress<'tcx> {
     match impl_source {
@@ -1193,10 +1216,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
         super::ImplSource::DiscriminantKind(data) => {
             confirm_discriminant_kind_candidate(selcx, obligation, data)
         }
-        super::ImplSource::Object(_) => {
-            confirm_object_candidate(selcx, obligation, obligation_trait_ref)
-        }
-        super::ImplSource::AutoImpl(..)
+        super::ImplSource::Object(_)
+        | super::ImplSource::AutoImpl(..)
         | super::ImplSource::Param(..)
         | super::ImplSource::Builtin(..)
         | super::ImplSource::TraitAlias(..) =>
@@ -1211,72 +1232,6 @@ fn confirm_select_candidate<'cx, 'tcx>(
     }
 }
 
-fn confirm_object_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-) -> Progress<'tcx> {
-    let self_ty = obligation_trait_ref.self_ty();
-    let object_ty = selcx.infcx().shallow_resolve(self_ty);
-    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
-    let data = match object_ty.kind() {
-        ty::Dynamic(data, ..) => data,
-        _ => span_bug!(
-            obligation.cause.span,
-            "confirm_object_candidate called with non-object: {:?}",
-            object_ty
-        ),
-    };
-    let env_predicates = data
-        .projection_bounds()
-        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate(selcx.tcx()));
-    let env_predicate = {
-        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
-
-        // select only those projections that are actually projecting an
-        // item with the correct name
-
-        let env_predicates = env_predicates.filter_map(|o| match o.predicate.skip_binders() {
-            ty::PredicateAtom::Projection(data)
-                if data.projection_ty.item_def_id == obligation.predicate.item_def_id =>
-            {
-                Some(ty::Binder::bind(data))
-            }
-            _ => None,
-        });
-
-        // select those with a relevant trait-ref
-        let mut env_predicates = env_predicates.filter(|data| {
-            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
-            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-            selcx.infcx().probe(|_| {
-                selcx
-                    .infcx()
-                    .at(&obligation.cause, obligation.param_env)
-                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                    .is_ok()
-            })
-        });
-
-        // select the first matching one; there really ought to be one or
-        // else the object type is not WF, since an object type should
-        // include all of its projections explicitly
-        match env_predicates.next() {
-            Some(env_predicate) => env_predicate,
-            None => {
-                debug!(
-                    "confirm_object_candidate: no env-predicate \
-                     found in object type `{:?}`; ill-formed",
-                    object_ty
-                );
-                return Progress::error(selcx.tcx());
-            }
-        }
-    };
-
-    confirm_param_env_candidate(selcx, obligation, env_predicate)
-}
-
 fn confirm_generator_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
@@ -1325,7 +1280,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         }
     });
 
-    confirm_param_env_candidate(selcx, obligation, predicate)
+    confirm_param_env_candidate(selcx, obligation, predicate, false)
         .with_addl_obligations(impl_source.nested)
         .with_addl_obligations(obligations)
 }
@@ -1347,7 +1302,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
         ty: self_ty.discriminant_ty(tcx),
     };
 
-    confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate))
+    confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false)
 }
 
 fn confirm_fn_pointer_candidate<'cx, 'tcx>(
@@ -1422,13 +1377,14 @@ fn confirm_callable_candidate<'cx, 'tcx>(
         ty: ret_type,
     });
 
-    confirm_param_env_candidate(selcx, obligation, predicate)
+    confirm_param_env_candidate(selcx, obligation, predicate, false)
 }
 
 fn confirm_param_env_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
+    potentially_unnormalized_candidate: bool,
 ) -> Progress<'tcx> {
     let infcx = selcx.infcx();
     let cause = &obligation.cause;
@@ -1442,8 +1398,28 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
 
     let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
     let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
+    let mut nested_obligations = Vec::new();
+    let cache_trait_ref = if potentially_unnormalized_candidate {
+        ensure_sufficient_stack(|| {
+            normalize_with_depth_to(
+                selcx,
+                obligation.param_env,
+                obligation.cause.clone(),
+                obligation.recursion_depth + 1,
+                &cache_trait_ref,
+                &mut nested_obligations,
+            )
+        })
+    } else {
+        cache_trait_ref
+    };
+
     match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
-        Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
+        Ok(InferOk { value: _, obligations }) => {
+            nested_obligations.extend(obligations);
+            assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
+            Progress { ty: cache_entry.ty, obligations: nested_obligations }
+        }
         Err(e) => {
             let msg = format!(
                 "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
@@ -1463,7 +1439,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
 
-    let ImplSourceUserDefinedData { impl_def_id, substs, nested } = impl_impl_source;
+    let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
     let assoc_item_id = obligation.predicate.item_def_id;
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
@@ -1496,15 +1472,48 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let ty = tcx.type_of(assoc_ty.item.def_id);
     if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
         let err = tcx.ty_error_with_message(
-            DUMMY_SP,
+            obligation.cause.span,
             "impl item and trait item have different parameter counts",
         );
         Progress { ty: err, obligations: nested }
     } else {
+        assoc_ty_own_obligations(selcx, obligation, &mut nested);
         Progress { ty: ty.subst(tcx, substs), obligations: nested }
     }
 }
 
+// Get obligations corresponding to the predicates from the where-clause of the
+// associated type itself.
+// Note: `feature(generic_associated_types)` is required to write such
+// predicates, even for non-generic associcated types.
+fn assoc_ty_own_obligations<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    nested: &mut Vec<PredicateObligation<'tcx>>,
+) {
+    let tcx = selcx.tcx();
+    for predicate in tcx
+        .predicates_of(obligation.predicate.item_def_id)
+        .instantiate_own(tcx, obligation.predicate.substs)
+        .predicates
+    {
+        let normalized = normalize_with_depth_to(
+            selcx,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &predicate,
+            nested,
+        );
+        nested.push(Obligation::with_depth(
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            obligation.param_env,
+            normalized,
+        ));
+    }
+}
+
 /// Locate the definition of an associated type in the specialization hierarchy,
 /// starting from the given impl.
 ///
index 9cb5c232646f854e73457951643373a0eec25077..038ba431c47d3be42145c1b674418810dd519b69 100644 (file)
@@ -165,7 +165,7 @@ fn candidate_from_obligation_no_cache<'o>(
 
         debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
 
-        let needs_infer = stack.obligation.predicate.needs_infer();
+        let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
 
         // If there are STILL multiple candidates, we can further
         // reduce the list by dropping duplicates -- including
@@ -327,8 +327,8 @@ fn assemble_candidates_from_projected_tys(
             .infcx
             .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
 
-        if result {
-            candidates.vec.push(ProjectionCandidate);
+        for predicate_index in result {
+            candidates.vec.push(ProjectionCandidate(predicate_index));
         }
     }
 
index 88b656ce6808273c8e37b0d8decf56f4e533ceef..96f0bedf6f1a733a8d4a41b7b9be5108751c7005 100644 (file)
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::InferOk;
+use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness};
 use rustc_span::def_id::DefId;
 
-use crate::traits::project::{self, normalize_with_depth};
+use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
 use crate::traits::select::TraitObligationExt;
 use crate::traits::util;
 use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
@@ -68,9 +69,9 @@ pub(super) fn confirm_candidate(
                 Ok(ImplSource::AutoImpl(data))
             }
 
-            ProjectionCandidate => {
-                self.confirm_projection_candidate(obligation);
-                Ok(ImplSource::Param(Vec::new()))
+            ProjectionCandidate(idx) => {
+                let obligations = self.confirm_projection_candidate(obligation, idx);
+                Ok(ImplSource::Param(obligations))
             }
 
             ClosureCandidate => {
@@ -116,10 +117,72 @@ pub(super) fn confirm_candidate(
         }
     }
 
-    fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
+    fn confirm_projection_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        idx: usize,
+    ) -> Vec<PredicateObligation<'tcx>> {
         self.infcx.commit_unconditionally(|_| {
-            let result = self.match_projection_obligation_against_definition_bounds(obligation);
-            assert!(result);
+            let tcx = self.tcx();
+
+            let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
+            let placeholder_trait_predicate =
+                self.infcx().replace_bound_vars_with_placeholders(&trait_predicate);
+            let placeholder_self_ty = placeholder_trait_predicate.self_ty();
+            let (def_id, substs) = match *placeholder_self_ty.kind() {
+                ty::Projection(proj) => (proj.item_def_id, proj.substs),
+                ty::Opaque(def_id, substs) => (def_id, substs),
+                _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
+            };
+
+            let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs);
+            let candidate = candidate_predicate
+                .to_opt_poly_trait_ref()
+                .expect("projection candidate is not a trait predicate");
+            let mut obligations = Vec::new();
+            let candidate = normalize_with_depth_to(
+                self,
+                obligation.param_env,
+                obligation.cause.clone(),
+                obligation.recursion_depth + 1,
+                &candidate,
+                &mut obligations,
+            );
+
+            obligations.extend(
+                self.infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate)
+                    .map(|InferOk { obligations, .. }| obligations)
+                    .unwrap_or_else(|_| {
+                        bug!(
+                            "Projection bound `{:?}` was applicable to `{:?}` but now is not",
+                            candidate,
+                            obligation
+                        );
+                    }),
+            );
+
+            if let ty::Projection(..) = placeholder_self_ty.kind() {
+                for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates {
+                    let normalized = normalize_with_depth_to(
+                        self,
+                        obligation.param_env,
+                        obligation.cause.clone(),
+                        obligation.recursion_depth + 1,
+                        &predicate,
+                        &mut obligations,
+                    );
+                    obligations.push(Obligation::with_depth(
+                        obligation.cause.clone(),
+                        obligation.recursion_depth + 1,
+                        obligation.param_env,
+                        normalized,
+                    ));
+                }
+            }
+
+            obligations
         })
     }
 
@@ -229,7 +292,7 @@ fn vtable_auto_impl(
             let trait_obligations: Vec<PredicateObligation<'_>> =
                 self.infcx.commit_unconditionally(|_| {
                     let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
-                    let (trait_ref, _) =
+                    let trait_ref =
                         self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref);
                     let cause = obligation.derived_cause(ImplDerivedObligation);
                     self.impl_or_trait_obligations(
@@ -307,55 +370,70 @@ fn vtable_impl(
         // relying on projections in the impl-trait-ref.
         //
         // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
-        impl_obligations.append(&mut substs.obligations);
+        substs.obligations.append(&mut impl_obligations);
 
-        ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
+        ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations }
     }
 
     fn confirm_object_candidate(
         &mut self,
         obligation: &TraitObligation<'tcx>,
     ) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> {
+        let tcx = self.tcx();
         debug!("confirm_object_candidate({:?})", obligation);
 
-        // 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.kind() {
-            ty::Dynamic(data, ..) => data
-                .principal()
-                .unwrap_or_else(|| {
-                    span_bug!(obligation.cause.span, "object candidate with no principal")
-                })
-                .with_self_ty(self.tcx(), self_ty),
+        let trait_predicate =
+            self.infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
+        let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
+        let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
+        let data = match self_ty.kind() {
+            ty::Dynamic(data, ..) => {
+                self.infcx
+                    .replace_bound_vars_with_fresh_vars(
+                        obligation.cause.span,
+                        HigherRankedType,
+                        data,
+                    )
+                    .0
+            }
             _ => span_bug!(obligation.cause.span, "object candidate with non-object"),
         };
 
+        let object_trait_ref = data
+            .principal()
+            .unwrap_or_else(|| {
+                span_bug!(obligation.cause.span, "object candidate with no principal")
+            })
+            .with_self_ty(self.tcx(), self_ty);
+
         let mut upcast_trait_ref = None;
         let mut nested = vec![];
         let vtable_base;
 
         {
-            let tcx = self.tcx();
-
             // We want to find the first supertrait in the list of
             // supertraits that we can unify with, and do that
             // unification. We know that there is exactly one in the list
             // where we can unify, because otherwise select would have
             // reported an ambiguity. (When we do find a match, also
             // record it for later.)
-            let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| {
-                match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) {
-                    Ok(obligations) => {
-                        upcast_trait_ref = Some(t);
-                        nested.extend(obligations);
-                        false
+            let nonmatching = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref))
+                .take_while(|&t| {
+                    match self.infcx.commit_if_ok(|_| {
+                        self.infcx
+                            .at(&obligation.cause, obligation.param_env)
+                            .sup(obligation_trait_ref, t)
+                            .map(|InferOk { obligations, .. }| obligations)
+                            .map_err(|_| ())
+                    }) {
+                        Ok(obligations) => {
+                            upcast_trait_ref = Some(t);
+                            nested.extend(obligations);
+                            false
+                        }
+                        Err(_) => true,
                     }
-                    Err(_) => true,
-                }
-            });
+                });
 
             // Additionally, for each of the non-matching predicates that
             // we pass over, we sum up the set of number of vtable
@@ -364,7 +442,73 @@ fn confirm_object_candidate(
             vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
         }
 
-        ImplSourceObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested }
+        let upcast_trait_ref = upcast_trait_ref.unwrap();
+
+        // Check supertraits hold. This is so that their associated type bounds
+        // will be checked in the code below.
+        for super_trait in tcx
+            .super_predicates_of(trait_predicate.def_id())
+            .instantiate(tcx, trait_predicate.trait_ref.substs)
+            .predicates
+            .into_iter()
+        {
+            if let ty::PredicateAtom::Trait(..) = super_trait.skip_binders() {
+                let normalized_super_trait = normalize_with_depth_to(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    &super_trait,
+                    &mut nested,
+                );
+                nested.push(Obligation::new(
+                    obligation.cause.clone(),
+                    obligation.param_env.clone(),
+                    normalized_super_trait,
+                ));
+            }
+        }
+
+        let assoc_types: Vec<_> = tcx
+            .associated_items(trait_predicate.def_id())
+            .in_definition_order()
+            .filter_map(
+                |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
+            )
+            .collect();
+
+        for assoc_type in assoc_types {
+            if !tcx.generics_of(assoc_type).params.is_empty() {
+                // FIXME(generic_associated_types) generate placeholders to
+                // extend the trait substs.
+                tcx.sess.span_fatal(
+                    obligation.cause.span,
+                    "generic associated types in trait objects are not supported yet",
+                );
+            }
+            // This maybe belongs in wf, but that can't (doesn't) handle
+            // higher-ranked things.
+            // Prevent, e.g., `dyn Iterator<Item = str>`.
+            for bound in self.tcx().item_bounds(assoc_type) {
+                let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs);
+                let normalized_bound = normalize_with_depth_to(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    &subst_bound,
+                    &mut nested,
+                );
+                nested.push(Obligation::new(
+                    obligation.cause.clone(),
+                    obligation.param_env.clone(),
+                    normalized_bound,
+                ));
+            }
+        }
+
+        debug!("confirm_object_candidate: nested: {:?}", nested);
+        ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }
     }
 
     fn confirm_fn_pointer_candidate(
@@ -386,8 +530,8 @@ fn confirm_fn_pointer_candidate(
         )
         .map_bound(|(trait_ref, _)| trait_ref);
 
-        let Normalized { value: trait_ref, obligations } = ensure_sufficient_stack(|| {
-            project::normalize_with_depth(
+        let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
+            normalize_with_depth(
                 self,
                 obligation.param_env,
                 obligation.cause.clone(),
@@ -396,12 +540,12 @@ fn confirm_fn_pointer_candidate(
             )
         });
 
-        self.confirm_poly_trait_refs(
+        obligations.extend(self.confirm_poly_trait_refs(
             obligation.cause.clone(),
             obligation.param_env,
             obligation.predicate.to_poly_trait_ref(),
             trait_ref,
-        )?;
+        )?);
         Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations })
     }
 
@@ -413,7 +557,7 @@ fn confirm_trait_alias_candidate(
         debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id);
 
         self.infcx.commit_unconditionally(|_| {
-            let (predicate, _) =
+            let predicate =
                 self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
             let trait_ref = predicate.trait_ref;
             let trait_def_id = trait_ref.def_id;
index 114dc79c44f50e58134f45cc14a8ba6ede5d5f1f..a142ba58a6904a8d32e5b631a1cd15283e645d5d 100644 (file)
@@ -9,6 +9,7 @@
 use super::const_evaluatable;
 use super::project;
 use super::project::normalize_with_depth_to;
+use super::project::ProjectionTyObligation;
 use super::util;
 use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
 use super::wf;
@@ -36,9 +37,8 @@
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
-use rustc_middle::ty::{
-    self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
+use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, WithConstness};
 use rustc_span::symbol::sym;
 
 use std::cell::{Cell, RefCell};
@@ -343,7 +343,10 @@ pub fn select(
                 Err(SelectionError::Overflow)
             }
             Err(e) => Err(e),
-            Ok(candidate) => Ok(Some(candidate)),
+            Ok(candidate) => {
+                debug!("select: candidate = {:?}", candidate);
+                Ok(Some(candidate))
+            }
         }
     }
 
@@ -413,9 +416,10 @@ fn evaluate_predicates_recursively<'o, I>(
         predicates: I,
     ) -> Result<EvaluationResult, OverflowError>
     where
-        I: IntoIterator<Item = PredicateObligation<'tcx>>,
+        I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
     {
         let mut result = EvaluatedToOk;
+        debug!("evaluate_predicates_recursively({:?})", predicates);
         for obligation in predicates {
             let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
             debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
@@ -436,9 +440,9 @@ fn evaluate_predicate_recursively<'o>(
         obligation: PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         debug!(
-            "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
-            previous_stack.head(),
-            obligation
+            "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})",
+            obligation,
+            previous_stack.head()
         );
 
         // `previous_stack` stores a `TraitObligation`, while `obligation` is
@@ -479,15 +483,13 @@ fn evaluate_predicate_recursively<'o>(
                     self.infcx,
                     obligation.param_env,
                     obligation.cause.body_id,
+                    obligation.recursion_depth + 1,
                     arg,
                     obligation.cause.span,
                 ) {
                     Some(mut obligations) => {
                         self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
-                        self.evaluate_predicates_recursively(
-                            previous_stack,
-                            obligations.into_iter(),
-                        )
+                        self.evaluate_predicates_recursively(previous_stack, obligations)
                     }
                     None => Ok(EvaluatedToAmbig),
                 },
@@ -511,10 +513,8 @@ fn evaluate_predicate_recursively<'o>(
                     match project::poly_project_and_unify_type(self, &project_obligation) {
                         Ok(Ok(Some(mut subobligations))) => {
                             self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
-                            let result = self.evaluate_predicates_recursively(
-                                previous_stack,
-                                subobligations.into_iter(),
-                            );
+                            let result = self
+                                .evaluate_predicates_recursively(previous_stack, subobligations);
                             if let Some(key) =
                                 ProjectionCacheKey::from_poly_projection_predicate(self, data)
                             {
@@ -879,10 +879,13 @@ fn evaluate_candidate<'o>(
         let result = self.evaluation_probe(|this| {
             let candidate = (*candidate).clone();
             match this.confirm_candidate(stack.obligation, candidate) {
-                Ok(selection) => this.evaluate_predicates_recursively(
-                    stack.list(),
-                    selection.nested_obligations().into_iter(),
-                ),
+                Ok(selection) => {
+                    debug!("evaluate_candidate: selection = {:?}", selection);
+                    this.evaluate_predicates_recursively(
+                        stack.list(),
+                        selection.nested_obligations().into_iter(),
+                    )
+                }
                 Err(..) => Ok(EvaluatedToErr),
             }
         })?;
@@ -943,10 +946,9 @@ fn insert_evaluation_cache(
     /// to have a *lower* recursion_depth than the obligation used to create it.
     /// Projection sub-obligations may be returned from the projection cache,
     /// which results in obligations with an 'old' `recursion_depth`.
-    /// Additionally, methods like `wf::obligations` and
-    /// `InferCtxt.subtype_predicate` produce subobligations without
-    /// taking in a 'parent' depth, causing the generated subobligations
-    /// to have a `recursion_depth` of `0`.
+    /// Additionally, methods like `InferCtxt.subtype_predicate` produce
+    /// subobligations without taking in a 'parent' depth, causing the
+    /// generated subobligations to have a `recursion_depth` of `0`.
     ///
     /// To ensure that obligation_depth never decreasees, we force all subobligations
     /// to have at least the depth of the original obligation.
@@ -1156,12 +1158,18 @@ fn insert_candidate_cache(
         self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
     }
 
+    /// Matches a predicate against the bounds of its self type.
+    ///
+    /// Given an obligation like `<T as Foo>::Bar: Baz` where the self type is
+    /// a projection, look at the bounds of `T::Bar`, see if we can find a
+    /// `Baz` bound. We return indexes into the list returned by
+    /// `tcx.item_bounds` for any applicable bounds.
     fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-    ) -> bool {
+    ) -> smallvec::SmallVec<[usize; 2]> {
         let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
-        let (placeholder_trait_predicate, _) =
+        let placeholder_trait_predicate =
             self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate);
         debug!(
             "match_projection_obligation_against_definition_bounds: \
@@ -1170,11 +1178,9 @@ fn match_projection_obligation_against_definition_bounds(
         );
 
         let tcx = self.infcx.tcx;
-        let predicates = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Projection(ref data) => {
-                tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
-            }
-            ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
+        let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
+            ty::Projection(ref data) => (data.item_def_id, data.substs),
+            ty::Opaque(def_id, substs) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -1184,48 +1190,86 @@ fn match_projection_obligation_against_definition_bounds(
                 );
             }
         };
+        let bounds = tcx.item_bounds(def_id).subst(tcx, substs);
+
+        // The bounds returned by `item_bounds` may contain duplicates after
+        // normalization, so try to deduplicate when possible to avoid
+        // unnecessary ambiguity.
+        let mut distinct_normalized_bounds = FxHashSet::default();
 
-        let matching_bound = predicates.iter().find_map(|bound| {
-            if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() {
-                let bound = ty::Binder::bind(pred.trait_ref);
-                if self.infcx.probe(|_| {
-                    self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref)
-                }) {
-                    return Some(bound);
+        let matching_bounds = bounds
+            .iter()
+            .enumerate()
+            .filter_map(|(idx, bound)| {
+                if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() {
+                    let bound = ty::Binder::bind(pred.trait_ref);
+                    if self.infcx.probe(|_| {
+                        match self.match_projection(
+                            obligation,
+                            bound,
+                            placeholder_trait_predicate.trait_ref,
+                        ) {
+                            Ok(None) => true,
+                            Ok(Some(normalized_trait))
+                                if distinct_normalized_bounds.insert(normalized_trait) =>
+                            {
+                                true
+                            }
+                            _ => false,
+                        }
+                    }) {
+                        return Some(idx);
+                    }
                 }
-            }
-            None
-        });
+                None
+            })
+            .collect();
 
         debug!(
             "match_projection_obligation_against_definition_bounds: \
-             matching_bound={:?}",
-            matching_bound
+             matching_bounds={:?}",
+            matching_bounds
         );
-        match matching_bound {
-            None => false,
-            Some(bound) => {
-                // Repeat the successful match, if any, this time outside of a probe.
-                let result =
-                    self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref);
-
-                assert!(result);
-                true
-            }
-        }
+        matching_bounds
     }
 
+    /// Equates the trait in `obligation` with trait bound. If the two traits
+    /// can be equated and the normalized trait bound doesn't contain inference
+    /// variables or placeholders, the normalized bound is returned.
     fn match_projection(
         &mut self,
         obligation: &TraitObligation<'tcx>,
         trait_bound: ty::PolyTraitRef<'tcx>,
         placeholder_trait_ref: ty::TraitRef<'tcx>,
-    ) -> bool {
+    ) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
         debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
+        if placeholder_trait_ref.def_id != trait_bound.def_id() {
+            // Avoid unnecessary normalization
+            return Err(());
+        }
+
+        let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| {
+            project::normalize_with_depth(
+                self,
+                obligation.param_env,
+                obligation.cause.clone(),
+                obligation.recursion_depth + 1,
+                &trait_bound,
+            )
+        });
         self.infcx
             .at(&obligation.cause, obligation.param_env)
             .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
-            .is_ok()
+            .map(|InferOk { obligations: _, value: () }| {
+                // This method is called within a probe, so we can't have
+                // inference variables and placeholders escape.
+                if !trait_bound.needs_infer() && !trait_bound.has_placeholders() {
+                    Some(trait_bound)
+                } else {
+                    None
+                }
+            })
+            .map_err(|_| ())
     }
 
     fn evaluate_where_clause<'o>(
@@ -1235,14 +1279,50 @@ fn evaluate_where_clause<'o>(
     ) -> Result<EvaluationResult, OverflowError> {
         self.evaluation_probe(|this| {
             match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
-                Ok(obligations) => {
-                    this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
-                }
+                Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),
                 Err(()) => Ok(EvaluatedToErr),
             }
         })
     }
 
+    pub(super) fn match_projection_projections(
+        &mut self,
+        obligation: &ProjectionTyObligation<'tcx>,
+        obligation_trait_ref: &ty::TraitRef<'tcx>,
+        data: &PolyProjectionPredicate<'tcx>,
+        potentially_unnormalized_candidates: bool,
+    ) -> bool {
+        let mut nested_obligations = Vec::new();
+        let projection_ty = if potentially_unnormalized_candidates {
+            ensure_sufficient_stack(|| {
+                project::normalize_with_depth_to(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.recursion_depth + 1,
+                    &data.map_bound_ref(|data| data.projection_ty),
+                    &mut nested_obligations,
+                )
+            })
+        } else {
+            data.map_bound_ref(|data| data.projection_ty)
+        };
+
+        // FIXME(generic_associated_types): Compare the whole projections
+        let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx()));
+        let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+        self.infcx
+            .at(&obligation.cause, obligation.param_env)
+            .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+            .map_or(false, |InferOk { obligations, value: () }| {
+                self.evaluate_predicates_recursively(
+                    TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+                    nested_obligations.into_iter().chain(obligations),
+                )
+                .map_or(false, |res| res.may_apply())
+            })
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // WINNOW
     //
@@ -1277,18 +1357,27 @@ fn candidate_should_be_dropped_in_favor_of(
         //
         // This is a fix for #53123 and prevents winnowing from accidentally extending the
         // lifetime of a variable.
-        match other.candidate {
+        match (&other.candidate, &victim.candidate) {
+            (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => {
+                bug!(
+                    "default implementations shouldn't be recorded \
+                    when there are other valid candidates"
+                );
+            }
+
             // (*)
-            BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => true,
-            ParamCandidate(ref cand) => match victim.candidate {
-                AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates"
-                    );
-                }
-                // (*)
-                BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false,
+            (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true,
+            (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false,
+
+            (ParamCandidate(..), ParamCandidate(..)) => false,
+
+            // 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.
+            // Arbitrarily give param candidates priority
+            // over projection and object candidates.
+            (
+                ParamCandidate(ref cand),
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
@@ -1296,28 +1385,45 @@ fn candidate_should_be_dropped_in_favor_of(
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
                 | 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.
-                    !is_global(cand)
-                }
-                ObjectCandidate | ProjectionCandidate => {
-                    // Arbitrarily give param candidates priority
-                    // over projection and object candidates.
-                    !is_global(cand)
-                }
-                ParamCandidate(..) => false,
-            },
-            ObjectCandidate | ProjectionCandidate => match victim.candidate {
-                AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates"
-                    );
-                }
-                // (*)
-                BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false,
+                | TraitAliasCandidate(..)
+                | ObjectCandidate
+                | ProjectionCandidate(_),
+            ) => !is_global(cand),
+            (ObjectCandidate | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
+                // Prefer these to a global where-clause bound
+                // (see issue #50825).
+                is_global(cand)
+            }
+            (
+                ImplCandidate(_)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { has_nested: true }
+                | TraitAliasCandidate(..),
+                ParamCandidate(ref cand),
+            ) => {
+                // Prefer these to a global where-clause bound
+                // (see issue #50825).
+                is_global(cand) && other.evaluation.must_apply_modulo_regions()
+            }
+
+            (ProjectionCandidate(i), ProjectionCandidate(j)) => {
+                // Arbitrarily pick the first candidate for backwards
+                // compatibility reasons. Don't let this affect inference.
+                i > j && !needs_infer
+            }
+            (ObjectCandidate, ObjectCandidate) => bug!("Duplicate object candidate"),
+            (ObjectCandidate, ProjectionCandidate(_))
+            | (ProjectionCandidate(_), ObjectCandidate) => {
+                bug!("Have both object and projection candidate")
+            }
+
+            // Arbitrarily give projection and object candidates priority.
+            (
+                ObjectCandidate | ProjectionCandidate(_),
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
@@ -1325,98 +1431,100 @@ fn candidate_should_be_dropped_in_favor_of(
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
                 | BuiltinCandidate { .. }
-                | TraitAliasCandidate(..) => true,
-                ObjectCandidate | ProjectionCandidate => {
-                    // Arbitrarily give param candidates priority
-                    // over projection and object candidates.
-                    true
-                }
-                ParamCandidate(ref cand) => is_global(cand),
-            },
-            ImplCandidate(other_def) => {
+                | TraitAliasCandidate(..),
+            ) => true,
+
+            (
+                ImplCandidate(..)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { .. }
+                | TraitAliasCandidate(..),
+                ObjectCandidate | ProjectionCandidate(_),
+            ) => false,
+
+            (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
                 // See if we can toss out `victim` based on specialization.
                 // This requires us to know *for sure* that the `other` impl applies
                 // i.e., `EvaluatedToOk`.
                 if other.evaluation.must_apply_modulo_regions() {
-                    match victim.candidate {
-                        ImplCandidate(victim_def) => {
-                            let tcx = self.tcx();
-                            if tcx.specializes((other_def, victim_def)) {
-                                return true;
-                            }
-                            return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
-                                Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
-                                    // Subtle: If the predicate we are evaluating has inference
-                                    // variables, do *not* allow discarding candidates due to
-                                    // marker trait impls.
-                                    //
-                                    // Without this restriction, we could end up accidentally
-                                    // constrainting inference variables based on an arbitrarily
-                                    // chosen trait impl.
-                                    //
-                                    // Imagine we have the following code:
-                                    //
-                                    // ```rust
-                                    // #[marker] trait MyTrait {}
-                                    // impl MyTrait for u8 {}
-                                    // impl MyTrait for bool {}
-                                    // ```
-                                    //
-                                    // And we are evaluating the predicate `<_#0t as MyTrait>`.
-                                    //
-                                    // During selection, we will end up with one candidate for each
-                                    // impl of `MyTrait`. If we were to discard one impl in favor
-                                    // of the other, we would be left with one candidate, causing
-                                    // us to "successfully" select the predicate, unifying
-                                    // _#0t with (for example) `u8`.
-                                    //
-                                    // However, we have no reason to believe that this unification
-                                    // is correct - we've essentially just picked an arbitrary
-                                    // *possibility* for _#0t, and required that this be the *only*
-                                    // possibility.
-                                    //
-                                    // Eventually, we will either:
-                                    // 1) Unify all inference variables in the predicate through
-                                    // some other means (e.g. type-checking of a function). We will
-                                    // then be in a position to drop marker trait candidates
-                                    // without constraining inference variables (since there are
-                                    // none left to constrin)
-                                    // 2) Be left with some unconstrained inference variables. We
-                                    // will then correctly report an inference error, since the
-                                    // existence of multiple marker trait impls tells us nothing
-                                    // about which one should actually apply.
-                                    !needs_infer
-                                }
-                                Some(_) => true,
-                                None => false,
-                            };
-                        }
-                        ParamCandidate(ref cand) => {
-                            // Prefer the impl to a global where clause candidate.
-                            return is_global(cand);
-                        }
-                        _ => (),
+                    let tcx = self.tcx();
+                    if tcx.specializes((other_def, victim_def)) {
+                        return true;
                     }
-                }
-
-                false
-            }
-            ClosureCandidate
-            | GeneratorCandidate
-            | FnPointerCandidate
-            | BuiltinObjectCandidate
-            | BuiltinUnsizeCandidate
-            | BuiltinCandidate { has_nested: true } => {
-                match victim.candidate {
-                    ParamCandidate(ref cand) => {
-                        // Prefer these to a global where-clause bound
-                        // (see issue #50825).
-                        is_global(cand) && other.evaluation.must_apply_modulo_regions()
-                    }
-                    _ => false,
+                    return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
+                        Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
+                            // Subtle: If the predicate we are evaluating has inference
+                            // variables, do *not* allow discarding candidates due to
+                            // marker trait impls.
+                            //
+                            // Without this restriction, we could end up accidentally
+                            // constrainting inference variables based on an arbitrarily
+                            // chosen trait impl.
+                            //
+                            // Imagine we have the following code:
+                            //
+                            // ```rust
+                            // #[marker] trait MyTrait {}
+                            // impl MyTrait for u8 {}
+                            // impl MyTrait for bool {}
+                            // ```
+                            //
+                            // And we are evaluating the predicate `<_#0t as MyTrait>`.
+                            //
+                            // During selection, we will end up with one candidate for each
+                            // impl of `MyTrait`. If we were to discard one impl in favor
+                            // of the other, we would be left with one candidate, causing
+                            // us to "successfully" select the predicate, unifying
+                            // _#0t with (for example) `u8`.
+                            //
+                            // However, we have no reason to believe that this unification
+                            // is correct - we've essentially just picked an arbitrary
+                            // *possibility* for _#0t, and required that this be the *only*
+                            // possibility.
+                            //
+                            // Eventually, we will either:
+                            // 1) Unify all inference variables in the predicate through
+                            // some other means (e.g. type-checking of a function). We will
+                            // then be in a position to drop marker trait candidates
+                            // without constraining inference variables (since there are
+                            // none left to constrin)
+                            // 2) Be left with some unconstrained inference variables. We
+                            // will then correctly report an inference error, since the
+                            // existence of multiple marker trait impls tells us nothing
+                            // about which one should actually apply.
+                            !needs_infer
+                        }
+                        Some(_) => true,
+                        None => false,
+                    };
+                } else {
+                    false
                 }
             }
-            _ => false,
+
+            // Everything else is ambiguous
+            (
+                ImplCandidate(_)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { has_nested: true }
+                | TraitAliasCandidate(..),
+                ImplCandidate(_)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { has_nested: true }
+                | TraitAliasCandidate(..),
+            ) => false,
         }
     }
 
@@ -1649,7 +1757,7 @@ fn collect_predicates_for_types(
                 let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
 
                 self.infcx.commit_unconditionally(|_| {
-                    let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
+                    let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(&ty);
                     let Normalized { value: normalized_ty, mut obligations } =
                         ensure_sufficient_stack(|| {
                             project::normalize_with_depth(
@@ -1717,7 +1825,7 @@ fn match_impl(
             return Err(());
         }
 
-        let (placeholder_obligation, _) =
+        let placeholder_obligation =
             self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
         let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
 
index 909cd2aa1551ec3bd93f7393a4da20c961334ffb..d66bfd482069dab2a32847a7e8099fedc2f90459 100644 (file)
@@ -20,6 +20,7 @@ pub fn obligations<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body_id: hir::HirId,
+    recursion_depth: usize,
     arg: GenericArg<'tcx>,
     span: Span,
 ) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
@@ -59,7 +60,8 @@ pub fn obligations<'a, 'tcx>(
         GenericArgKind::Lifetime(..) => return Some(Vec::new()),
     };
 
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
+    let mut wf =
+        WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None };
     wf.compute(arg);
     debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
 
@@ -80,7 +82,8 @@ pub fn trait_obligations<'a, 'tcx>(
     span: Span,
     item: Option<&'tcx hir::Item<'tcx>>,
 ) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
+    let mut wf =
+        WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item };
     wf.compute_trait_ref(trait_ref, Elaborate::All);
     wf.normalize()
 }
@@ -92,7 +95,15 @@ pub fn predicate_obligations<'a, 'tcx>(
     predicate: ty::Predicate<'tcx>,
     span: Span,
 ) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
+    let mut wf = WfPredicates {
+        infcx,
+        param_env,
+        body_id,
+        span,
+        out: vec![],
+        recursion_depth: 0,
+        item: None,
+    };
 
     // It's ok to skip the binder here because wf code is prepared for it
     match predicate.skip_binders() {
@@ -142,6 +153,7 @@ struct WfPredicates<'a, 'tcx> {
     body_id: hir::HirId,
     span: Span,
     out: Vec<traits::PredicateObligation<'tcx>>,
+    recursion_depth: usize,
     item: Option<&'tcx hir::Item<'tcx>>,
 }
 
@@ -241,18 +253,27 @@ fn cause(&self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCa
         traits::ObligationCause::new(self.span, self.body_id, code)
     }
 
-    fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
+    fn normalize(mut self) -> Vec<traits::PredicateObligation<'tcx>> {
         let cause = self.cause(traits::MiscObligation);
         let infcx = &mut self.infcx;
         let param_env = self.param_env;
         let mut obligations = Vec::with_capacity(self.out.len());
-        for pred in &self.out {
-            assert!(!pred.has_escaping_bound_vars());
+        for mut obligation in self.out {
+            assert!(!obligation.has_escaping_bound_vars());
             let mut selcx = traits::SelectionContext::new(infcx);
-            let i = obligations.len();
-            let value =
-                traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations);
-            obligations.insert(i, value);
+            // Don't normalize the whole obligation, the param env is either
+            // already normalized, or we're currently normalizing the
+            // param_env. Either way we should only normalize the predicate.
+            let normalized_predicate = traits::project::normalize_with_depth_to(
+                &mut selcx,
+                param_env,
+                cause.clone(),
+                self.recursion_depth,
+                &obligation.predicate,
+                &mut obligations,
+            );
+            obligation.predicate = normalized_predicate;
+            obligations.push(obligation);
         }
         obligations
     }
@@ -265,6 +286,7 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
         debug!("compute_trait_ref obligations {:?}", obligations);
         let cause = self.cause(traits::MiscObligation);
         let param_env = self.param_env;
+        let depth = self.recursion_depth;
 
         let item = self.item;
 
@@ -286,7 +308,7 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
                 &obligation.predicate,
                 tcx.associated_items(trait_ref.def_id).in_definition_order(),
             );
-            traits::Obligation::new(cause, param_env, obligation.predicate)
+            traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
         };
 
         if let Elaborate::All = elaborate {
@@ -315,8 +337,9 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
                             new_cause.make_mut().span = self_ty.span;
                         }
                     }
-                    traits::Obligation::new(
+                    traits::Obligation::with_depth(
                         new_cause,
+                        depth,
                         param_env,
                         ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
                     )
@@ -327,17 +350,51 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
     /// Pushes the obligations required for `trait_ref::Item` to be WF
     /// into `self.out`.
     fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
-        // A projection is well-formed if (a) the trait ref itself is
-        // WF and (b) the trait-ref holds.  (It may also be
-        // normalizable and be WF that way.)
-        let trait_ref = data.trait_ref(self.infcx.tcx);
-        self.compute_trait_ref(&trait_ref, Elaborate::None);
-
-        if !data.has_escaping_bound_vars() {
-            let predicate = trait_ref.without_const().to_predicate(self.infcx.tcx);
-            let cause = self.cause(traits::ProjectionWf(data));
-            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
+        // A projection is well-formed if
+        //
+        // (a) its predicates hold (*)
+        // (b) its substs are wf
+        //
+        // (*) The predicates of an associated type include the predicates of
+        //     the trait that it's contained in. For example, given
+        //
+        // trait A<T>: Clone {
+        //     type X where T: Copy;
+        // }
+        //
+        // The predicates of `<() as A<i32>>::X` are:
+        // [
+        //     `(): Sized`
+        //     `(): Clone`
+        //     `(): A<i32>`
+        //     `i32: Sized`
+        //     `i32: Clone`
+        //     `i32: Copy`
+        // ]
+        let obligations = self.nominal_obligations(data.item_def_id, data.substs);
+        self.out.extend(obligations);
+
+        let tcx = self.tcx();
+        let cause = self.cause(traits::MiscObligation);
+        let param_env = self.param_env;
+        let depth = self.recursion_depth;
+
+        self.out.extend(
+            data.substs
+                .iter()
+                .filter(|arg| {
+                    matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
+                })
+                .filter(|arg| !arg.has_escaping_bound_vars())
+                .map(|arg| {
+                    traits::Obligation::with_depth(
+                        cause.clone(),
+                        depth,
+                        param_env,
+                        ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
+                    )
+                }),
+        );
     }
 
     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
@@ -347,8 +404,9 @@ fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<
                 def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None),
                 substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
             };
-            self.out.push(traits::Obligation::new(
+            self.out.push(traits::Obligation::with_depth(
                 cause,
+                self.recursion_depth,
                 self.param_env,
                 trait_ref.without_const().to_predicate(self.infcx.tcx),
             ));
@@ -359,6 +417,7 @@ fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<
     fn compute(&mut self, arg: GenericArg<'tcx>) {
         let mut walker = arg.walk();
         let param_env = self.param_env;
+        let depth = self.recursion_depth;
         while let Some(arg) = walker.next() {
             let ty = match arg.unpack() {
                 GenericArgKind::Type(ty) => ty,
@@ -378,8 +437,9 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                             let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
                                 .to_predicate(self.tcx());
                             let cause = self.cause(traits::MiscObligation);
-                            self.out.push(traits::Obligation::new(
+                            self.out.push(traits::Obligation::with_depth(
                                 cause,
+                                self.recursion_depth,
                                 self.param_env,
                                 predicate,
                             ));
@@ -394,8 +454,9 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                                     val: ty::ConstKind::Infer(resolved),
                                     ..*constant
                                 });
-                                self.out.push(traits::Obligation::new(
+                                self.out.push(traits::Obligation::with_depth(
                                     cause,
+                                    self.recursion_depth,
                                     self.param_env,
                                     ty::PredicateAtom::WellFormed(resolved_constant.into())
                                         .to_predicate(self.tcx()),
@@ -480,8 +541,9 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                     // WfReference
                     if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
-                        self.out.push(traits::Obligation::new(
+                        self.out.push(traits::Obligation::with_depth(
                             cause,
+                            depth,
                             param_env,
                             ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
                                 .to_predicate(self.tcx()),
@@ -571,8 +633,9 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                         let component_traits = data.auto_traits().chain(data.principal_def_id());
                         let tcx = self.tcx();
                         self.out.extend(component_traits.map(|did| {
-                            traits::Obligation::new(
+                            traits::Obligation::with_depth(
                                 cause.clone(),
+                                depth,
                                 param_env,
                                 ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
                             )
@@ -597,8 +660,9 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                     if let ty::Infer(ty::TyVar(_)) = ty.kind() {
                         // Not yet resolved, but we've made progress.
                         let cause = self.cause(traits::MiscObligation);
-                        self.out.push(traits::Obligation::new(
+                        self.out.push(traits::Obligation::with_depth(
                             cause,
+                            self.recursion_depth,
                             param_env,
                             ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
                         ));
@@ -635,7 +699,7 @@ fn nominal_obligations(
             .zip(origins.into_iter().rev())
             .map(|((pred, span), origin_def_id)| {
                 let cause = self.cause(traits::BindingObligation(origin_def_id, span));
-                traits::Obligation::new(cause, self.param_env, pred)
+                traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
             })
             .filter(|pred| !pred.has_escaping_bound_vars())
             .collect()
@@ -688,8 +752,9 @@ fn from_object_ty(
                 let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
                 let outlives =
                     ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
-                self.out.push(traits::Obligation::new(
+                self.out.push(traits::Obligation::with_depth(
                     cause,
+                    self.recursion_depth,
                     self.param_env,
                     outlives.to_predicate(self.infcx.tcx),
                 ));
index 828ee6dea625689fa8c38de116c9af1fc886d214..223635e9aecd91aa70f80c259fd002011b3acd4c 100644 (file)
@@ -50,6 +50,19 @@ fn where_clauses_for(
             .map(|wc| wc.fold_with(&mut regions_substitutor))
             .filter_map(|wc| LowerInto::<Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>>::lower_into(wc, &self.interner)).collect()
     }
+
+    fn bounds_for<T>(&self, def_id: DefId, bound_vars: SubstsRef<'tcx>) -> Vec<T>
+    where
+        ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option<T>>,
+    {
+        self.interner
+            .tcx
+            .explicit_item_bounds(def_id)
+            .iter()
+            .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
+            .filter_map(|bound| LowerInto::<Option<_>>::lower_into(bound, &self.interner))
+            .collect()
+    }
 }
 
 impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'tcx> {
@@ -73,10 +86,9 @@ fn associated_ty_data(
         }
         let bound_vars = bound_vars_for_item(self.interner.tcx, def_id);
         let binders = binders_for(&self.interner, bound_vars);
-        // FIXME(chalk): this really isn't right I don't think. The functions
-        // for GATs are a bit hard to figure out. Are these supposed to be where
-        // clauses or bounds?
+
         let where_clauses = self.where_clauses_for(def_id, bound_vars);
+        let bounds = self.bounds_for(def_id, bound_vars);
 
         Arc::new(chalk_solve::rust_ir::AssociatedTyDatum {
             trait_id: chalk_ir::TraitId(trait_def_id),
@@ -84,7 +96,7 @@ fn associated_ty_data(
             name: (),
             binders: chalk_ir::Binders::new(
                 binders,
-                chalk_solve::rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses },
+                chalk_solve::rust_ir::AssociatedTyDatumBound { bounds, where_clauses },
             ),
         })
     }
@@ -442,11 +454,13 @@ fn opaque_ty_data(
         let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0);
         let binders = binders_for(&self.interner, bound_vars);
         let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars);
+        let bounds = self.bounds_for(opaque_ty_id.0, bound_vars);
 
         let value = chalk_solve::rust_ir::OpaqueTyDatumBound {
-            bounds: chalk_ir::Binders::new(binders.clone(), vec![]),
+            bounds: chalk_ir::Binders::new(binders.clone(), bounds),
             where_clauses: chalk_ir::Binders::new(binders, where_clauses),
         };
+
         Arc::new(chalk_solve::rust_ir::OpaqueTyDatum {
             opaque_ty_id,
             bound: chalk_ir::Binders::empty(&self.interner, value),
index 1e1841a57f8185cedd311d126d56449961a1a5ab..bdb2513cc46026ad81b0123446c45cc5f6dcd8ff 100644 (file)
@@ -728,6 +728,87 @@ fn lower_into(self, _interner: &RustInterner<'_>) -> FnSig<RustInterner<'tcx>> {
     }
 }
 
+// We lower into an Option here since there are some predicates which Chalk
+// doesn't have a representation for yet (as an `InlineBound`). The `Option` will
+// eventually be removed.
+impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>>>
+    for ty::Predicate<'tcx>
+{
+    fn lower_into(
+        self,
+        interner: &RustInterner<'tcx>,
+    ) -> Option<chalk_solve::rust_ir::QuantifiedInlineBound<RustInterner<'tcx>>> {
+        match self.bound_atom(interner.tcx).skip_binder() {
+            ty::PredicateAtom::Trait(predicate, _) => {
+                let (predicate, binders, _named_regions) =
+                    collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate));
+
+                Some(chalk_ir::Binders::new(
+                    binders,
+                    chalk_solve::rust_ir::InlineBound::TraitBound(
+                        predicate.trait_ref.lower_into(interner),
+                    ),
+                ))
+            }
+            ty::PredicateAtom::Projection(predicate) => {
+                let (predicate, binders, _named_regions) =
+                    collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate));
+
+                Some(chalk_ir::Binders::new(
+                    binders,
+                    chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
+                ))
+            }
+            ty::PredicateAtom::TypeOutlives(_predicate) => None,
+            ty::PredicateAtom::WellFormed(_ty) => None,
+
+            ty::PredicateAtom::RegionOutlives(..)
+            | ty::PredicateAtom::ObjectSafe(..)
+            | ty::PredicateAtom::ClosureKind(..)
+            | ty::PredicateAtom::Subtype(..)
+            | ty::PredicateAtom::ConstEvaluatable(..)
+            | ty::PredicateAtom::ConstEquate(..)
+            | ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
+                bug!("unexpected predicate {}", &self)
+            }
+        }
+    }
+}
+
+impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>>>
+    for ty::TraitRef<'tcx>
+{
+    fn lower_into(
+        self,
+        interner: &RustInterner<'tcx>,
+    ) -> chalk_solve::rust_ir::TraitBound<RustInterner<'tcx>> {
+        chalk_solve::rust_ir::TraitBound {
+            trait_id: chalk_ir::TraitId(self.def_id),
+            args_no_self: self.substs[1..].iter().map(|arg| arg.lower_into(interner)).collect(),
+        }
+    }
+}
+
+impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>>
+    for ty::ProjectionPredicate<'tcx>
+{
+    fn lower_into(
+        self,
+        interner: &RustInterner<'tcx>,
+    ) -> chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>> {
+        let trait_ref = self.projection_ty.trait_ref(interner.tcx);
+        chalk_solve::rust_ir::AliasEqBound {
+            trait_bound: trait_ref.lower_into(interner),
+            associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
+            parameters: self.projection_ty.substs[trait_ref.substs.len()..]
+                .iter()
+                .map(|arg| arg.lower_into(interner))
+                .collect(),
+            value: self.ty.lower_into(interner),
+        }
+    }
+}
+
 /// To collect bound vars, we have to do two passes. In the first pass, we
 /// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then
 /// replace `BrNamed` into `BrAnon`. The two separate passes are important,
index 79308b032eccd89e7b5bbf1521225e63adf9df46..bc5c07fce045c385f7c8e839f7714e456dab798c 100644 (file)
@@ -61,8 +61,8 @@ fn compute_implied_outlives_bounds<'tcx>(
         // than the ultimate set. (Note: normally there won't be
         // unresolved inference variables here anyway, but there might be
         // during typeck under some circumstances.)
-        let obligations =
-            wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, arg, DUMMY_SP).unwrap_or(vec![]);
+        let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
+            .unwrap_or(vec![]);
 
         // N.B., all of these predicates *ought* to be easily proven
         // true. In fact, their correctness is (mostly) implied by
index c4b6b64339a03713bf481545ee1bbf4a62984d66..1f21d9488a454b720dd79319b0d95820d7c8c07d 100644 (file)
@@ -1,11 +1,9 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_infer::traits::util;
 use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{
     self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
 };
@@ -492,133 +490,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
     fn_like.asyncness()
 }
 
-/// For associated types we allow bounds written on the associated type
-/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
-/// when desugared as bounds on the trait `where Self::X: Trait`.
-///
-/// Note that this filtering is done with the items identity substs to
-/// simplify checking that these bounds are met in impls. This means that
-/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
-/// `hr-associated-type-bound-1.rs`.
-fn associated_type_projection_predicates(
-    tcx: TyCtxt<'_>,
-    assoc_item_def_id: DefId,
-) -> &'_ ty::List<ty::Predicate<'_>> {
-    let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
-    // We include predicates from the trait as well to handle
-    // `where Self::X: Trait`.
-    let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
-    let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
-
-    let assoc_item_ty = ty::ProjectionTy {
-        item_def_id: assoc_item_def_id,
-        substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
-    };
-
-    let predicates = item_predicates.filter_map(|obligation| {
-        let pred = obligation.predicate;
-        match pred.skip_binders() {
-            ty::PredicateAtom::Trait(tr, _) => {
-                if let ty::Projection(p) = *tr.self_ty().kind() {
-                    if p == assoc_item_ty {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::Projection(proj) => {
-                if let ty::Projection(p) = *proj.projection_ty.self_ty().kind() {
-                    if p == assoc_item_ty {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::TypeOutlives(outlives) => {
-                if let ty::Projection(p) = *outlives.0.kind() {
-                    if p == assoc_item_ty {
-                        return Some(pred);
-                    }
-                }
-            }
-            _ => {}
-        }
-        None
-    });
-
-    let result = tcx.mk_predicates(predicates);
-    debug!(
-        "associated_type_projection_predicates({}) = {:?}",
-        tcx.def_path_str(assoc_item_def_id),
-        result
-    );
-    result
-}
-
-/// Opaque types don't have the same issues as associated types: the only
-/// predicates on an opaque type (excluding those it inherits from its parent
-/// item) should be of the form we're expecting.
-fn opaque_type_projection_predicates(
-    tcx: TyCtxt<'_>,
-    def_id: DefId,
-) -> &'_ ty::List<ty::Predicate<'_>> {
-    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-
-    let bounds = tcx.predicates_of(def_id);
-    let predicates =
-        util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred));
-
-    let filtered_predicates = predicates.filter_map(|obligation| {
-        let pred = obligation.predicate;
-        match pred.skip_binders() {
-            ty::PredicateAtom::Trait(tr, _) => {
-                if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.self_ty().kind() {
-                    if opaque_def_id == def_id && opaque_substs == substs {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::Projection(proj) => {
-                if let ty::Opaque(opaque_def_id, opaque_substs) =
-                    *proj.projection_ty.self_ty().kind()
-                {
-                    if opaque_def_id == def_id && opaque_substs == substs {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::TypeOutlives(outlives) => {
-                if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.0.kind() {
-                    if opaque_def_id == def_id && opaque_substs == substs {
-                        return Some(pred);
-                    }
-                } else {
-                    // These can come from elaborating other predicates
-                    return None;
-                }
-            }
-            // These can come from elaborating other predicates
-            ty::PredicateAtom::RegionOutlives(_) => return None,
-            _ => {}
-        }
-        tcx.sess.delay_span_bug(
-            obligation.cause.span(tcx),
-            &format!("unexpected predicate {:?} on opaque type", pred),
-        );
-        None
-    });
-
-    let result = tcx.mk_predicates(filtered_predicates);
-    debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
-    result
-}
-
-fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
-    match tcx.def_kind(def_id) {
-        DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id),
-        DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id),
-        k => bug!("projection_predicates called on {}", k.descr(def_id)),
-    }
-}
-
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
         asyncness,
@@ -636,7 +507,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         instance_def_size_estimate,
         issue33140_self_ty,
         impl_defaultness,
-        projection_predicates,
         ..*providers
     };
 }
index 63295f5faacc9c8b4d6aea95025c1ea17de1be56..80f39051c587f9d9055c151c07cd84dca3454f19 100644 (file)
@@ -71,12 +71,8 @@ pub fn predicates(
                 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 either only refers to early-bound regions,
-                        // or it's a generic associated type that deliberately has escaping bound vars.
-                        let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
                         let outlives = ty::OutlivesPredicate(param_ty, region_bound);
-                        (ty::Binder::bind(outlives).to_predicate(tcx), span)
+                        (ty::Binder::dummy(outlives).to_predicate(tcx), span)
                     })
                     .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
                         let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
index 0647be2dfde0be3332a26ef0952dd590833f6ec6..d319ac2cba65479823f0263ff7a87f99142abd90 100644 (file)
@@ -1,15 +1,16 @@
 use super::coercion::CoerceMany;
+use super::compare_method::check_type_bounds;
 use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
 use super::*;
 
 use rustc_attr as attr;
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ItemKind, Node};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::RegionVariableOrigin;
+use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt, Representability};
@@ -18,6 +19,8 @@
 use rustc_span::symbol::sym;
 use rustc_span::{self, MultiSpan, Span};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::opaque_types::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
 
 pub fn check_wf_new(tcx: TyCtxt<'_>) {
@@ -385,8 +388,13 @@ pub(super) fn check_opaque<'tcx>(
     origin: &hir::OpaqueTyOrigin,
 ) {
     check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
-    tcx.ensure().type_of(def_id);
-    check_opaque_for_cycles(tcx, def_id, substs, span, origin);
+    if tcx.type_of(def_id).references_error() {
+        return;
+    }
+    if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() {
+        return;
+    }
+    check_opaque_meets_bounds(tcx, def_id, substs, span, origin);
 }
 
 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
@@ -453,8 +461,7 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
             ty: None,
         };
         let prohibit_opaque = tcx
-            .predicates_of(def_id)
-            .predicates
+            .explicit_item_bounds(def_id)
             .iter()
             .any(|(predicate, _)| predicate.visit_with(&mut visitor));
         debug!(
@@ -476,7 +483,7 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
                 span,
                 E0760,
                 "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
-             a parent scope",
+                 a parent scope",
                 if is_async { "async fn" } else { "impl Trait" },
             );
 
@@ -504,7 +511,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
     substs: SubstsRef<'tcx>,
     span: Span,
     origin: &hir::OpaqueTyOrigin,
-) {
+) -> Result<(), ErrorReported> {
     if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
     {
         match origin {
@@ -514,9 +521,82 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
             }
             _ => opaque_type_cycle_error(tcx, def_id, span),
         }
+        Err(ErrorReported)
+    } else {
+        Ok(())
     }
 }
 
+/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
+///
+/// This is mostly checked at the places that specify the opaque type, but we
+/// check those cases in the `param_env` of that function, which may have
+/// bounds not on this opaque type:
+///
+/// type X<T> = impl Clone
+/// fn f<T: Clone>(t: T) -> X<T> {
+///     t
+/// }
+///
+/// Without this check the above code is incorrectly accepted: we would ICE if
+/// some tried, for example, to clone an `Option<X<&mut ()>>`.
+fn check_opaque_meets_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+    substs: SubstsRef<'tcx>,
+    span: Span,
+    origin: &hir::OpaqueTyOrigin,
+) {
+    match origin {
+        // Checked when type checking the function containing them.
+        hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return,
+        // Can have different predicates to their defining use
+        hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => {}
+    }
+
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+    let param_env = tcx.param_env(def_id);
+
+    tcx.infer_ctxt().enter(move |infcx| {
+        let inh = Inherited::new(infcx, def_id);
+        let infcx = &inh.infcx;
+        let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
+
+        let misc_cause = traits::ObligationCause::misc(span, hir_id);
+
+        let (_, opaque_type_map) = inh.register_infer_ok_obligations(
+            infcx.instantiate_opaque_types(def_id, hir_id, param_env, &opaque_ty, span),
+        );
+
+        for (def_id, opaque_defn) in opaque_type_map {
+            match infcx
+                .at(&misc_cause, param_env)
+                .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs))
+            {
+                Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
+                Err(ty_err) => tcx.sess.delay_span_bug(
+                    opaque_defn.definition_span,
+                    &format!(
+                        "could not unify `{}` with revealed type:\n{}",
+                        opaque_defn.concrete_ty, ty_err,
+                    ),
+                ),
+            }
+        }
+
+        // Check that all obligations are satisfied by the implementation's
+        // version.
+        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
+            infcx.report_fulfillment_errors(errors, None, false);
+        }
+
+        // Finally, resolve all regions. This catches wily misuses of
+        // lifetime parameters.
+        let fcx = FnCtxt::new(&inh, param_env, hir_id);
+        fcx.regionck_item(hir_id, span, &[]);
+    });
+}
+
 pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
     debug!(
         "check_item_type(it.hir_id={}, it.name={})",
@@ -553,9 +633,25 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
 
             for item in items.iter() {
                 let item = tcx.hir().trait_item(item.id);
-                if let hir::TraitItemKind::Fn(sig, _) = &item.kind {
-                    let abi = sig.header.abi;
-                    fn_maybe_err(tcx, item.ident.span, abi);
+                match item.kind {
+                    hir::TraitItemKind::Fn(ref sig, _) => {
+                        let abi = sig.header.abi;
+                        fn_maybe_err(tcx, item.ident.span, abi);
+                    }
+                    hir::TraitItemKind::Type(.., Some(_default)) => {
+                        let item_def_id = tcx.hir().local_def_id(item.hir_id).to_def_id();
+                        let assoc_item = tcx.associated_item(item_def_id);
+                        let trait_substs =
+                            InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                        let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds(
+                            tcx,
+                            assoc_item,
+                            assoc_item,
+                            item.span,
+                            ty::TraitRef { def_id: def_id.to_def_id(), substs: trait_substs },
+                        );
+                    }
+                    _ => {}
                 }
             }
         }
index 7aa54e0ebcc6b5d5d2f9ab3a3a1a90097ab98dc7..4acc7451a2131399a065829788a1f8f7698a4c62 100644 (file)
@@ -5,6 +5,7 @@
 use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_infer::traits::util;
 use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -327,7 +328,7 @@ fn compare_predicate_entailment<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
-        fcx.regionck_item(impl_m_hir_id, impl_m_span, &[]);
+        fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output);
 
         Ok(())
     })
@@ -1052,7 +1053,7 @@ fn nested_visit_map(
 
         compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
 
-        compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
+        check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
     })();
 }
 
@@ -1170,20 +1171,13 @@ fn compare_type_predicate_entailment<'tcx>(
 /// For default associated types the normalization is not possible (the value
 /// from the impl could be overridden). We also can't normalize generic
 /// associated types (yet) because they contain bound parameters.
-fn compare_projection_bounds<'tcx>(
+pub fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ty: &ty::AssocItem,
     impl_ty: &ty::AssocItem,
     impl_ty_span: Span,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorReported> {
-    let have_gats = tcx.features().generic_associated_types;
-    if impl_ty.defaultness.is_final() && !have_gats {
-        // For "final", non-generic associate type implementations, we
-        // don't need this as described above.
-        return Ok(());
-    }
-
     // Given
     //
     // impl<A, B> Foo<u32> for (A, B) {
@@ -1211,16 +1205,27 @@ fn compare_projection_bounds<'tcx>(
     // ParamEnv for normalization specifically.
     let normalize_param_env = {
         let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
-        predicates.push(
-            ty::Binder::dummy(ty::ProjectionPredicate {
-                projection_ty: ty::ProjectionTy {
-                    item_def_id: trait_ty.def_id,
-                    substs: rebased_substs,
-                },
-                ty: impl_ty_value,
-            })
-            .to_predicate(tcx),
-        );
+        match impl_ty_value.kind() {
+            ty::Projection(proj)
+                if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+            {
+                // Don't include this predicate if the projected type is
+                // exactly the same as the projection. This can occur in
+                // (somewhat dubious) code like this:
+                //
+                // impl<T> X for T where T: X { type Y = <T as X>::Y; }
+            }
+            _ => predicates.push(
+                ty::Binder::dummy(ty::ProjectionPredicate {
+                    projection_ty: ty::ProjectionTy {
+                        item_def_id: trait_ty.def_id,
+                        substs: rebased_substs,
+                    },
+                    ty: impl_ty_value,
+                })
+                .to_predicate(tcx),
+            ),
+        };
         ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
     };
 
@@ -1231,33 +1236,38 @@ fn compare_projection_bounds<'tcx>(
 
         let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
         let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
-        let cause = ObligationCause::new(
-            impl_ty_span,
-            impl_ty_hir_id,
-            ObligationCauseCode::ItemObligation(trait_ty.def_id),
-        );
+        let mk_cause = |span| {
+            ObligationCause::new(
+                impl_ty_span,
+                impl_ty_hir_id,
+                ObligationCauseCode::BindingObligation(trait_ty.def_id, span),
+            )
+        };
 
-        let predicates = tcx.projection_predicates(trait_ty.def_id);
-        debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
+        let obligations = tcx
+            .explicit_item_bounds(trait_ty.def_id)
+            .iter()
+            .map(|&(bound, span)| {
+                let concrete_ty_bound = bound.subst(tcx, rebased_substs);
+                debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
 
-        for predicate in predicates {
-            let concrete_ty_predicate = predicate.subst(tcx, rebased_substs);
-            debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate);
+                traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
+            })
+            .collect();
+        debug!("check_type_bounds: item_bounds={:?}", obligations);
 
+        for mut obligation in util::elaborate_obligations(tcx, obligations) {
             let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
                 &mut selcx,
                 normalize_param_env,
                 normalize_cause.clone(),
-                &concrete_ty_predicate,
+                &obligation.predicate,
             );
             debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
+            obligation.predicate = normalized_predicate;
 
             inh.register_predicates(obligations);
-            inh.register_predicate(traits::Obligation::new(
-                cause.clone(),
-                param_env,
-                normalized_predicate,
-            ));
+            inh.register_predicate(obligation);
         }
 
         // Check that all obligations are satisfied by the implementation's
@@ -1270,7 +1280,11 @@ fn compare_projection_bounds<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+        let implied_bounds = match impl_ty.container {
+            ty::TraitContainer(_) => vec![],
+            ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
+        };
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds);
 
         Ok(())
     })
index 5203f3fa8f1d5b0ddad3eefaa03991558871f856..b4e950ab6e9e50b7771b25ca7c3cff6eb6c8ddbf 100644 (file)
@@ -420,6 +420,9 @@ fn check_associated_item(
                 check_method_receiver(fcx, hir_sig, &item, self_ty);
             }
             ty::AssocKind::Type => {
+                if let ty::AssocItemContainer::TraitContainer(_) = item.container {
+                    check_associated_type_bounds(fcx, item, span)
+                }
                 if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
                     let ty = fcx.normalize_associated_types_in(span, &ty);
@@ -571,7 +574,6 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
 
     for_item(tcx, item).with_fcx(|fcx, _| {
         check_where_clauses(tcx, fcx, item.span, trait_def_id.to_def_id(), None);
-        check_associated_type_defaults(fcx, trait_def_id.to_def_id());
 
         vec![]
     });
@@ -581,96 +583,26 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
 ///
 /// Assuming the defaults are used, check that all predicates (bounds on the
 /// assoc type and where clauses on the trait) hold.
-fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) {
+fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span: Span) {
     let tcx = fcx.tcx;
-    let substs = InternalSubsts::identity_for_item(tcx, trait_def_id);
-
-    // For all assoc. types with defaults, build a map from
-    // `<Self as Trait<...>>::Assoc` to the default type.
-    let map = tcx
-        .associated_items(trait_def_id)
-        .in_definition_order()
-        .filter_map(|item| {
-            if item.kind == ty::AssocKind::Type && item.defaultness.has_value() {
-                // `<Self as Trait<...>>::Assoc`
-                let proj = ty::ProjectionTy { substs, item_def_id: item.def_id };
-                let default_ty = tcx.type_of(item.def_id);
-                debug!("assoc. type default mapping: {} -> {}", proj, default_ty);
-                Some((proj, default_ty))
-            } else {
-                None
-            }
-        })
-        .collect::<FxHashMap<_, _>>();
-
-    /// Replaces projections of associated types with their default types.
-    ///
-    /// This does a "shallow substitution", meaning that defaults that refer to
-    /// other defaulted assoc. types will still refer to the projection
-    /// afterwards, not to the other default. For example:
-    ///
-    /// ```compile_fail
-    /// trait Tr {
-    ///     type A: Clone = Vec<Self::B>;
-    ///     type B = u8;
-    /// }
-    /// ```
-    ///
-    /// This will end up replacing the bound `Self::A: Clone` with
-    /// `Vec<Self::B>: Clone`, not with `Vec<u8>: Clone`. If we did a deep
-    /// substitution and ended up with the latter, the trait would be accepted.
-    /// If an `impl` then replaced `B` with something that isn't `Clone`,
-    /// suddenly the default for `A` is no longer valid. The shallow
-    /// substitution forces the trait to add a `B: Clone` bound to be accepted,
-    /// which means that an `impl` can replace any default without breaking
-    /// others.
-    ///
-    /// Note that this isn't needed for soundness: The defaults would still be
-    /// checked in any impl that doesn't override them.
-    struct DefaultNormalizer<'tcx> {
-        tcx: TyCtxt<'tcx>,
-        map: FxHashMap<ty::ProjectionTy<'tcx>, Ty<'tcx>>,
-    }
 
-    impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> {
-        fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
-            self.tcx
-        }
+    let bounds = tcx.explicit_item_bounds(item.def_id);
 
-        fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-            match t.kind() {
-                ty::Projection(proj_ty) => {
-                    if let Some(default) = self.map.get(&proj_ty) {
-                        default
-                    } else {
-                        t.super_fold_with(self)
-                    }
-                }
-                _ => t.super_fold_with(self),
-            }
-        }
-    }
-
-    // Now take all predicates defined on the trait, replace any mention of
-    // the assoc. types with their default, and prove them.
-    // We only consider predicates that directly mention the assoc. type.
-    let mut norm = DefaultNormalizer { tcx, map };
-    let predicates = fcx.tcx.predicates_of(trait_def_id);
-    for &(orig_pred, span) in predicates.predicates.iter() {
-        let pred = orig_pred.fold_with(&mut norm);
-        if pred != orig_pred {
-            // Mentions one of the defaulted assoc. types
-            debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred);
-            let pred = fcx.normalize_associated_types_in(span, &pred);
-            let cause = traits::ObligationCause::new(
-                span,
-                fcx.body_id,
-                traits::ItemObligation(trait_def_id),
-            );
-            let obligation = traits::Obligation::new(cause, fcx.param_env, pred);
+    debug!("check_associated_type_bounds: bounds={:?}", bounds);
+    let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
+        let normalized_bound = fcx.normalize_associated_types_in(span, &bound);
+        traits::wf::predicate_obligations(
+            fcx,
+            fcx.param_env,
+            fcx.body_id,
+            normalized_bound,
+            bound_span,
+        )
+    });
 
-            fcx.register_predicate(obligation);
-        }
+    for obligation in wf_obligations {
+        debug!("next obligation cause: {:?}", obligation.cause);
+        fcx.register_predicate(obligation);
     }
 }
 
@@ -1493,7 +1425,7 @@ fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec<AdtVariant<'tcx>> {
             .collect()
     }
 
-    fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
+    pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
         match self.tcx.impl_trait_ref(impl_def_id) {
             Some(ref trait_ref) => {
                 // Trait impl: take implied bounds from all types that
index 1f4f40fca9be33dbb161b01273f8e3d84c410465..092dae18192e51e03100ab4b632af06fa7a3ee5a 100644 (file)
@@ -50,6 +50,7 @@
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 
+mod item_bounds;
 mod type_of;
 
 struct OnlySelfBounds(bool);
@@ -68,12 +69,15 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         opt_const_param_of: type_of::opt_const_param_of,
         type_of: type_of::type_of,
+        item_bounds: item_bounds::item_bounds,
+        explicit_item_bounds: item_bounds::explicit_item_bounds,
         generics_of,
         predicates_of,
         predicates_defined_on,
         projection_ty_from_predicates,
         explicit_predicates_of,
         super_predicates_of,
+        trait_explicit_predicates_and_bounds,
         type_param_predicates,
         trait_def,
         adt_def,
@@ -700,6 +704,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
         hir::ItemKind::OpaqueTy(..) => {
             tcx.ensure().generics_of(def_id);
             tcx.ensure().predicates_of(def_id);
+            tcx.ensure().explicit_item_bounds(def_id);
         }
         hir::ItemKind::TyAlias(..)
         | hir::ItemKind::Static(..)
@@ -708,8 +713,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
             tcx.ensure().generics_of(def_id);
             tcx.ensure().type_of(def_id);
             tcx.ensure().predicates_of(def_id);
-            if let hir::ItemKind::Fn(..) = it.kind {
-                tcx.ensure().fn_sig(def_id);
+            match it.kind {
+                hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
+                hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
+                _ => (),
             }
         }
     }
@@ -730,15 +737,25 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
             tcx.ensure().type_of(def_id);
         }
 
-        hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(_, Some(_)) => {
+        hir::TraitItemKind::Const(..) => {
             tcx.ensure().type_of(def_id);
-            // Account for `const C: _;` and `type T = _;`.
+            // Account for `const C: _;`.
+            let mut visitor = PlaceholderHirTyCollector::default();
+            visitor.visit_trait_item(trait_item);
+            placeholder_type_error(tcx, None, &[], visitor.0, false);
+        }
+
+        hir::TraitItemKind::Type(_, Some(_)) => {
+            tcx.ensure().item_bounds(def_id);
+            tcx.ensure().type_of(def_id);
+            // Account for `type T = _;`.
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_trait_item(trait_item);
             placeholder_type_error(tcx, None, &[], visitor.0, false);
         }
 
         hir::TraitItemKind::Type(_, None) => {
+            tcx.ensure().item_bounds(def_id);
             // #74612: Visit and try to find bad placeholders
             // even if there is no concrete type.
             let mut visitor = PlaceholderHirTyCollector::default();
@@ -1716,7 +1733,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
 
 /// Returns a list of user-specified type predicates for the definition with ID `def_id`.
 /// N.B., this does not include any implied/inferred constraints.
-fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
     use rustc_hir::*;
 
     debug!("explicit_predicates_of(def_id={:?})", def_id);
@@ -1726,7 +1743,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
 
     let mut is_trait = None;
     let mut is_default_impl_trait = None;
-    let mut is_trait_associated_type = None;
 
     let icx = ItemCtxt::new(tcx, def_id);
     let constness = icx.default_constness_for_trait_bounds();
@@ -1739,12 +1755,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
 
     let ast_generics = match node {
-        Node::TraitItem(item) => {
-            if let hir::TraitItemKind::Type(bounds, _) = item.kind {
-                is_trait_associated_type = Some((bounds, item.span));
-            }
-            &item.generics
-        }
+        Node::TraitItem(item) => &item.generics,
 
         Node::ImplItem(item) => &item.generics,
 
@@ -1762,44 +1773,38 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
                 | ItemKind::Struct(_, ref generics)
                 | ItemKind::Union(_, ref generics) => generics,
 
-                ItemKind::Trait(_, _, ref generics, .., items) => {
-                    is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
+                ItemKind::Trait(_, _, ref generics, ..) => {
+                    is_trait = Some(ty::TraitRef::identity(tcx, def_id));
                     generics
                 }
                 ItemKind::TraitAlias(ref generics, _) => {
-                    is_trait = Some((ty::TraitRef::identity(tcx, def_id), &[]));
+                    is_trait = Some(ty::TraitRef::identity(tcx, def_id));
                     generics
                 }
                 ItemKind::OpaqueTy(OpaqueTy {
-                    ref bounds,
+                    bounds: _,
                     impl_trait_fn,
                     ref generics,
                     origin: _,
                 }) => {
-                    let bounds_predicates = ty::print::with_no_queries(|| {
-                        let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                        let opaque_ty = tcx.mk_opaque(def_id, substs);
-
-                        // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
-                        let bounds = AstConv::compute_bounds(
-                            &icx,
-                            opaque_ty,
-                            bounds,
-                            SizedByDefault::Yes,
-                            tcx.def_span(def_id),
-                        );
-
-                        bounds.predicates(tcx, opaque_ty)
-                    });
                     if impl_trait_fn.is_some() {
-                        // opaque types
-                        return ty::GenericPredicates {
-                            parent: None,
-                            predicates: tcx.arena.alloc_from_iter(bounds_predicates),
-                        };
+                        // return-position impl trait
+                        //
+                        // We don't inherit predicates from the parent here:
+                        // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}`
+                        // then the return type is `f::<'static, T>::{{opaque}}`.
+                        //
+                        // If we inherited the predicates of `f` then we would
+                        // require that `T: 'static` to show that the return
+                        // type is well-formed.
+                        //
+                        // The only way to have something with this opaque type
+                        // is from the return type of the containing function,
+                        // which will ensure that the function's predicates
+                        // hold.
+                        return ty::GenericPredicates { parent: None, predicates: &[] };
                     } else {
-                        // named opaque types
-                        predicates.extend(bounds_predicates);
+                        // type-alias impl trait
                         generics
                     }
                 }
@@ -1825,7 +1830,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     // and the explicit where-clauses, but to get the full set of predicates
     // on a trait we need to add in the supertrait bounds and bounds found on
     // associated types.
-    if let Some((_trait_ref, _)) = is_trait {
+    if let Some(_trait_ref) = is_trait {
         predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
     }
 
@@ -1992,24 +1997,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
         }
     }
 
-    // Add predicates from associated type bounds (`type X: Bound`)
-    if tcx.features().generic_associated_types {
-        // New behavior: bounds declared on associate type are predicates of that
-        // associated type. Not the default because it needs more testing.
-        if let Some((bounds, span)) = is_trait_associated_type {
-            let projection_ty =
-                tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id));
-
-            predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span))
-        }
-    } else if let Some((self_trait_ref, trait_items)) = is_trait {
-        // Current behavior: bounds declared on associate type are predicates
-        // of its parent trait.
-        predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
-            trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
-        }))
-    }
-
     if tcx.features().const_evaluatable_checked {
         predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
     }
@@ -2131,6 +2118,69 @@ fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool {
     collector.preds
 }
 
+fn trait_explicit_predicates_and_bounds(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+) -> ty::GenericPredicates<'_> {
+    assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
+    gather_explicit_predicates_of(tcx, def_id.to_def_id())
+}
+
+fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+    if let DefKind::Trait = tcx.def_kind(def_id) {
+        // Remove bounds on associated types from the predicates, they will be
+        // returned by `explicit_item_bounds`.
+        let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
+        let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+
+        let is_assoc_item_ty = |ty: Ty<'_>| {
+            // For a predicate from a where clause to become a bound on an
+            // associated type:
+            // * It must use the identity substs of the item.
+            //     * Since any generic parameters on the item are not in scope,
+            //       this means that the item is not a GAT, and its identity
+            //       substs are the same as the trait's.
+            // * It must be an associated type for this trait (*not* a
+            //   supertrait).
+            if let ty::Projection(projection) = ty.kind() {
+                if projection.substs == trait_identity_substs
+                    && tcx.associated_item(projection.item_def_id).container.id() == def_id
+                {
+                    true
+                } else {
+                    false
+                }
+            } else {
+                false
+            }
+        };
+
+        let predicates: Vec<_> = predicates_and_bounds
+            .predicates
+            .iter()
+            .copied()
+            .filter(|(pred, _)| match pred.skip_binders() {
+                ty::PredicateAtom::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()),
+                ty::PredicateAtom::Projection(proj) => {
+                    !is_assoc_item_ty(proj.projection_ty.self_ty())
+                }
+                ty::PredicateAtom::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
+                _ => true,
+            })
+            .collect();
+        if predicates.len() == predicates_and_bounds.predicates.len() {
+            predicates_and_bounds
+        } else {
+            ty::GenericPredicates {
+                parent: predicates_and_bounds.parent,
+                predicates: tcx.arena.alloc_slice(&predicates),
+            }
+        }
+    } else {
+        gather_explicit_predicates_of(tcx, def_id)
+    }
+}
+
 fn projection_ty_from_predicates(
     tcx: TyCtxt<'tcx>,
     key: (
@@ -2153,55 +2203,6 @@ fn projection_ty_from_predicates(
     projection_ty
 }
 
-fn trait_associated_item_predicates(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-    self_trait_ref: ty::TraitRef<'tcx>,
-    trait_item_ref: &hir::TraitItemRef,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
-    let trait_item = tcx.hir().trait_item(trait_item_ref.id);
-    let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
-    let bounds = match trait_item.kind {
-        hir::TraitItemKind::Type(ref bounds, _) => bounds,
-        _ => return Vec::new(),
-    };
-
-    if !tcx.generics_of(item_def_id).params.is_empty() {
-        // For GATs the substs provided to the mk_projection call below are
-        // wrong. We should emit a feature gate error if we get here so skip
-        // this type.
-        tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate");
-        return Vec::new();
-    }
-
-    let assoc_ty = tcx.mk_projection(
-        tcx.hir().local_def_id(trait_item.hir_id).to_def_id(),
-        self_trait_ref.substs,
-    );
-
-    associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span)
-}
-
-fn associated_item_bounds(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-    bounds: &'tcx [hir::GenericBound<'tcx>],
-    projection_ty: Ty<'tcx>,
-    span: Span,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
-    let bounds = AstConv::compute_bounds(
-        &ItemCtxt::new(tcx, def_id),
-        projection_ty,
-        bounds,
-        SizedByDefault::Yes,
-        span,
-    );
-
-    let predicates = bounds.predicates(tcx, projection_ty);
-
-    predicates
-}
-
 /// 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 zero predicates (`T: ?Sized` adds no
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
new file mode 100644 (file)
index 0000000..9c29cee
--- /dev/null
@@ -0,0 +1,111 @@
+use super::ItemCtxt;
+use crate::astconv::{AstConv, SizedByDefault};
+use rustc_hir as hir;
+use rustc_infer::traits::util;
+use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::DefId;
+use rustc_span::Span;
+
+/// For associated types we include both bounds written on the type
+/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
+///
+/// Note that this filtering is done with the items identity substs to
+/// simplify checking that these bounds are met in impls. This means that
+/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
+/// `hr-associated-type-bound-1.rs`.
+fn associated_type_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    assoc_item_def_id: DefId,
+    bounds: &'tcx [hir::GenericBound<'tcx>],
+    span: Span,
+) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+    let item_ty = tcx.mk_projection(
+        assoc_item_def_id,
+        InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
+    );
+
+    let bounds = AstConv::compute_bounds(
+        &ItemCtxt::new(tcx, assoc_item_def_id),
+        item_ty,
+        bounds,
+        SizedByDefault::Yes,
+        span,
+    );
+
+    let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
+    let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
+
+    let bounds_from_parent =
+        trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.skip_binders() {
+            ty::PredicateAtom::Trait(tr, _) => tr.self_ty() == item_ty,
+            ty::PredicateAtom::Projection(proj) => proj.projection_ty.self_ty() == item_ty,
+            ty::PredicateAtom::TypeOutlives(outlives) => outlives.0 == item_ty,
+            _ => false,
+        });
+
+    let all_bounds = tcx
+        .arena
+        .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
+    debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
+    all_bounds
+}
+
+/// Opaque types don't inherit bounds from their parent: for return position
+/// impl trait it isn't possible to write a suitable predicate on the
+/// containing function and for type-alias impl trait we don't have a backwards
+/// compatibility issue.
+fn opaque_type_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    opaque_def_id: DefId,
+    bounds: &'tcx [hir::GenericBound<'tcx>],
+    span: Span,
+) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+    let item_ty =
+        tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
+
+    let bounds = ty::print::with_no_queries(|| {
+        AstConv::compute_bounds(
+            &ItemCtxt::new(tcx, opaque_def_id),
+            item_ty,
+            bounds,
+            SizedByDefault::Yes,
+            span,
+        )
+    });
+
+    let bounds = bounds.predicates(tcx, item_ty);
+    debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
+
+    tcx.arena.alloc_slice(&bounds)
+}
+
+pub(super) fn explicit_item_bounds(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+) -> &'_ [(ty::Predicate<'_>, Span)] {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    match tcx.hir().get(hir_id) {
+        hir::Node::TraitItem(hir::TraitItem {
+            kind: hir::TraitItemKind::Type(bounds, _),
+            span,
+            ..
+        }) => associated_type_bounds(tcx, def_id, bounds, *span),
+        hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
+            span,
+            ..
+        }) => opaque_type_bounds(tcx, def_id, bounds, *span),
+        _ => bug!("item_bounds called on {:?}", def_id),
+    }
+}
+
+pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
+    tcx.mk_predicates(
+        util::elaborate_predicates(
+            tcx,
+            tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
+        )
+        .map(|obligation| obligation.predicate),
+    )
+}
index 60b9467fca8b3dc05674735ec9b7e02c59cced6c..4cf3efcf5136d254e834414e846d59ea15aa4ba5 100644 (file)
@@ -337,6 +337,7 @@ fn check_predicates<'tcx>(
             infcx,
             tcx.param_env(impl1_def_id),
             tcx.hir().local_def_id_to_hir_id(impl1_def_id),
+            0,
             arg,
             span,
         ) {
index 788bb5e787b829d937ccc6dbd43f85d86b431d25..ac1e2b467045c5a03f8cf75926ba156c83cbba54 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::middle::stability;
 use rustc_middle::ty::fold::TypeFolder;
-use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
 use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
 use rustc_span::hygiene::MacroKind;
@@ -1268,13 +1268,10 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             ty::AssocKind::Type => {
                 let my_name = self.ident.name.clean(cx);
 
-                if let ty::TraitContainer(did) = self.container {
-                    // When loading a cross-crate associated type, the bounds for this type
-                    // are actually located on the trait/impl itself, so we need to load
-                    // all of the generics from there and then look for bounds that are
-                    // applied to this associated type in question.
-                    let predicates = cx.tcx.explicit_predicates_of(did);
-                    let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+                if let ty::TraitContainer(_) = self.container {
+                    let bounds = cx.tcx.explicit_item_bounds(self.def_id);
+                    let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
+                    let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx);
                     let mut bounds = generics
                         .where_predicates
                         .iter()
@@ -1678,19 +1675,22 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
 
             ty::Opaque(def_id, substs) => {
                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
-                // by looking up the projections associated with the def_id.
-                let predicates_of = cx.tcx.explicit_predicates_of(def_id);
+                // by looking up the bounds associated with the def_id.
                 let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
-                let bounds = predicates_of.instantiate(cx.tcx, substs);
+                let bounds = cx
+                    .tcx
+                    .explicit_item_bounds(def_id)
+                    .iter()
+                    .map(|(bound, _)| bound.subst(cx.tcx, substs))
+                    .collect::<Vec<_>>();
                 let mut regions = vec![];
                 let mut has_sized = false;
                 let mut bounds = bounds
-                    .predicates
                     .iter()
-                    .filter_map(|predicate| {
+                    .filter_map(|bound| {
                         // Note: The substs of opaque types can contain unbound variables,
                         // meaning that we have to use `ignore_quantifiers_with_unbound_vars` here.
-                        let trait_ref = match predicate.bound_atom(cx.tcx).skip_binder() {
+                        let trait_ref = match bound.bound_atom(cx.tcx).skip_binder() {
                             ty::PredicateAtom::Trait(tr, _constness) => {
                                 ty::Binder::bind(tr.trait_ref)
                             }
@@ -1711,11 +1711,10 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
                         }
 
                         let bounds: Vec<_> = bounds
-                            .predicates
                             .iter()
-                            .filter_map(|pred| {
+                            .filter_map(|bound| {
                                 if let ty::PredicateAtom::Projection(proj) =
-                                    pred.bound_atom(cx.tcx).skip_binder()
+                                    bound.bound_atom(cx.tcx).skip_binder()
                                 {
                                     if proj.projection_ty.trait_ref(cx.tcx)
                                         == trait_ref.skip_binder()
@@ -2067,13 +2066,10 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             visibility: self.vis.clean(cx),
             stability: cx.stability(self.id).clean(cx),
             deprecation: cx.deprecation(self.id).clean(cx),
-            inner: OpaqueTyItem(
-                OpaqueTy {
-                    bounds: self.opaque_ty.bounds.clean(cx),
-                    generics: self.opaque_ty.generics.clean(cx),
-                },
-                false,
-            ),
+            inner: OpaqueTyItem(OpaqueTy {
+                bounds: self.opaque_ty.bounds.clean(cx),
+                generics: self.opaque_ty.generics.clean(cx),
+            }),
         }
     }
 }
index d70446d2574980a51073cc51179d7c6738403b0a..bb6f449e3550d5768558f8185199351816e3fd91 100644 (file)
@@ -252,7 +252,7 @@ pub enum ItemEnum {
     FunctionItem(Function),
     ModuleItem(Module),
     TypedefItem(Typedef, bool /* is associated type */),
-    OpaqueTyItem(OpaqueTy, bool /* is associated type */),
+    OpaqueTyItem(OpaqueTy),
     StaticItem(Static),
     ConstantItem(Constant),
     TraitItem(Trait),
index 8b5ba7a239c5f75009de02706539db9a8f7021e3..afd1dc596427ff640dad0690b57f330047ab6a71 100644 (file)
@@ -1709,7 +1709,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache)
         clean::ConstantItem(ref c) => item_constant(buf, cx, item, c),
         clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache),
         clean::KeywordItem(_) => item_keyword(buf, cx, item),
-        clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e, cache),
+        clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e, cache),
         clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache),
         _ => {
             // We don't generate pages for any other type.
index 25dc7cdf129d5037a494425510a107d5df21ed85..9e449de0cf5acdf4357ea119e43b5132f2cd53cd 100644 (file)
@@ -1,6 +1,9 @@
 // revisions: rpass cfail
 
-trait Tr {
+trait Tr
+where
+    (Self::Arr,): Sized,
+{
     type Arr;
 
     const C: usize = 0;
index 62bf97a772ead783b641339a0236865277ddb875..c1421f20a0ba23da67f9e3203b958aa58bc4cd3c 100644 (file)
@@ -69,7 +69,7 @@ fn test() -> Option<Box<u32>> {
 
     bb5: {
         StorageDead(_9);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        _0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+        _0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:15: 9:20
                                          // + literal: Const { ty: fn(<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::Error) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
index 33245b65e8c42fba438f86608ae485eb9ecfcf0d..a811a2c178f170877fb65f05aa07c213605258ae 100644 (file)
@@ -29,7 +29,7 @@
               scope 8 {
 -                 debug v => _8;           // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
               }
           }
       }
index eb2521c8ba08ec7cac792ce5d74b0697e20304cf..b0cc3e88f35ac2bbe82087207dfc8b53b8e62d90 100644 (file)
@@ -25,7 +25,7 @@
               }
               scope 8 {
                   debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
               }
           }
       }
index 2af387a73b762e14c1dd8fbca7128e4773900803..12a6617cc5a278f89adda828952f1f0d94d887b3 100644 (file)
@@ -25,7 +25,7 @@
               }
               scope 8 {
                   debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
               }
           }
       }
index 6fa14f1e0d840fae389aeb1771a34d1f25d45adf..534836eff7b2d1875e60a1eed5cc82aca063bb7c 100644 (file)
@@ -29,7 +29,7 @@
               scope 8 {
 -                 debug v => _8;           // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
               }
           }
       }
index ceb5bfb19a133d41cd336fae934515f8bcfec51f..d2e37bf4e12ebcb10ece3686a3ac6b8c70f679fc 100644 (file)
@@ -24,7 +24,7 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
             }
             scope 8 {
                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15
+                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
             }
         }
     }
diff --git a/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs
new file mode 100644 (file)
index 0000000..49f1114
--- /dev/null
@@ -0,0 +1,16 @@
+// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`.
+
+//check-pass
+
+trait Op
+where
+    Self::Output: Copy,
+{
+    type Output;
+}
+
+fn duplicate<T: Op>(x: T::Output) -> (T::Output, T::Output) {
+    (x, x)
+}
+
+fn main() {}
index 498a555c441b8f19312a0aad3fc74de94544022b..73b23da5bcb66528d55385ef3179ca718852de42 100644 (file)
@@ -12,7 +12,9 @@
 
 fn main() {}
 
-trait Bar { type Assoc; }
+trait Bar {
+    type Assoc;
+}
 
 trait Thing {
     type Out;
@@ -20,11 +22,14 @@ trait Thing {
 }
 
 struct AssocNoCopy;
-impl Bar for AssocNoCopy { type Assoc = String; }
+impl Bar for AssocNoCopy {
+    type Assoc = String;
+}
 
 impl Thing for AssocNoCopy {
     type Out = Box<dyn Bar<Assoc: Copy>>;
     //~^ ERROR the trait bound `String: Copy` is not satisfied
+    //~| ERROR the trait bound `String: Copy` is not satisfied
 
     fn func() -> Self::Out {
         Box::new(AssocNoCopy)
index 5236f0efa869ecfb66da40b1d9ae5cfab7ecaf00..414d74d4786d97ce6d2da284b35b21a023ca975d 100644 (file)
@@ -1,11 +1,15 @@
 error[E0277]: the trait bound `String: Copy` is not satisfied
-  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28
+  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
    |
 LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
    |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28
    |
-   = note: the return type of a function must have a statically known size
+LL |     type Out = Box<dyn Bar<Assoc: Copy>>;
+   |                            ^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 556d8900d1a2e88369c9bf4d6cd281c1199fbf06..d180de9be3bf310896f4f65b601240a691ebb9da 100644 (file)
@@ -6,40 +6,49 @@
 use std::fmt::Debug;
 use std::iter::Once;
 
-trait Lam<Binder> { type App; }
+trait Lam<Binder> {
+    type App;
+}
 
 #[derive(Clone)]
 struct L1;
-impl<'a> Lam<&'a u8> for L1 { type App = u8; }
+impl<'a> Lam<&'a u8> for L1 {
+    type App = u8;
+}
 
 #[derive(Clone)]
 struct L2;
-impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; }
+impl<'a, 'b> Lam<&'a &'b u8> for L2 {
+    type App = u8;
+}
 
 trait Case1 {
-    type C: Clone + Iterator<Item:
-        Send + Iterator<Item:
-            for<'a> Lam<&'a u8, App:
-                Debug
-            >
-        > + Sync>;
+    type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+    //~^ ERROR `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+    //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+    //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
 }
 
 pub struct S1;
 impl Case1 for S1 {
-//~^ ERROR `<L1 as Lam<&'a u8>>::App` doesn't implement `Debug` [E0277]
     type C = Once<Once<L1>>;
 }
 
 fn assume_case1<T: Case1>() {
-//~^ ERROR `<_ as Lam<&'a u8>>::App` doesn't implement `Debug` [E0277]
-//~| ERROR `<<T as Case1>::C as Iterator>::Item` is not an iterator [E0277]
-//~| ERROR `<<T as Case1>::C as Iterator>::Item` cannot be sent between threads safely [E0277]
-//~| ERROR `<<T as Case1>::C as Iterator>::Item` cannot be shared between threads safely [E0277]
-    fn assert_a<_0, A>() where A: Iterator<Item = _0>, _0: Debug {}
+    fn assert_a<_0, A>()
+    where
+        A: Iterator<Item = _0>,
+        _0: Debug,
+    {
+    }
     assert_a::<_, T::A>();
 
-    fn assert_b<_0, B>() where B: Iterator<Item = _0>, _0: 'static {}
+    fn assert_b<_0, B>()
+    where
+        B: Iterator<Item = _0>,
+        _0: 'static,
+    {
+    }
     assert_b::<_, T::B>();
 
     fn assert_c<_0, _1, _2, C>()
@@ -48,7 +57,8 @@ fn assert_c<_0, _1, _2, C>()
         _2: Send + Iterator<Item = _1>,
         _1: for<'a> Lam<&'a u8, App = _0>,
         _0: Debug,
-    {}
+    {
+    }
     assert_c::<_, _, _, T::C>();
 }
 
index 49b5e7fbb89a972f55ba334c535274d24e8fd3bf..e68b5b342a40c825bb146f2a96abd2bf0403eb7e 100644 (file)
@@ -1,79 +1,49 @@
-error[E0277]: `<L1 as Lam<&'a u8>>::App` doesn't implement `Debug`
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:29:6
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:5
    |
-LL | trait Case1 {
-   |       ----- required by a bound in this
-...
-LL |                 Debug
-   |                 ----- required by this bound in `Case1`
-...
-LL | impl Case1 for S1 {
-   |      ^^^^^ `<L1 as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator
    |
-   = help: the trait `for<'a> Debug` is not implemented for `<L1 as Lam<&'a u8>>::App`
-
-error[E0277]: `<<T as Case1>::C as Iterator>::Item` is not an iterator
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
-   |
-LL | fn assume_case1<T: Case1>() {
-   |                    ^^^^^ `<<T as Case1>::C as Iterator>::Item` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `<<T as Case1>::C as Iterator>::Item`
+   = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
 help: consider further restricting the associated type
    |
-LL | fn assume_case1<T: Case1>() where <<T as Case1>::C as Iterator>::Item: Iterator {
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: `<<T as Case1>::C as Iterator>::Item` cannot be sent between threads safely
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36
+   |
+LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+   |                                    ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+   | 
+  ::: $SRC_DIR/core/src/marker.rs:LL:COL
    |
-LL | trait Case1 {
-   |       ----- required by a bound in this
-LL |     type C: Clone + Iterator<Item:
-LL |         Send + Iterator<Item:
-   |         ---- required by this bound in `Case1`
-...
-LL | fn assume_case1<T: Case1>() {
-   |                    ^^^^^ `<<T as Case1>::C as Iterator>::Item` cannot be sent between threads safely
+LL | pub unsafe auto trait Send {
+   | -------------------------- required by this bound in `Send`
    |
-   = help: the trait `Send` is not implemented for `<<T as Case1>::C as Iterator>::Item`
+   = help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
 help: consider further restricting the associated type
    |
-LL | fn assume_case1<T: Case1>() where <<T as Case1>::C as Iterator>::Item: Send {
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: `<<T as Case1>::C as Iterator>::Item` cannot be shared between threads safely
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93
    |
-LL | trait Case1 {
-   |       ----- required by a bound in this
-...
-LL |         > + Sync>;
-   |             ---- required by this bound in `Case1`
-...
-LL | fn assume_case1<T: Case1>() {
-   |                    ^^^^^ `<<T as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+   |                                                                                             ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
+   | 
+  ::: $SRC_DIR/core/src/marker.rs:LL:COL
    |
-   = help: the trait `Sync` is not implemented for `<<T as Case1>::C as Iterator>::Item`
-help: consider further restricting the associated type
-   |
-LL | fn assume_case1<T: Case1>() where <<T as Case1>::C as Iterator>::Item: Sync {
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `Debug`
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20
+LL | pub unsafe auto trait Sync {
+   | -------------------------- required by this bound in `Sync`
    |
-LL | trait Case1 {
-   |       ----- required by a bound in this
-...
-LL |                 Debug
-   |                 ----- required by this bound in `Case1`
-...
-LL | fn assume_case1<T: Case1>() {
-   |                    ^^^^^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   = help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
+help: consider further restricting the associated type
    |
-   = help: the trait `for<'a> Debug` is not implemented for `<_ as Lam<&'a u8>>::App`
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index ceca54b7cd75fd0c6dadc85ef7c66e30b6ab19d5..23be735010bf3374d169fcd18944533ee1272b7a 100644 (file)
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(associated_type_bounds)]
 
 use std::fmt::Debug;
@@ -18,6 +16,7 @@
 
 trait Case1 {
     type A: Iterator<Item: Debug>;
+    //~^ ERROR `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
 
     type B: Iterator<Item: 'static>;
 }
@@ -30,7 +29,11 @@ impl Case1 for S1 {
 
 // Ensure we don't have opaque `impl Trait` desugaring:
 
+// What is this supposed to mean? Rustc currently lowers `: Default` in the
+// bounds of `Out`, but trait selection can't find the bound since it applies
+// to a type other than `Self::Out`.
 pub trait Foo { type Out: Baz<Assoc: Default>; }
+//~^ ERROR trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied
 pub trait Baz { type Assoc; }
 
 #[derive(Default)]
diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr
new file mode 100644 (file)
index 0000000..919b186
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0277]: `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug`
+  --> $DIR/bounds-on-assoc-in-trait.rs:18:28
+   |
+LL |     type A: Iterator<Item: Debug>;
+   |                            ^^^^^ `<<Self as Case1>::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   | 
+  ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+LL | pub trait Debug {
+   | --------------- required by this bound in `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `<<Self as Case1>::A as Iterator>::Item`
+help: consider further restricting the associated type
+   |
+LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied
+  --> $DIR/bounds-on-assoc-in-trait.rs:35:38
+   |
+LL | pub trait Foo { type Out: Baz<Assoc: Default>; }
+   |                                      ^^^^^^^ the trait `Default` is not implemented for `<<Self as Foo>::Out as Baz>::Assoc`
+   | 
+  ::: $SRC_DIR/core/src/default.rs:LL:COL
+   |
+LL | pub trait Default: Sized {
+   | ------------------------ required by this bound in `Default`
+   |
+help: consider further restricting the associated type
+   |
+LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; }
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 77cd88e524f5ff8522dbfff43037caa563ee724f..de2876d6b60b8bcdb1ce410d2473b63f9d8825ae 100644 (file)
@@ -511,30 +511,6 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  |
    |                                  `Item` bound here first
 
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:145:43
-   |
-LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
-   |                               ----------  ^^^^^^^^^^ re-bound here
-   |                               |
-   |                               `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:147:43
-   |
-LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
-   |                               ----------  ^^^^^^^^^^ re-bound here
-   |                               |
-   |                               `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
-  --> $DIR/duplicate.rs:149:46
-   |
-LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
-   |                               -------------  ^^^^^^^^^^^^^ re-bound here
-   |                               |
-   |                               `Item` bound here first
-
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:152:40
    |
@@ -559,6 +535,30 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            |
    |                            `Item` bound here first
 
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+  --> $DIR/duplicate.rs:145:43
+   |
+LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
+   |                               ----------  ^^^^^^^^^^ re-bound here
+   |                               |
+   |                               `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+  --> $DIR/duplicate.rs:147:43
+   |
+LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
+   |                               ----------  ^^^^^^^^^^ re-bound here
+   |                               |
+   |                               `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
+  --> $DIR/duplicate.rs:149:46
+   |
+LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
+   |                               -------------  ^^^^^^^^^^^^^ re-bound here
+   |                               |
+   |                               `Item` bound here first
+
 error: aborting due to 69 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0719`.
diff --git a/src/test/ui/associated-types/associate-type-bound-normalization.rs b/src/test/ui/associated-types/associate-type-bound-normalization.rs
new file mode 100644 (file)
index 0000000..db09297
--- /dev/null
@@ -0,0 +1,25 @@
+// Make sure that we normalize bounds on associated types before checking them
+// as candidates.
+
+// check-pass
+
+trait Mul<T> {
+    type Output;
+}
+
+trait Matrix: Mul<<Self as Matrix>::Row, Output = ()> {
+    type Row;
+
+    type Transpose: Matrix<Row = Self::Row>;
+}
+
+fn is_mul<S, T: Mul<S, Output = ()>>() {}
+
+fn f<T: Matrix>() {
+    // The unnormalized bound on `T::Transpose` is
+    // `Mul<<T::Transpose as Matrix>::Row` which has to be normalized to be
+    // equal to `T::Row`.
+    is_mul::<T::Row, T::Transpose>();
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-bound-ambiguity.rs b/src/test/ui/associated-types/associated-types-bound-ambiguity.rs
new file mode 100644 (file)
index 0000000..9f179b6
--- /dev/null
@@ -0,0 +1,23 @@
+// Make sure that if there are multiple applicable bounds on a projection, we
+// consider them ambiguous. In this test we are initially trying to solve
+// `Self::Repr: From<_>`, which is ambiguous until we later infer `_` to
+// `{integer}`.
+
+// check-pass
+
+trait PrimeField: Sized {
+    type Repr: From<u64> + From<Self>;
+    type Repr2: From<Self> + From<u64>;
+
+    fn method() {
+        Self::Repr::from(10);
+        Self::Repr2::from(10);
+    }
+}
+
+fn function<T: PrimeField>() {
+    T::Repr::from(10);
+    T::Repr2::from(10);
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs b/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs
new file mode 100644 (file)
index 0000000..353f82e
--- /dev/null
@@ -0,0 +1,16 @@
+// Check that if we have multiple applicable projection bounds we pick one (for
+// backwards compatibility reasons).
+
+// check-pass
+use std::ops::Mul;
+
+trait A {
+    type V;
+    type U: Mul<Self::V, Output = ()> + Mul<(), Output = ()>;
+}
+
+fn g<T: A<V = ()>>() {
+    let y: <T::U as Mul<()>>::Output = ();
+}
+
+fn main() {}
index 2914a7f868b2b2891fab601449013c178952007d..9d084203e3a8664c3962dedb90c85445bc1d1555 100644 (file)
@@ -1,11 +1,14 @@
-error[E0284]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/associated-types-unconstrained.rs:14:20
    |
+LL |     fn bar() -> isize;
+   |     ------------------ required by `Foo::bar`
+...
 LL |     let x: isize = Foo::bar();
    |                    ^^^^^^^^ cannot infer type
    |
-   = note: cannot satisfy `<_ as Foo>::A == _`
+   = note: cannot satisfy `_: Foo`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
index fa75f6bc152284e73230c2761f7f24cffd3cb47f..afb2b3df716ebda7e0b2828b9518dcfcbae60a06 100644 (file)
@@ -6,11 +6,8 @@ trait Tr {
     type B = Self::A;
 }
 
-// ...but is an error in any impl that doesn't override at least one of the defaults
 impl Tr for () {}
-//~^ ERROR overflow evaluating the requirement
 
-// As soon as at least one is redefined, it works:
 impl Tr for u8 {
     type A = u8;
 }
@@ -24,16 +21,14 @@ impl Tr for u32 {
     type B = u8;
 }
 
-// ...but only if this actually breaks the cycle
+// ...but not in an impl that redefines one of the types.
 impl Tr for bool {
-    //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
     type A = Box<Self::B>;
     //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
 }
 // (the error is shown twice for some reason)
 
 impl Tr for usize {
-    //~^ ERROR type mismatch resolving `<usize as Tr>::B == _`
     type B = &'static Self::A;
     //~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
 }
index 0aea30b11126b944f0896ed89e78a00f81f0756f..ae7150d47ca999e0921b6efc688d8109a3b96bd8 100644 (file)
@@ -1,34 +1,15 @@
-error[E0275]: overflow evaluating the requirement `<() as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:10:6
-   |
-LL | impl Tr for () {}
-   |      ^^
-
-error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:28:6
-   |
-LL | impl Tr for bool {
-   |      ^^ cyclic type of infinite size
-
-error[E0271]: type mismatch resolving `<usize as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:35:6
-   |
-LL | impl Tr for usize {
-   |      ^^ cyclic type of infinite size
-
 error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:30:5
+  --> $DIR/defaults-cyclic-fail-1.rs:26:5
    |
 LL |     type A = Box<Self::B>;
    |     ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
 error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:37:5
+  --> $DIR/defaults-cyclic-fail-1.rs:32:5
    |
 LL |     type B = &'static Self::A;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0271, E0275.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0271`.
index edcd310908aa4b2fd28c9e7b5dde2e1688b8f331..ba4bb0d5a296bbc7fed770e052082ab0d3f4440c 100644 (file)
@@ -8,11 +8,8 @@ trait Tr {
     type B = Box<Self::A>;
 }
 
-// ...but is an error in any impl that doesn't override at least one of the defaults
 impl Tr for () {}
-//~^ ERROR type mismatch resolving `<() as Tr>::B == _`
 
-// As soon as at least one is redefined, it works:
 impl Tr for u8 {
     type A = u8;
 }
@@ -26,16 +23,13 @@ impl Tr for u32 {
     type B = u8;
 }
 
-// ...but only if this actually breaks the cycle
 impl Tr for bool {
-    //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
     type A = Box<Self::B>;
     //~^ ERROR type mismatch resolving `<bool as Tr>::B == _`
 }
 // (the error is shown twice for some reason)
 
 impl Tr for usize {
-    //~^ ERROR type mismatch resolving `<usize as Tr>::B == _`
     type B = &'static Self::A;
     //~^ ERROR type mismatch resolving `<usize as Tr>::A == _`
 }
index f39021c30edc1d4fd6ac5fc9432e07bb4c47811c..0dfbac2dec5d5d4a0576e43708b029409413b0db 100644 (file)
@@ -1,33 +1,15 @@
-error[E0271]: type mismatch resolving `<() as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:12:6
-   |
-LL | impl Tr for () {}
-   |      ^^ cyclic type of infinite size
-
-error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:30:6
-   |
-LL | impl Tr for bool {
-   |      ^^ cyclic type of infinite size
-
-error[E0271]: type mismatch resolving `<usize as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:37:6
-   |
-LL | impl Tr for usize {
-   |      ^^ cyclic type of infinite size
-
 error[E0271]: type mismatch resolving `<bool as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:32:5
+  --> $DIR/defaults-cyclic-fail-2.rs:27:5
    |
 LL |     type A = Box<Self::B>;
    |     ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
 error[E0271]: type mismatch resolving `<usize as Tr>::A == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:39:5
+  --> $DIR/defaults-cyclic-fail-2.rs:33:5
    |
 LL |     type B = &'static Self::A;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
 
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
index 30c2555df8bb924c620090723f5b67edc020bbc1..504c957d98753f377e5764171ce3bf3e0dceb382 100644 (file)
@@ -1,10 +1,8 @@
 //! Checks that associated type defaults are properly validated.
 //!
 //! This means:
-//! * Default types are wfchecked
 //! * Default types are checked against where clauses on the assoc. type
-//!   (eg. `type Assoc: Clone = NotClone`), and also against where clauses on
-//!   the trait itself when possible
+//!   (eg. `type Assoc: Clone = NotClone`)
 
 #![feature(associated_type_defaults)]
 
@@ -17,15 +15,12 @@ trait Tr {
 }
 
 // Where-clauses defined on the trait must also be considered
-trait Tr2 where Self::Ty: Clone {
-    //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
+trait Tr2
+where
+    Self::Ty: Clone,
+{
     type Ty = NotClone;
-}
-
-// Independent of where-clauses (there are none here), default types must always be wf
-trait Tr3 {
-    type Ty = Vec<[u8]>;
-    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+    //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
 }
 
 // Involved type parameters must fulfill all bounds required by defaults that mention them
@@ -43,7 +38,7 @@ trait Bar: Sized {
 trait IsU8<T> {}
 impl<T> IsU8<u8> for T {}
 
-// Test that mentioning the assoc. type inside where clauses works
+// Test that mentioning the assoc. type inside where clauses is not allowed
 trait C where
     Vec<Self::Assoc>: Clone,
     Self::Assoc: IsU8<Self::Assoc>,
@@ -55,13 +50,11 @@ trait C where
 // Test that we get all expected errors if that default is unsuitable
 trait D where
     Vec<Self::Assoc>: Clone,
-    //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
     Self::Assoc: IsU8<Self::Assoc>,
-    //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
     bool: IsU8<Self::Assoc>,
-    //~^ ERROR the trait bound `bool: IsU8<NotClone>` is not satisfied
 {
     type Assoc = NotClone;
+    //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
 }
 
 // Test behavior of the check when defaults refer to other defaults:
@@ -85,18 +78,20 @@ trait Foo25<T: Clone> {
 
 // Adding the `Baz: Clone` bound isn't enough since the default is type
 // parameter `T`, which also might not be `Clone`.
-trait Foo3<T> where
+trait Foo3<T>
+where
     Self::Bar: Clone,
     Self::Baz: Clone,
-    //~^ ERROR the trait bound `T: Clone` is not satisfied
 {
     type Bar = Vec<Self::Baz>;
     type Baz = T;
+    //~^ ERROR the trait bound `T: Clone` is not satisfied
 }
 
 // This one finally works, with `Clone` bounds on all assoc. types and the type
 // parameter.
-trait Foo4<T> where
+trait Foo4<T>
+where
     T: Clone,
 {
     type Bar: Clone = Vec<Self::Baz>;
index c2ad4c5824ea9d65463fae93bdecb5f8e9b30564..274d09fd09c867baa47ec605af44adc05d68edc1 100644 (file)
@@ -1,27 +1,32 @@
 error[E0277]: the trait bound `NotClone: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:15:14
+  --> $DIR/defaults-suitability.rs:13:5
    |
-LL | trait Tr {
-   | -------- required by `Tr`
 LL |     type Ty: Clone = NotClone;
-   |              ^^^^^ the trait `Clone` is not implemented for `NotClone`
+   |     ^^^^^^^^^-----^^^^^^^^^^^^
+   |     |        |
+   |     |        required by this bound in `Tr::Ty`
+   |     the trait `Clone` is not implemented for `NotClone`
 
 error[E0277]: the trait bound `NotClone: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:20:27
-   |
-LL | trait Tr2 where Self::Ty: Clone {
-   | --------------------------^^^^^
-   | |                         |
-   | |                         the trait `Clone` is not implemented for `NotClone`
-   | required by `Tr2`
+  --> $DIR/defaults-suitability.rs:22:5
+   |
+LL |     Self::Ty: Clone,
+   |               ----- required by this bound in `Tr2::Ty`
+LL | {
+LL |     type Ty = NotClone;
+   |     ^^^^^--^^^^^^^^^^^^
+   |     |    |
+   |     |    required by a bound in this
+   |     the trait `Clone` is not implemented for `NotClone`
 
 error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:33:15
+  --> $DIR/defaults-suitability.rs:28:5
    |
-LL | trait Foo<T> {
-   | ------------ required by `Foo`
 LL |     type Bar: Clone = Vec<T>;
-   |               ^^^^^ the trait `Clone` is not implemented for `T`
+   |     ^^^^^^^^^^-----^^^^^^^^^^
+   |     |         |
+   |     |         required by this bound in `Foo::Bar`
+   |     the trait `Clone` is not implemented for `T`
    |
    = note: required because of the requirements on the impl of `Clone` for `Vec<T>`
 help: consider restricting type parameter `T`
@@ -30,64 +35,34 @@ LL | trait Foo<T: Clone> {
    |            ^^^^^^^
 
 error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
-  --> $DIR/defaults-suitability.rs:39:17
+  --> $DIR/defaults-suitability.rs:34:5
    |
-LL | trait Bar: Sized {
-   | ---------------- required by `Bar`
-LL |     // `(): Foo<Self>` might hold for some possible impls but not all.
 LL |     type Assoc: Foo<Self> = ();
-   |                 ^^^^^^^^^ the trait `Foo<Self>` is not implemented for `()`
+   |     ^^^^^^^^^^^^---------^^^^^^
+   |     |           |
+   |     |           required by this bound in `Bar::Assoc`
+   |     the trait `Foo<Self>` is not implemented for `()`
 
 error[E0277]: the trait bound `NotClone: IsU8<NotClone>` is not satisfied
-  --> $DIR/defaults-suitability.rs:59:18
-   |
-LL | / trait D where
-LL | |     Vec<Self::Assoc>: Clone,
-LL | |
-LL | |     Self::Assoc: IsU8<Self::Assoc>,
-   | |                  ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `NotClone`
-...  |
-LL | |     type Assoc = NotClone;
-LL | | }
-   | |_- required by `D`
-
-error[E0277]: the trait bound `bool: IsU8<NotClone>` is not satisfied
-  --> $DIR/defaults-suitability.rs:61:11
-   |
-LL | / trait D where
-LL | |     Vec<Self::Assoc>: Clone,
-LL | |
-LL | |     Self::Assoc: IsU8<Self::Assoc>,
-LL | |
-LL | |     bool: IsU8<Self::Assoc>,
-   | |           ^^^^^^^^^^^^^^^^^ the trait `IsU8<NotClone>` is not implemented for `bool`
-...  |
-LL | |     type Assoc = NotClone;
-LL | | }
-   | |_- required by `D`
-
-error[E0277]: the trait bound `NotClone: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:57:23
-   |
-LL | / trait D where
-LL | |     Vec<Self::Assoc>: Clone,
-   | |                       ^^^^^ the trait `Clone` is not implemented for `NotClone`
-LL | |
-LL | |     Self::Assoc: IsU8<Self::Assoc>,
-...  |
-LL | |     type Assoc = NotClone;
-LL | | }
-   | |_- required by `D`
-   |
-   = note: required because of the requirements on the impl of `Clone` for `Vec<NotClone>`
+  --> $DIR/defaults-suitability.rs:56:5
+   |
+LL |     Self::Assoc: IsU8<Self::Assoc>,
+   |                  ----------------- required by this bound in `D::Assoc`
+...
+LL |     type Assoc = NotClone;
+   |     ^^^^^-----^^^^^^^^^^^^
+   |     |    |
+   |     |    required by a bound in this
+   |     the trait `IsU8<NotClone>` is not implemented for `NotClone`
 
 error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:72:15
+  --> $DIR/defaults-suitability.rs:65:5
    |
-LL | trait Foo2<T> {
-   | ------------- required by `Foo2`
 LL |     type Bar: Clone = Vec<Self::Baz>;
-   |               ^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
+   |     ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^
+   |     |         |
+   |     |         required by this bound in `Foo2::Bar`
+   |     the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
    |
    = note: required because of the requirements on the impl of `Clone` for `Vec<<Self as Foo2<T>>::Baz>`
 help: consider further restricting the associated type
@@ -96,12 +71,13 @@ LL | trait Foo2<T> where <Self as Foo2<T>>::Baz: Clone {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:81:15
+  --> $DIR/defaults-suitability.rs:74:5
    |
-LL | trait Foo25<T: Clone> {
-   | --------------------- required by `Foo25`
 LL |     type Bar: Clone = Vec<Self::Baz>;
-   |               ^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
+   |     ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^
+   |     |         |
+   |     |         required by this bound in `Foo25::Bar`
+   |     the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
    |
    = note: required because of the requirements on the impl of `Clone` for `Vec<<Self as Foo25<T>>::Baz>`
 help: consider further restricting the associated type
@@ -110,36 +86,22 @@ LL | trait Foo25<T: Clone> where <Self as Foo25<T>>::Baz: Clone {
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/defaults-suitability.rs:90:16
-   |
-LL | / trait Foo3<T> where
-LL | |     Self::Bar: Clone,
-LL | |     Self::Baz: Clone,
-   | |                ^^^^^ the trait `Clone` is not implemented for `T`
-LL | |
-...  |
-LL | |     type Baz = T;
-LL | | }
-   | |_- required by `Foo3`
+  --> $DIR/defaults-suitability.rs:87:5
+   |
+LL |     Self::Baz: Clone,
+   |                ----- required by this bound in `Foo3::Baz`
+...
+LL |     type Baz = T;
+   |     ^^^^^---^^^^^
+   |     |    |
+   |     |    required by a bound in this
+   |     the trait `Clone` is not implemented for `T`
    |
 help: consider further restricting type parameter `T`
    |
 LL |     Self::Baz: Clone, T: Clone
    |                     ^^^^^^^^^^
 
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/defaults-suitability.rs:27:5
-   |
-LL |     type Ty = Vec<[u8]>;
-   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   | 
-  ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
-   |
-LL | pub struct Vec<T> {
-   |                - required by this bound in `Vec`
-   |
-   = help: the trait `Sized` is not implemented for `[u8]`
-
-error: aborting due to 11 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index f283d22b3c7eb9eecb0dbb5d64f3af45234fa52d..fa6a208b4f1baf287ab7e58c27d49b698e70d7a5 100644 (file)
 
 use std::{
     fmt::Display,
-    ops::{AddAssign, Deref}
+    ops::{AddAssign, Deref},
 };
 
-
 trait UncheckedCopy: Sized {
     // This Output is said to be Copy. Yet we default to Self
     // and it's accepted, not knowing if Self ineed is Copy
-    type Output: Copy
+    type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
     //~^ ERROR the trait bound `Self: Copy` is not satisfied
-    + Deref<Target = str>
-    //~^ ERROR the trait bound `Self: Deref` is not satisfied
-    + AddAssign<&'static str>
-    //~^ ERROR cannot add-assign `&'static str` to `Self`
-    + From<Self>
-    + Display = Self;
-    //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+    //~| ERROR the trait bound `Self: Deref` is not satisfied
+    //~| ERROR cannot add-assign `&'static str` to `Self`
+    //~| ERROR `Self` doesn't implement `std::fmt::Display`
 
     // We said the Output type was Copy, so we can Copy it freely!
     fn unchecked_copy(other: &Self::Output) -> Self::Output {
@@ -39,10 +34,6 @@ fn make_origin(s: Self) -> Self::Output {
 }
 
 impl<T> UncheckedCopy for T {}
-//~^ ERROR `T` doesn't implement `std::fmt::Display`
-//~| ERROR the trait bound `T: Deref` is not satisfied
-//~| ERROR cannot add-assign `&'static str` to `T`
-//~| ERROR the trait bound `T: Copy` is not satisfied
 
 fn bug<T: UncheckedCopy>(origin: T) {
     let origin = T::make_origin(origin);
index 29a7c2eab41d5d4a6679db3ac93e1cae19559df2..8e446cf051f477b8092bcf36806805869addb3bd 100644 (file)
-error[E0277]: the trait bound `Self: Copy` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:21:18
-   |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     type Output: Copy
-   |                  ^^^^ the trait `Copy` is not implemented for `Self`
-   |
-help: consider further restricting `Self`
-   |
-LL | trait UncheckedCopy: Sized + Copy {
-   |                            ^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `Self`
-  --> $DIR/defaults-unsound-62211-1.rs:25:7
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-1.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     + AddAssign<&'static str>
-   |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^
+   |     |                                                                                |
+   |     |                                                                                required by this bound in `UncheckedCopy::Output`
+   |     `Self` cannot be formatted with the default formatter
    |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 help: consider further restricting `Self`
    |
-LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + std::fmt::Display {
+   |                            ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Self: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:23:7
+  --> $DIR/defaults-unsound-62211-1.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     + Deref<Target = str>
-   |       ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self`
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                   |
+   |     |                   required by this bound in `UncheckedCopy::Output`
+   |     the trait `Deref` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
 LL | trait UncheckedCopy: Sized + Deref {
    |                            ^^^^^^^
 
-error[E0277]: `Self` doesn't implement `std::fmt::Display`
-  --> $DIR/defaults-unsound-62211-1.rs:28:7
+error[E0277]: cannot add-assign `&'static str` to `Self`
+  --> $DIR/defaults-unsound-62211-1.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     + Display = Self;
-   |       ^^^^^^^ `Self` cannot be formatted with the default formatter
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                                         |
+   |     |                                         required by this bound in `UncheckedCopy::Output`
+   |     no implementation for `Self += &'static str`
    |
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 help: consider further restricting `Self`
    |
-LL | trait UncheckedCopy: Sized + std::fmt::Display {
-   |                            ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `std::fmt::Display`
-  --> $DIR/defaults-unsound-62211-1.rs:41:9
-   |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     + Display = Self;
-   |       ------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
-   |
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: std::fmt::Display> UncheckedCopy for T {}
-   |       ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `T: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:41:9
-   |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     + Deref<Target = str>
-   |       ------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: Deref> UncheckedCopy for T {}
-   |       ^^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `T`
-  --> $DIR/defaults-unsound-62211-1.rs:41:9
-   |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     + AddAssign<&'static str>
-   |       ----------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ no implementation for `T += &'static str`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: AddAssign<&'static str>> UncheckedCopy for T {}
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:41:9
+error[E0277]: the trait bound `Self: Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     type Output: Copy
-   |                  ---- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |            |
+   |     |            required by this bound in `UncheckedCopy::Output`
+   |     the trait `Copy` is not implemented for `Self`
    |
-help: consider restricting type parameter `T`
+help: consider further restricting `Self`
    |
-LL | impl<T: Copy> UncheckedCopy for T {}
-   |       ^^^^^^
+LL | trait UncheckedCopy: Sized + Copy {
+   |                            ^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 5518cda37087cd44aeb415d3479b77ccae4a99a0..c13ec776afe2bd15b79f6267900770e1f8556d29 100644 (file)
 
 use std::{
     fmt::Display,
-    ops::{AddAssign, Deref}
+    ops::{AddAssign, Deref},
 };
 
-
 trait UncheckedCopy: Sized {
     // This Output is said to be Copy. Yet we default to Self
     // and it's accepted, not knowing if Self ineed is Copy
-    type Output: Copy
+    type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
     //~^ ERROR the trait bound `Self: Copy` is not satisfied
-    + Deref<Target = str>
-    //~^ ERROR the trait bound `Self: Deref` is not satisfied
-    + AddAssign<&'static str>
-    //~^ ERROR cannot add-assign `&'static str` to `Self`
-    + From<Self>
-    + Display = Self;
-    //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+    //~| ERROR the trait bound `Self: Deref` is not satisfied
+    //~| ERROR cannot add-assign `&'static str` to `Self`
+    //~| ERROR `Self` doesn't implement `std::fmt::Display`
 
     // We said the Output type was Copy, so we can Copy it freely!
     fn unchecked_copy(other: &Self::Output) -> Self::Output {
@@ -39,10 +34,6 @@ fn make_origin(s: Self) -> Self::Output {
 }
 
 impl<T> UncheckedCopy for T {}
-//~^ ERROR `T` doesn't implement `std::fmt::Display`
-//~| ERROR the trait bound `T: Deref` is not satisfied
-//~| ERROR cannot add-assign `&'static str` to `T`
-//~| ERROR the trait bound `T: Copy` is not satisfied
 
 fn bug<T: UncheckedCopy>(origin: T) {
     let origin = T::make_origin(origin);
index 49c66093bf039d7b355f82892298d0cde608488f..93f4f497b38a2cf4ebbf3c9bbebb716d29ea71c8 100644 (file)
-error[E0277]: the trait bound `Self: Copy` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:21:18
-   |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     type Output: Copy
-   |                  ^^^^ the trait `Copy` is not implemented for `Self`
-   |
-help: consider further restricting `Self`
-   |
-LL | trait UncheckedCopy: Sized + Copy {
-   |                            ^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `Self`
-  --> $DIR/defaults-unsound-62211-2.rs:25:7
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-2.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     + AddAssign<&'static str>
-   |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^
+   |     |                                                                                |
+   |     |                                                                                required by this bound in `UncheckedCopy::Output`
+   |     `Self` cannot be formatted with the default formatter
    |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 help: consider further restricting `Self`
    |
-LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + std::fmt::Display {
+   |                            ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Self: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:23:7
+  --> $DIR/defaults-unsound-62211-2.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     + Deref<Target = str>
-   |       ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self`
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                   |
+   |     |                   required by this bound in `UncheckedCopy::Output`
+   |     the trait `Deref` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
 LL | trait UncheckedCopy: Sized + Deref {
    |                            ^^^^^^^
 
-error[E0277]: `Self` doesn't implement `std::fmt::Display`
-  --> $DIR/defaults-unsound-62211-2.rs:28:7
+error[E0277]: cannot add-assign `&'static str` to `Self`
+  --> $DIR/defaults-unsound-62211-2.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
-...
-LL |     + Display = Self;
-   |       ^^^^^^^ `Self` cannot be formatted with the default formatter
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                                         |
+   |     |                                         required by this bound in `UncheckedCopy::Output`
+   |     no implementation for `Self += &'static str`
    |
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 help: consider further restricting `Self`
    |
-LL | trait UncheckedCopy: Sized + std::fmt::Display {
-   |                            ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `std::fmt::Display`
-  --> $DIR/defaults-unsound-62211-2.rs:41:9
-   |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     + Display = Self;
-   |       ------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
-   |
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: std::fmt::Display> UncheckedCopy for T {}
-   |       ^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `T: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:41:9
-   |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     + Deref<Target = str>
-   |       ------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: Deref> UncheckedCopy for T {}
-   |       ^^^^^^^
-
-error[E0277]: cannot add-assign `&'static str` to `T`
-  --> $DIR/defaults-unsound-62211-2.rs:41:9
-   |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     + AddAssign<&'static str>
-   |       ----------------------- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ no implementation for `T += &'static str`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: AddAssign<&'static str>> UncheckedCopy for T {}
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:41:9
+error[E0277]: the trait bound `Self: Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:20:5
    |
-LL | trait UncheckedCopy: Sized {
-   |       ------------- required by a bound in this
-...
-LL |     type Output: Copy
-   |                  ---- required by this bound in `UncheckedCopy`
-...
-LL | impl<T> UncheckedCopy for T {}
-   |         ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |            |
+   |     |            required by this bound in `UncheckedCopy::Output`
+   |     the trait `Copy` is not implemented for `Self`
    |
-help: consider restricting type parameter `T`
+help: consider further restricting `Self`
    |
-LL | impl<T: Copy> UncheckedCopy for T {}
-   |       ^^^^^^
+LL | trait UncheckedCopy: Sized + Copy {
+   |                            ^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/defaults-wf.rs b/src/test/ui/associated-types/defaults-wf.rs
new file mode 100644 (file)
index 0000000..99b5125
--- /dev/null
@@ -0,0 +1,11 @@
+// Check that associated type defaults are wf checked.
+
+#![feature(associated_type_defaults)]
+
+// Default types must always be wf
+trait Tr3 {
+    type Ty = Vec<[u8]>;
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr
new file mode 100644 (file)
index 0000000..f9044c2
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/defaults-wf.rs:7:5
+   |
+LL |     type Ty = Vec<[u8]>;
+   |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   | 
+  ::: $SRC_DIR/alloc/src/vec.rs:LL:COL
+   |
+LL | pub struct Vec<T> {
+   |                - required by this bound in `Vec`
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 566e390a31e4820cd68b60192ba1d320f69cdad9..b0e9e33a6c38ecffeda0cbef786f32659c24878f 100644 (file)
@@ -9,7 +9,6 @@ LL | fn baz() -> impl Bar<Item = i32> {
    |
    = note: expected associated type `<impl Bar as Foo>::Item`
                          found type `i32`
-   = note: the return type of a function must have a statically known size
 help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
    |
 LL | fn bar() -> impl Bar<Item = i32> {
index 26f1183c6bd768e6ab18ea8671a98a2d62eecdf8..6a63b3e0936742df7ba2e727c15b1ec2442e463f 100644 (file)
@@ -4,12 +4,13 @@
 // type-checked.
 
 trait Foo<T: Default + ToString> {
-    type Out: Default + ToString + ?Sized = dyn ToString;  //~ error: not satisfied
+    type Out: Default + ToString + ?Sized = dyn ToString;  //~ ERROR not satisfied
 }
 
-impl Foo<u32> for () {}  //~ error: not satisfied
-impl Foo<u64> for () {}  //~ error: not satisfied
+impl Foo<u32> for () {}
+impl Foo<u64> for () {}
 
 fn main() {
     assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
+    //~^ ERROR no function or associated item named `default` found for trait object
 }
index 661730bcd757ace8e47333d2ea565fec0a1e4257..8d4ecac750268f82f31b1e8f1403037d0ea0d549 100644 (file)
@@ -1,33 +1,19 @@
 error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
-  --> $DIR/issue-43924.rs:7:15
+  --> $DIR/issue-43924.rs:7:5
    |
-LL | trait Foo<T: Default + ToString> {
-   | -------------------------------- required by `Foo`
 LL |     type Out: Default + ToString + ?Sized = dyn ToString;
-   |               ^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
+   |     ^^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |         |
+   |     |         required by this bound in `Foo::Out`
+   |     the trait `Default` is not implemented for `(dyn ToString + 'static)`
 
-error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
-  --> $DIR/issue-43924.rs:10:6
-   |
-LL | trait Foo<T: Default + ToString> {
-   |       --- required by a bound in this
-LL |     type Out: Default + ToString + ?Sized = dyn ToString;
-   |               ------- required by this bound in `Foo`
-...
-LL | impl Foo<u32> for () {}
-   |      ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
-
-error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
-  --> $DIR/issue-43924.rs:11:6
+error[E0599]: no function or associated item named `default` found for trait object `(dyn ToString + 'static)` in the current scope
+  --> $DIR/issue-43924.rs:14:39
    |
-LL | trait Foo<T: Default + ToString> {
-   |       --- required by a bound in this
-LL |     type Out: Default + ToString + ?Sized = dyn ToString;
-   |               ------- required by this bound in `Foo`
-...
-LL | impl Foo<u64> for () {}
-   |      ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
+LL |     assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
+   |                                       ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
index ddc0bf436f6d516bb39c0ee93356ad934755e635..16ae07687e2c7f355dbd56a02d022201e08db5b8 100644 (file)
@@ -1,10 +1,11 @@
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
   --> $DIR/issue-63593.rs:9:5
    |
-LL | trait MyTrait {
-   | ------------- required by `MyTrait`
 LL |     type This = Self;
-   |     ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |     ^^^^^^^^^^^^^^^^^
+   |     |
+   |     doesn't have a size known at compile-time
+   |     required by this bound in `MyTrait::This`
    |
 help: consider further restricting `Self`
    |
index 0ffd6cc2cf23008507ad17157a103caf62821e52..9345140558b079ba036890db7dea14cf5bdb7b21 100644 (file)
@@ -14,7 +14,6 @@ trait MPU {
 struct S;
 
 impl MPU for S { }
-//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
 
 trait MyWrite {
     fn my_write(&self, _: &dyn MyDisplay) { }
@@ -43,6 +42,7 @@ fn process_detail_fmt(&self, writer: &mut dyn MyWrite)
         // FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
         // depth=1),Unimplemented)
         let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
+        //~^ ERROR the trait bound `T: MyDisplay` is not satisfied
         closure(valref);
     }
 }
index 72f47df5d80e727b1be77f8bc4a323e49cafd671..f644eb5a1f47887b8060e5957ca4e674918605cf 100644 (file)
@@ -1,21 +1,20 @@
 error[E0277]: the trait bound `T: MyDisplay` is not satisfied
-  --> $DIR/issue-65774-1.rs:10:21
+  --> $DIR/issue-65774-1.rs:10:5
    |
-LL | trait MPU {
-   | --------- required by `MPU`
 LL |     type MpuConfig: MyDisplay = T;
-   |                     ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+   |     ^^^^^^^^^^^^^^^^---------^^^^^
+   |     |               |
+   |     |               required by this bound in `MPU::MpuConfig`
+   |     the trait `MyDisplay` is not implemented for `T`
 
 error[E0277]: the trait bound `T: MyDisplay` is not satisfied
-  --> $DIR/issue-65774-1.rs:16:6
+  --> $DIR/issue-65774-1.rs:44:76
    |
-LL | trait MPU {
-   |       --- required by a bound in this
-LL |     type MpuConfig: MyDisplay = T;
-   |                     --------- required by this bound in `MPU`
-...
-LL | impl MPU for S { }
-   |      ^^^ the trait `MyDisplay` is not implemented for `T`
+LL |         let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(&config);
+   |                                                                            ^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+   |
+   = note: required because of the requirements on the impl of `MyDisplay` for `&mut T`
+   = note: required for the cast to the object type `dyn MyDisplay`
 
 error: aborting due to 2 previous errors
 
index 31e203a81d3972bf00a5105c64cb2964d2c43421..171e0893b4719a570837dd78c84e672595a04154 100644 (file)
@@ -14,7 +14,6 @@ trait MPU {
 struct S;
 
 impl MPU for S { }
-//~^ ERROR the trait bound `T: MyDisplay` is not satisfied
 
 trait MyWrite {
     fn my_write(&self, _: &dyn MyDisplay) { }
@@ -38,6 +37,7 @@ fn process_detail_fmt(&self, writer: &mut dyn MyWrite)
         // // `Unimplemented` selecting `Binder(<T as MyDisplay>)` during codegen
         //
         writer.my_write(valref)
+        //~^ ERROR the trait bound `T: MyDisplay` is not satisfied
 
         // This one causes the ICE:
         // FulfillmentError(Obligation(predicate=Binder(TraitPredicate(<T as MyDisplay>)),
index aef70885af369d5afe50d676076b8824856d9dfe..572a9cf190952116463f1a238d6822e52c5442f9 100644 (file)
@@ -1,21 +1,19 @@
 error[E0277]: the trait bound `T: MyDisplay` is not satisfied
-  --> $DIR/issue-65774-2.rs:10:21
+  --> $DIR/issue-65774-2.rs:10:5
    |
-LL | trait MPU {
-   | --------- required by `MPU`
 LL |     type MpuConfig: MyDisplay = T;
-   |                     ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T`
+   |     ^^^^^^^^^^^^^^^^---------^^^^^
+   |     |               |
+   |     |               required by this bound in `MPU::MpuConfig`
+   |     the trait `MyDisplay` is not implemented for `T`
 
 error[E0277]: the trait bound `T: MyDisplay` is not satisfied
-  --> $DIR/issue-65774-2.rs:16:6
+  --> $DIR/issue-65774-2.rs:39:25
    |
-LL | trait MPU {
-   |       --- required by a bound in this
-LL |     type MpuConfig: MyDisplay = T;
-   |                     --------- required by this bound in `MPU`
-...
-LL | impl MPU for S { }
-   |      ^^^ the trait `MyDisplay` is not implemented for `T`
+LL |         writer.my_write(valref)
+   |                         ^^^^^^ the trait `MyDisplay` is not implemented for `T`
+   |
+   = note: required for the cast to the object type `dyn MyDisplay`
 
 error: aborting due to 2 previous errors
 
index ae63781d568a1bc8d669d244e05717a84933398e..94758250346d12329b81c0674d8115ec555a8d0c 100644 (file)
@@ -9,9 +9,10 @@ trait Bar2 {
 struct Foo;
 struct Foo2;
 
-impl Bar for Foo {  //~ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == char`
+impl Bar for Foo {
     type Ok = ();
     type Sibling = Foo2;
+    //~^ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == char`
 }
 impl Bar2 for Foo2 {
     type Ok = u32;
index 03a6565848dc3524717f6de4112eaf1fc5d4e78e..23fabbee1c5d4ba181d4c8465b7ccb46364f0d2e 100644 (file)
@@ -1,8 +1,11 @@
 error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == char`
-  --> $DIR/issue-72806.rs:12:6
+  --> $DIR/issue-72806.rs:14:5
    |
-LL | impl Bar for Foo {
-   |      ^^^ expected `u32`, found `char`
+LL |     type Sibling: Bar2<Ok=char>;
+   |                        ------- required by this bound in `Bar::Sibling`
+...
+LL |     type Sibling = Foo2;
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `char`, found `u32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/object-normalization.rs b/src/test/ui/associated-types/object-normalization.rs
new file mode 100644 (file)
index 0000000..1f93248
--- /dev/null
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+
+// Check that we normalize super predicates for object candidates.
+
+// check-pass
+
+use std::ops::Index;
+
+fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
+    // To prove
+    // `dyn SVec<Item = T, Output = T>: SVec`
+    // we need to show
+    // `dyn SVec<Item = T, Output = T> as Index>::Output == <dyn SVec<Item = T, Output = T> as SVec>::Item`
+    // which, with the current normalization strategy, has to be eagerly
+    // normalized to:
+    // `dyn SVec<Item = T, Output = T> as Index>::Output == T`.
+    let _ = s.len();
+}
+
+trait SVec: Index<usize, Output = <Self as SVec>::Item> {
+    type Item;
+
+    fn len(&self) -> usize;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/param-env-normalize-cycle.rs b/src/test/ui/associated-types/param-env-normalize-cycle.rs
new file mode 100644 (file)
index 0000000..12db595
--- /dev/null
@@ -0,0 +1,39 @@
+// Minimized case from typenum that didn't compile because:
+// - We tried to normalize the ParamEnv of the second impl
+// - This requires trying to normalize `GrEq<Self, Square<Square<U>>>`
+// - This requires proving `Square<Square<U>>: Sized` so that the first impl
+//   applies
+// - This requires Providing `Square<Square<U>>` is well-formed, so that we
+//   can use the `Sized` bound on `Mul::Output`
+// - This requires proving `Square<U>: Mul`
+// - But first we tried normalizing the whole obligation, including the
+//   ParamEnv, which leads to a cycle error.
+
+// check-pass
+
+trait PrivateSquareRoot {}
+
+pub trait Mul<Rhs = Self> {
+    type Output;
+}
+
+pub trait IsGreaterOrEqual<Rhs> {
+    type Output;
+}
+
+pub type Square<A> = <A as Mul>::Output;
+pub type GrEq<A, B> = <A as IsGreaterOrEqual<B>>::Output;
+
+impl<A, B> IsGreaterOrEqual<B> for A {
+    type Output = ();
+}
+
+impl<U> PrivateSquareRoot for U
+where
+    U: Mul,
+    Square<U>: Mul,
+    GrEq<Self, Square<Square<U>>>: Sized,
+{
+}
+
+fn main() {}
index 67b7c78071c378af04253c203f6e6b2fe652878e..4b3d6e9d6067f1a5842e54b026996656c44647f8 100644 (file)
@@ -8,7 +8,10 @@ impl Foo for () {
     type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
 }
 
-trait Baz where Self::Assoc: Bar {
+trait Baz
+where
+    Self::Assoc: Bar,
+{
     type Assoc;
 }
 
@@ -16,7 +19,10 @@ impl Baz for () {
     type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
 }
 
-trait Bat where <Self as Bat>::Assoc: Bar {
+trait Bat
+where
+    <Self as Bat>::Assoc: Bar,
+{
     type Assoc;
 }
 
index 3118a9c5352c351ca0105cdeaf6ac4059b5ebe26..b23030d7cb52b37b59bbb60e412328ab5cd6e736 100644 (file)
@@ -1,31 +1,35 @@
 error[E0277]: the trait bound `bool: Bar` is not satisfied
-  --> $DIR/point-at-type-on-obligation-failure-2.rs:8:18
+  --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
    |
-LL | trait Foo {
-   |       --- required by a bound in this
 LL |     type Assoc: Bar;
-   |                 --- required by this bound in `Foo`
+   |                 --- required by this bound in `Foo::Assoc`
 ...
 LL |     type Assoc = bool;
-   |                  ^^^^ the trait `Bar` is not implemented for `bool`
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
 
 error[E0277]: the trait bound `bool: Bar` is not satisfied
-  --> $DIR/point-at-type-on-obligation-failure-2.rs:16:18
+  --> $DIR/point-at-type-on-obligation-failure-2.rs:19:5
    |
-LL | trait Baz where Self::Assoc: Bar {
-   |                              --- required by this bound in `Baz`
+LL |     Self::Assoc: Bar,
+   |                  --- required by this bound in `Baz::Assoc`
+LL | {
+LL |     type Assoc;
+   |          ----- required by a bound in this
 ...
 LL |     type Assoc = bool;
-   |                  ^^^^ the trait `Bar` is not implemented for `bool`
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
 
 error[E0277]: the trait bound `bool: Bar` is not satisfied
-  --> $DIR/point-at-type-on-obligation-failure-2.rs:24:18
+  --> $DIR/point-at-type-on-obligation-failure-2.rs:30:5
    |
-LL | trait Bat where <Self as Bat>::Assoc: Bar {
-   |                                       --- required by this bound in `Bat`
+LL |     <Self as Bat>::Assoc: Bar,
+   |                           --- required by this bound in `Bat::Assoc`
+LL | {
+LL |     type Assoc;
+   |          ----- required by a bound in this
 ...
 LL |     type Assoc = bool;
-   |                  ^^^^ the trait `Bar` is not implemented for `bool`
+   |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
 
 error: aborting due to 3 previous errors
 
index dc43dbaf54b99b1669ff85137f5f2b80dfec5cb9..66666006887e6b2a84b82c54775efc1d3ddd6c11 100644 (file)
@@ -10,8 +10,9 @@ trait Bar2 {
 struct Foo2;
 
 impl Bar for Foo {
-    type Ok = ();  //~ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
+    type Ok = ();
     type Sibling = Foo2;
+    //~^ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
 }
 impl Bar2 for Foo2 {
     type Ok = u32;
index 818702b7afe2ab2e850e07be78e993aca59ceb17..7417a5aa3d43a4adeeb4540891901d532ad22680 100644 (file)
@@ -1,8 +1,11 @@
 error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
-  --> $DIR/point-at-type-on-obligation-failure.rs:13:15
+  --> $DIR/point-at-type-on-obligation-failure.rs:14:5
    |
-LL |     type Ok = ();
-   |               ^^ expected `u32`, found `()`
+LL |     type Sibling: Bar2<Ok=Self::Ok>;
+   |                        ----------- required by this bound in `Bar::Sibling`
+...
+LL |     type Sibling = Foo2;
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u32`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/wf-cycle-2.rs b/src/test/ui/associated-types/wf-cycle-2.rs
new file mode 100644 (file)
index 0000000..d7467ac
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+trait IntoIt {
+    type Item;
+}
+
+impl<I> IntoIt for I {
+    type Item = ();
+}
+
+trait BaseGraph
+where
+    <Self::VertexIter as IntoIt>::Item: Sized,
+{
+    type VertexIter: IntoIt;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/wf-cycle.rs b/src/test/ui/associated-types/wf-cycle.rs
new file mode 100644 (file)
index 0000000..cf65085
--- /dev/null
@@ -0,0 +1,13 @@
+// check-pass
+
+trait A {
+    type U: Copy;
+}
+
+trait B where
+    <Self::V as A>::U: Copy,
+{
+    type V: A;
+}
+
+fn main() {}
index d808a5939bbe79769a5bd4765359c2f8fd027cef..994bfd33ba42e37d2137b6035a29dee7cff67100 100644 (file)
@@ -3,12 +3,8 @@ error[E0277]: `()` is not a future
    |
 LL | fn get_future() -> impl Future<Output = ()> {
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
-LL |
-LL |     panic!()
-   |     -------- this returned value is of type `!`
    |
    = help: the trait `Future` is not implemented for `()`
-   = note: the return type of a function must have a statically known size
 
 error[E0698]: type inside `async fn` body must be known in this context
   --> $DIR/async-error-span.rs:13:9
index f1f1b2d4439ecffe301d90d1445b0b0572e7c73a..88ea7251eaf1f8f5edc55de827ad3ab49e015a57 100644 (file)
@@ -27,33 +27,18 @@ error[E0609]: no field `0` on type `impl Future`
    |
 LL |     let _: i32 = tuple().0;
    |                          ^
-   |
-help: consider awaiting before field access
-   |
-LL |     let _: i32 = tuple().await.0;
-   |                         ^^^^^^
 
 error[E0609]: no field `a` on type `impl Future`
   --> $DIR/issue-61076.rs:60:28
    |
 LL |     let _: i32 = struct_().a;
    |                            ^
-   |
-help: consider awaiting before field access
-   |
-LL |     let _: i32 = struct_().await.a;
-   |                           ^^^^^^
 
 error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope
   --> $DIR/issue-61076.rs:62:15
    |
 LL |     struct_().method();
    |               ^^^^^^ method not found in `impl Future`
-   |
-help: consider awaiting before this method call
-   |
-LL |     struct_().await.method();
-   |               ^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-61076.rs:69:9
@@ -66,10 +51,6 @@ LL |         Tuple(_) => {}
    |
    = note: expected opaque type `impl Future`
                    found struct `Tuple`
-help: consider awaiting on the future
-   |
-LL |     match tuple().await {
-   |                  ^^^^^^
 
 error: aborting due to 6 previous errors
 
index 440ea0a38e6b902c440ce7ce2a32d24d3da42a04..2d46dfb7269d1f93d3582e49e5ceeb556a5327a8 100644 (file)
@@ -1,17 +1,8 @@
 error: future cannot be sent between threads safely
   --> $DIR/issue-64130-4-async-move.rs:15:17
    |
-LL |   pub fn foo() -> impl Future + Send {
-   |                   ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
-...
-LL | /     async move {
-LL | |         match client.status() {
-LL | |             200 => {
-LL | |                 let _x = get().await;
-...  |
-LL | |         }
-LL | |     }
-   | |_____- this returned value is of type `impl Future`
+LL | pub fn foo() -> impl Future + Send {
+   |                 ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
 note: future is not `Send` as this value is used across an await
@@ -30,7 +21,6 @@ help: consider moving this into a `let` binding to create a shorter lived borrow
    |
 LL |         match client.status() {
    |               ^^^^^^^^^^^^^^^
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
 
index 78253042bee1c35eb4ace7a201f892bbf5d3a92e..832b736ad86424112888bff610d11007ab97c253 100644 (file)
@@ -1,11 +1,11 @@
 error[E0515]: cannot return value referencing local variable `s`
-  --> $DIR/issue-67765-async-diagnostic.rs:13:11
+  --> $DIR/issue-67765-async-diagnostic.rs:13:5
    |
 LL |     let b = &s[..];
    |              - `s` is borrowed here
 LL | 
 LL |     Err(b)?;
-   |           ^ returns a value referencing data owned by the current function
+   |     ^^^^^^^ returns a value referencing data owned by the current function
 
 error: aborting due to previous error
 
index 364194bea100e914c2d285a3a68a22976699d1f2..11fca2dd8ef4c53d464bcaa40a0259540c751b15 100644 (file)
@@ -3,16 +3,12 @@ error: future cannot be sent between threads safely
    |
 LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
-LL |
-LL |     async { (ty, ty1) }
-   |     ------------------- this returned value is of type `impl Future`
    |
 note: captured value is not `Send`
   --> $DIR/issue-70818.rs:6:18
    |
 LL |     async { (ty, ty1) }
    |                  ^^^ has type `U` which is not `Send`
-   = note: the return type of a function must have a statically known size
 help: consider restricting type parameter `U`
    |
 LL | fn foo<T: Send, U: Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
index 465eb10241ea20d9e38962bdc3474a094f3b9f84..66f57c2d11009fe1a2d4ea82520b5968b88a326e 100644 (file)
@@ -15,19 +15,6 @@ impl Foo for str { }
 // Implicit `T: Sized` bound.
 impl<T> Foo for Option<T> { }
 
-impl Bar for () {
-    type Item = i32;
-}
-
-impl<T> Bar for Option<T> {
-    type Item = Option<T>;
-}
-
-impl Bar for f32 {
-    type Item = f32;
-    //~^ ERROR the trait bound `f32: Foo` is not satisfied
-}
-
 trait Baz<U: ?Sized> where U: Foo { }
 
 impl Baz<i32> for i32 { }
index 4ca5ae472f20701a26c9e6e057956de24f21ea2e..24c7f0d82bdc8b4a3d40553f6b4728967303bb7d 100644 (file)
@@ -10,18 +10,7 @@ LL | impl Foo for str { }
    = help: the trait `Sized` is not implemented for `str`
 
 error[E0277]: the trait bound `f32: Foo` is not satisfied
-  --> $DIR/impl_wf.rs:27:17
-   |
-LL | trait Bar {
-   |       --- required by a bound in this
-LL |     type Item: Foo;
-   |                --- required by this bound in `Bar`
-...
-LL |     type Item = f32;
-   |                 ^^^ the trait `Foo` is not implemented for `f32`
-
-error[E0277]: the trait bound `f32: Foo` is not satisfied
-  --> $DIR/impl_wf.rs:35:6
+  --> $DIR/impl_wf.rs:22:6
    |
 LL | trait Baz<U: ?Sized> where U: Foo { }
    |                               --- required by this bound in `Baz`
@@ -29,6 +18,6 @@ LL | trait Baz<U: ?Sized> where U: Foo { }
 LL | impl Baz<f32> for f32 { }
    |      ^^^^^^^^ the trait `Foo` is not implemented for `f32`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/chalkify/impl_wf_2.rs b/src/test/ui/chalkify/impl_wf_2.rs
new file mode 100644 (file)
index 0000000..758a718
--- /dev/null
@@ -0,0 +1,33 @@
+// Split out of impl_wf.rs to work around rust aborting compilation early
+
+// compile-flags: -Z chalk
+
+trait Foo: Sized { }
+
+trait Bar {
+    type Item: Foo;
+}
+
+impl Foo for i32 { }
+
+// Implicit `T: Sized` bound.
+impl<T> Foo for Option<T> { }
+
+impl Bar for () {
+    type Item = i32;
+}
+
+impl<T> Bar for Option<T> {
+    type Item = Option<T>;
+}
+
+impl Bar for f32 {
+    type Item = f32;
+    //~^ ERROR the trait bound `f32: Foo` is not satisfied
+}
+
+trait Baz<U: ?Sized> where U: Foo { }
+
+impl Baz<i32> for i32 { }
+
+fn main() {}
diff --git a/src/test/ui/chalkify/impl_wf_2.stderr b/src/test/ui/chalkify/impl_wf_2.stderr
new file mode 100644 (file)
index 0000000..1da2144
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `f32: Foo` is not satisfied
+  --> $DIR/impl_wf_2.rs:25:5
+   |
+LL |     type Item: Foo;
+   |                --- required by this bound in `Bar::Item`
+...
+LL |     type Item = f32;
+   |     ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `f32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index af1e37ba867dee0327622dc1aec9f4c891e7d462..909c33f642d31f581e7fafb31ac18b0d04a3293b 100644 (file)
@@ -9,4 +9,5 @@ impl<'g> T<'g> for u32 {
 fn main() {
     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
     //~^ ERROR: type mismatch in closure arguments
+    //~| ERROR: size for values of type `<u32 as T<'_>>::V` cannot be known at compilation time
 }
index df0495cdc46434117236956f43d594ff8f79564d..200d411b51194d0f6796f5b6edac73954f4958f4 100644 (file)
@@ -9,6 +9,24 @@ LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
    |
    = note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)`
 
-error: aborting due to previous error
+error[E0277]: the size for values of type `<u32 as T<'_>>::V` cannot be known at compilation time
+  --> $DIR/issue-41366.rs:10:8
+   |
+LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+   |        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `<u32 as T<'_>>::V`
+   = help: unsized locals are gated as an unstable feature
+help: consider further restricting the associated type
+   |
+LL | fn main() where <u32 as T<'_>>::V: Sized {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     (&|&_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
+   |        ^
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0631`.
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
index 87058c3c29cf4ffe8ebf2f918cead24ff3d58c64..63a4df242f85f9897247a8b24d4101dd16eaeb35 100644 (file)
@@ -5,7 +5,6 @@ LL | fn will_ice(something: &u32) -> impl Iterator<Item = &u32> {
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `()`
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
 
index 9bce274027ee00186f26297d5012223a47ec96fb..38be85ff8201ed77a5840269e0acacd6ef558284 100644 (file)
@@ -14,6 +14,7 @@
 trait _Tr3 {
     type A: Iterator<Item: Copy>;
     //~^ ERROR associated type bounds are unstable
+    //~| ERROR the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
 
     type B: Iterator<Item: 'static>;
     //~^ ERROR associated type bounds are unstable
index 7f2704e1bc3715b314b28e557ad5535011452ed1..be5d35139b65c7db978aa46e1301d24f32071d65 100644 (file)
@@ -8,7 +8,7 @@ LL |     type A: Iterator<Item: Copy>;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:18:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:19:22
    |
 LL |     type B: Iterator<Item: 'static>;
    |                      ^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     type B: Iterator<Item: 'static>;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:22:20
+  --> $DIR/feature-gate-associated_type_bounds.rs:23:20
    |
 LL | struct _St1<T: Tr1<As1: Tr2>> {
    |                    ^^^^^^^^
@@ -26,7 +26,7 @@ LL | struct _St1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:29:18
+  --> $DIR/feature-gate-associated_type_bounds.rs:30:18
    |
 LL | enum _En1<T: Tr1<As1: Tr2>> {
    |                  ^^^^^^^^
@@ -35,7 +35,7 @@ LL | enum _En1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:36:19
+  --> $DIR/feature-gate-associated_type_bounds.rs:37:19
    |
 LL | union _Un1<T: Tr1<As1: Tr2>> {
    |                   ^^^^^^^^
@@ -44,7 +44,7 @@ LL | union _Un1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:43:37
+  --> $DIR/feature-gate-associated_type_bounds.rs:44:37
    |
 LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    |                                     ^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:46:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:47:22
    |
 LL | fn _apit(_: impl Tr1<As1: Copy>) {}
    |                      ^^^^^^^^^
@@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1<As1: Copy>) {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:48:26
+  --> $DIR/feature-gate-associated_type_bounds.rs:49:26
    |
 LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
    |                          ^^^^^^^^^
@@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:51:24
+  --> $DIR/feature-gate-associated_type_bounds.rs:52:24
    |
 LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
    |                        ^^^^^^^^^
@@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:54:31
+  --> $DIR/feature-gate-associated_type_bounds.rs:55:31
    |
 LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
    |                               ^^^^^^^^^
@@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:57:23
+  --> $DIR/feature-gate-associated_type_bounds.rs:58:23
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |                       ^^^^^^^^^
@@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:63:24
+  --> $DIR/feature-gate-associated_type_bounds.rs:64:24
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |                        ^^^^^^^^^
@@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:70:21
+  --> $DIR/feature-gate-associated_type_bounds.rs:71:21
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |                     ^^^^^^^^^
@@ -116,7 +116,7 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-associated_type_bounds.rs:57:14
+  --> $DIR/feature-gate-associated_type_bounds.rs:58:14
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |              ^^^^^^^^^^^^^^^^^^^
@@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-associated_type_bounds.rs:63:15
+  --> $DIR/feature-gate-associated_type_bounds.rs:64:15
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |               ^^^^^^^^^^^^^^^^^^^
@@ -132,14 +132,30 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-associated_type_bounds.rs:70:12
+  --> $DIR/feature-gate-associated_type_bounds.rs:71:12
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |            ^^^^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
-error: aborting due to 16 previous errors
+error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
+  --> $DIR/feature-gate-associated_type_bounds.rs:15:28
+   |
+LL |     type A: Iterator<Item: Copy>;
+   |                            ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item`
+   | 
+  ::: $SRC_DIR/core/src/marker.rs:LL:COL
+   |
+LL | pub trait Copy: Clone {
+   | --------------------- required by this bound in `Copy`
+   |
+help: consider further restricting the associated type
+   |
+LL | trait _Tr3 where <<Self as _Tr3>::A as Iterator>::Item: Copy {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 17 previous errors
 
-Some errors have detailed explanations: E0562, E0658.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0277, E0562, E0658.
+For more information about an error, try `rustc --explain E0277`.
index 17548d7b9e88c5551bf7a8b49b2cd132146c7eab..1d2be3657ffb2b16379768d9d3a1dfa0c593ddaa 100644 (file)
@@ -15,6 +15,7 @@ impl PointerFamily<u32> for Foo {
     //~^ ERROR generic associated types are unstable
     type Pointer2<U32> = Box<U32>;
     //~^ ERROR generic associated types are unstable
+    //~| ERROR the trait bound `U32: Clone` is not satisfied
 }
 
 trait Bar {
index 8499b1ab70f5d02a4bcbf7bef7d713ac5083064a..266008cc0def4c268b9d129945ef4bb2c8930422 100644 (file)
@@ -44,7 +44,7 @@ LL |     type Pointer2<U32> = Box<U32>;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: where clauses on associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:21:5
+  --> $DIR/feature-gate-generic_associated_types.rs:22:5
    |
 LL |     type Assoc where Self: Sized;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL |     type Assoc where Self: Sized;
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
 error[E0658]: where clauses on associated types are unstable
-  --> $DIR/feature-gate-generic_associated_types.rs:26:5
+  --> $DIR/feature-gate-generic_associated_types.rs:27:5
    |
 LL |     type Assoc where Self: Sized = Foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,6 +61,18 @@ LL |     type Assoc where Self: Sized = Foo;
    = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
    = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
 
-error: aborting due to 7 previous errors
+error[E0277]: the trait bound `U32: Clone` is not satisfied
+  --> $DIR/feature-gate-generic_associated_types.rs:16:5
+   |
+LL |     type Pointer2<U32> = Box<U32>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `U32`
+   |
+help: consider restricting type parameter `U32`
+   |
+LL |     type Pointer2<U32: Clone> = Box<U32>;
+   |                      ^^^^^^^
+
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0277, E0658.
+For more information about an error, try `rustc --explain E0277`.
index df66127c6041a87a4f199bf820d649895e058887..97a4ea53af583ce28e4b428721e5232495279c7a 100644 (file)
@@ -1,14 +1,16 @@
-// E0277 should point exclusively at line 14, not the entire for loop span
+// E0277 should point exclusively at line 6, not the entire for loop span
 
 fn main() {
     for c in "asdf" {
-    //~^ ERROR `&str` is not an iterator
-    //~| NOTE `&str` is not an iterator
-    //~| HELP the trait `Iterator` is not implemented for `&str`
-    //~| NOTE required by `into_iter`
-    //~| NOTE in this expansion of desugaring of `for` loop
-    //~| NOTE in this expansion of desugaring of `for` loop
-    //~| NOTE in this expansion of desugaring of `for` loop
+        //~^ ERROR `&str` is not an iterator
+        //~| NOTE `&str` is not an iterator
+        //~| HELP the trait `Iterator` is not implemented for `&str`
+        //~| NOTE required because of the requirements on the impl of `IntoIterator` for `&str`
+        //~| NOTE required by `into_iter`
+        //~| NOTE in this expansion of desugaring of `for` loop
+        //~| NOTE in this expansion of desugaring of `for` loop
+        //~| NOTE in this expansion of desugaring of `for` loop
+        //~| NOTE in this expansion of desugaring of `for` loop
         println!();
     }
 }
index b0f959ba0273c39fcab9e4c66c5dd458fdfafd9f..18e46e1d7ded73b0320982a3b6ef3e36def7e344 100644 (file)
@@ -5,6 +5,7 @@ LL |     for c in "asdf" {
    |              ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
    |
    = help: the trait `Iterator` is not implemented for `&str`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&str`
    = note: required by `into_iter`
 
 error: aborting due to previous error
index ccacd655a147df3132c5e56708134c6cc946c168..0d9409626897fb35ba12899221f743195f9e6529 100644 (file)
@@ -5,6 +5,7 @@ LL |     for x in bogus {
    |              ^^^^^ `MyStruct` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `MyStruct`
+   = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct`
    = note: required by `into_iter`
 
 error: aborting due to previous error
index 2bcf66dbeae279773b0ab9f35c28a8d217d890b6..8e3c2f67ed165aa126f24765f021fde607cbd862 100644 (file)
@@ -16,6 +16,11 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
    |
 LL |    Pin::new(&mut gen).resume(());
    |                       ^^^^^^ doesn't have a size known at compile-time
+   | 
+  ::: $SRC_DIR/core/src/ops/generator.rs:LL:COL
+   |
+LL | pub enum GeneratorState<Y, R> {
+   |                         - required by this bound in `GeneratorState`
    |
    = help: the trait `Sized` is not implemented for `str`
 
index 260fbb2ec7e6af34251716efebcbde13d86dae74..8f6f87f78de707e5d1d998b06d20f1f8085262c0 100644 (file)
@@ -15,7 +15,6 @@ LL | fn foo() -> impl Generator<Return = i32> {
    |
    = note: expected enum `std::result::Result<{integer}, _>`
               found type `i32`
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs
new file mode 100644 (file)
index 0000000..0e8e148
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(generic_associated_types)]
+
+use std::{future::Future, pin::Pin};
+
+pub trait Foo {
+    type Bar: AsRef<()>;
+    fn foo(&self) -> Pin<Box<dyn Future<Output = Self::Bar> + '_>>;
+}
diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.rs b/src/test/ui/generic-associated-types/cross-crate-bounds.rs
new file mode 100644 (file)
index 0000000..8934a07
--- /dev/null
@@ -0,0 +1,32 @@
+// regression test for #73816
+// We handled bounds differently when `feature(generic_associated_types)` was enabled
+
+// edition:2018
+// aux-build:foo_defn.rs
+
+extern crate foo_defn;
+
+use foo_defn::Foo;
+use std::{future::Future, pin::Pin};
+
+pub struct FooImpl;
+
+impl Foo for FooImpl {
+    type Bar = ();
+    //~^ ERROR the trait bound `(): AsRef<()>` is not satisfied
+    fn foo(&self) -> Pin<Box<dyn Future<Output = Self::Bar> + '_>> {
+        panic!()
+    }
+}
+
+async fn foo() {
+    bar(&FooImpl).await;
+}
+
+async fn bar<F: Foo>(foo: &F) {
+    foo.foo().await.as_ref();
+}
+
+fn main() {
+    // futures::executor::block_on(foo());
+}
diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr
new file mode 100644 (file)
index 0000000..d96c5f4
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `(): AsRef<()>` is not satisfied
+  --> $DIR/cross-crate-bounds.rs:15:5
+   |
+LL |     type Bar = ();
+   |     ^^^^^^^^^^^^^^ the trait `AsRef<()>` is not implemented for `()`
+   | 
+  ::: $DIR/auxiliary/foo_defn.rs:6:15
+   |
+LL |     type Bar: AsRef<()>;
+   |               --------- required by this bound in `foo_defn::Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 1a94796535c14b1f444097f7c8cca8a624e9aada..27970b15a411d6d94df825d1547de7b7691f6a46 100644 (file)
@@ -19,8 +19,9 @@ trait Foo {
 impl Foo for Bar {
     type Assoc = usize;
     type Assoc2<T> = Vec<T>;
+    //~^ ERROR `T` doesn't implement `std::fmt::Display`
     type Assoc3<T> where T: Iterator = Vec<T>;
-    //~^ impl has stricter requirements than trait
+    //~^ ERROR impl has stricter requirements than trait
     type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
     type NoGenerics = ::std::cell::Cell<i32>;
 }
index c95765d906c22ef56e17218a3f4b243ae81501ee..da8b625ea7f751ea01ed1ac1f474a1f353256673 100644 (file)
@@ -1,5 +1,17 @@
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/generic-associated-types-where.rs:21:5
+   |
+LL |     type Assoc2<T> = Vec<T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+help: consider restricting type parameter `T`
+   |
+LL |     type Assoc2<T: std::fmt::Display> = Vec<T>;
+   |                  ^^^^^^^^^^^^^^^^^^^
+
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/generic-associated-types-where.rs:22:5
+  --> $DIR/generic-associated-types-where.rs:23:5
    |
 LL |     type Assoc3<T>;
    |     --------------- definition of `Assoc3` from trait
@@ -7,6 +19,7 @@ LL |     type Assoc3<T>;
 LL |     type Assoc3<T> where T: Iterator = Vec<T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0276`.
+Some errors have detailed explanations: E0276, E0277.
+For more information about an error, try `rustc --explain E0276`.
index 77bebc9854aa09e72ec32a73f0d28bb8a52efe7b..089a214667ea24f8ee05713f1d0b90c6dedd74c6 100644 (file)
@@ -16,6 +16,7 @@ impl<T> Foo for Fooy<T> {
     //~^ ERROR the parameter type `T` may not live long enough
     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
     //~^ ERROR lifetime bound not satisfied
+    //~| ERROR lifetime bound not satisfied
     type C where Self: Copy = String;
     //~^ ERROR the trait bound `T: Copy` is not satisfied
 }
index 0546e38a33da7824fec21bc27ab0b2f4b09a7f7a..645d292714562213ebc4ea08c005f025656d3ef8 100644 (file)
@@ -24,8 +24,25 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined on the as
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
    |            ^^
 
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/impl_bounds.rs:17:5
+   |
+LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12
+  --> $DIR/impl_bounds.rs:17:12
+   |
+LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+   |            ^^
+note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16
+  --> $DIR/impl_bounds.rs:17:16
+   |
+LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+   |                ^^
+
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/impl_bounds.rs:19:5
+  --> $DIR/impl_bounds.rs:20:5
    |
 LL |     type C where Self: Copy = String;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
@@ -37,7 +54,7 @@ help: consider restricting type parameter `T`
 LL | impl<T: Copy> Foo for Fooy<T> {
    |       ^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0310, E0478.
 For more information about an error, try `rustc --explain E0277`.
index 2387b891755247cbca1dab8a0882b19e85103871..98aa82aba83055a33a1f244a9365b454fe69c3ce 100644 (file)
@@ -10,11 +10,12 @@ trait Foo {
     type C where Self: Clone;
 }
 
+#[derive(Clone)]
 struct Fooy;
 
 impl Foo for Fooy {
     type A<'a> = (&'a ());
-    type B<'a, 'b> = (&'a(), &'b ());
+    type B<'a: 'b, 'b> = (&'a(), &'b ());
     type C = String;
 }
 
@@ -24,7 +25,7 @@ impl Foo for Fooy {
 impl<T> Foo for Fooer<T> {
     type A<'x> where T: 'x = (&'x ());
     type B<'u, 'v> where 'u: 'v = (&'v &'u ());
-    type C where Self: ToOwned = String;
+    type C where Self: Clone + ToOwned = String;
 }
 
 fn main() {}
index 6ba79dd5437bee1843f79d49432689bbda75b501..b380f0da2ea401846e7449ccb921758c847c7fde 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/issue-68641-check-gat-bounds.rs:15:5
    |
 LL |     type Item<'a>: Copy;
-   |     -------------------- required by `UnsafeCopy::Item`
+   |                    ---- required by this bound in `UnsafeCopy::Item`
 ...
 LL |     type Item<'a> = T;
    |     ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
index 15a66e25b191b3e3fc91bc5f132c70fbda837175..61950478c32a8cf08f61c9c9fcdf1a99c72bb158 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T`
   --> $DIR/issue-68642-broken-llvm-ir.rs:15:5
    |
 LL |     type F<'a>: Fn() -> u32;
-   |     ------------------------ required by `Fun::F`
+   |                 ----------- required by this bound in `Fun::F`
 ...
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
index 9b2ddb23267ad173bef63def291d9b1290672ae6..13980618987be8740ce34c39edbb1fa6910e8992 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T`
   --> $DIR/issue-68643-broken-mir.rs:15:5
    |
 LL |     type F<'a>: Fn() -> u32;
-   |     ------------------------ required by `Fun::F`
+   |                 ----------- required by this bound in `Fun::F`
 ...
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
index f7bfab35052e12a4ab4f14cdf7ba1456f0bdd50c..811242514695914a66f2653f981c29767aace06b 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T`
   --> $DIR/issue-68644-codegen-selection.rs:15:5
    |
 LL |     type F<'a>: Fn() -> u32;
-   |     ------------------------ required by `Fun::F`
+   |                 ----------- required by this bound in `Fun::F`
 ...
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
index 6c2d330a19a82080929ae775918e0ba343500060..22f50b394982831511f3e2a8777d771cd03c193a 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T`
   --> $DIR/issue-68645-codegen-fulfillment.rs:15:5
    |
 LL |     type F<'a>: Fn() -> u32;
-   |     ------------------------ required by `Fun::F`
+   |                 ----------- required by this bound in `Fun::F`
 ...
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
index a9336151b6afeb9974f3f3ce84c4f5a6392dd235..c4ee2c4e61872c4114d36e3e3069f703a58b87b4 100644 (file)
@@ -11,7 +11,7 @@ error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
   --> $DIR/issue-68656-unsized-values.rs:16:5
    |
 LL |     type Item<'a>: std::ops::Deref<Target = T>;
-   |     ------------------------------------------- required by `UnsafeCopy::Item`
+   |                                    ---------- required by this bound in `UnsafeCopy::Item`
 ...
 LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
    |      - this type parameter
diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs
new file mode 100644 (file)
index 0000000..0cd676a
--- /dev/null
@@ -0,0 +1,62 @@
+// Like `projection-bound-cycle.rs` but this avoids using
+// `feature(trivial_bounds)`.
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+trait Print {
+    fn print();
+}
+
+trait Foo {
+    type Item: Sized where <Self as Foo>::Item: Sized;
+}
+
+struct Number<T> { t: T }
+
+impl<T> Foo for Number<T> {
+    // Well-formedness checks require that the following
+    // goal is true:
+    // ```
+    // if ([T]: Sized) { # if the where clauses hold
+    //     [T]: Sized # then the bound on the associated type hold
+    // }
+    // ```
+    // which it is :)
+    type Item where [T]: Sized = [T];
+}
+
+struct OnlySized<T> where T: Sized { f: T }
+impl<T> Print for OnlySized<T> {
+    fn print() {
+        println!("{}", std::mem::size_of::<T>());
+    }
+}
+
+trait Bar {
+    type Assoc: Print;
+}
+
+impl<T> Bar for T where T: Foo {
+    // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
+    // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
+    // can use the bound on `Foo::Item` for this, but that requires
+    // `wf(<T as Foo>::Item)`, which is an invalid cycle.
+    type Assoc = OnlySized<<T as Foo>::Item>;
+    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
+}
+
+fn foo<T: Print>() {
+    T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
+}
+
+fn bar<T: Bar>() {
+    // we have `FromEnv(T: Bar)` hence
+    // `<T as Bar>::Assoc` is well-formed and
+    // `Implemented(<T as Bar>::Assoc: Print)` hold
+    foo::<<T as Bar>::Assoc>()
+}
+
+fn main() {
+    bar::<Number<u8>>()
+}
diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr
new file mode 100644 (file)
index 0000000..d27e46f
--- /dev/null
@@ -0,0 +1,21 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/projection-bound-cycle-generic.rs:4:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
+  --> $DIR/projection-bound-cycle-generic.rs:45:5
+   |
+LL | struct OnlySized<T> where T: Sized { f: T }
+   |                  - required by this bound in `OnlySized`
+...
+LL |     type Assoc = OnlySized<<T as Foo>::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs
new file mode 100644 (file)
index 0000000..5043fe5
--- /dev/null
@@ -0,0 +1,64 @@
+// Test case from Chalk.
+// Make sure that we make sure that we don't allow arbitrary bounds to be
+// proven when a bound and a where clause of an associated type are the same.
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+#![feature(trivial_bounds)]
+
+trait Print {
+    fn print();
+}
+
+trait Foo {
+    type Item: Sized where <Self as Foo>::Item: Sized;
+}
+
+struct Number { }
+
+impl Foo for Number {
+    // Well-formedness checks require that the following
+    // goal is true:
+    // ```
+    // if (str: Sized) { # if the where clauses hold
+    //     str: Sized # then the bound on the associated type hold
+    // }
+    // ```
+    // which it is :)
+    type Item where str: Sized = str;
+}
+
+struct OnlySized<T> where T: Sized { f: T }
+impl<T> Print for OnlySized<T> {
+    fn print() {
+        println!("{}", std::mem::size_of::<T>());
+    }
+}
+
+trait Bar {
+    type Assoc: Print;
+}
+
+impl<T> Bar for T where T: Foo {
+    // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
+    // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
+    // can use the bound on `Foo::Item` for this, but that requires
+    // `wf(<T as Foo>::Item)`, which is an invalid cycle.
+    type Assoc = OnlySized<<T as Foo>::Item>;
+    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
+}
+
+fn foo<T: Print>() {
+    T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
+}
+
+fn bar<T: Bar>() {
+    // we have `FromEnv(T: Bar)` hence
+    // `<T as Bar>::Assoc` is well-formed and
+    // `Implemented(<T as Bar>::Assoc: Print)` hold
+    foo::<<T as Bar>::Assoc>()
+}
+
+fn main() {
+    bar::<Number>()
+}
diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr
new file mode 100644 (file)
index 0000000..400b664
--- /dev/null
@@ -0,0 +1,21 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/projection-bound-cycle.rs:5:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
+  --> $DIR/projection-bound-cycle.rs:47:5
+   |
+LL | struct OnlySized<T> where T: Sized { f: T }
+   |                  - required by this bound in `OnlySized`
+...
+LL |     type Assoc = OnlySized<<T as Foo>::Item>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
index 7510c58d57489aa76158811c06c3ae1fd8bcdfd1..99d5bcf2bace9a3cb6abb00bf404c0f157fbcaad 100644 (file)
@@ -7,7 +7,7 @@ trait ATy {
 
 impl<'b> ATy for &'b () {
     type Item<'a> = &'b ();
-    //~^ ERROR does not fulfill the required lifetime
+    //~^ ERROR  the type `&'b ()` does not fulfill the required lifetime
 }
 
 trait StaticTy {
@@ -16,7 +16,7 @@ trait StaticTy {
 
 impl StaticTy for () {
     type Item<'a> = &'a ();
-    //~^ ERROR does not fulfill the required lifetime
+    //~^ ERROR  the type `&'a ()` does not fulfill the required lifetime
 }
 
 fn main() {}
index 03aba10cc79b4a28468fb2fede535ac2102a3953..a7d06c71663de259f4d492da884c8df32a98f423 100644 (file)
@@ -15,7 +15,6 @@ LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
    |
    = note:         expected type `()`
            found associated type `<T as impl_trait::Trait>::Assoc`
-   = note: the return type of a function must have a statically known size
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
@@ -35,7 +34,6 @@ LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
    |
    = note:         expected type `()`
            found associated type `<T as lifetimes::Trait<'static>>::Assoc`
-   = note: the return type of a function must have a statically known size
 help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
    |
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
index db49d988bb8eb81ae62e0a86172ae23c04e0b871..64c536cf1fe30b5513c20a22027d00a22453744c 100644 (file)
@@ -14,7 +14,6 @@ LL |     type E = impl Copy;
    |              ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
    |
    = note: required because it appears within the type `(S, T)`
-   = note: the return type of a function must have a statically known size
 help: consider further restricting this bound
    |
 LL | impl<S: Default + Copy> Bar for S {
@@ -27,7 +26,6 @@ LL |     type E = impl Copy;
    |              ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `(S, T)`
-   = note: the return type of a function must have a statically known size
 help: consider further restricting this bound
    |
 LL |     fn foo<T: Default + Copy>() -> Self::E {
index 6da3704184abb61855aa7999acc1f14dfab75421..58c5ee45051af2159fcfd9994ccc2ec5d69544cc 100644 (file)
@@ -3,8 +3,6 @@ error[E0277]: the trait bound `impl Future: Copy` is not satisfied
    |
 LL |     type E = impl std::marker::Copy;
    |              ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future`
-   |
-   = note: the return type of a function must have a statically known size
 
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
   --> $DIR/issue-55872-2.rs:15:28
diff --git a/src/test/ui/impl-trait/wf-eval-order.rs b/src/test/ui/impl-trait/wf-eval-order.rs
new file mode 100644 (file)
index 0000000..c7d6bb8
--- /dev/null
@@ -0,0 +1,39 @@
+// Check that we handle evaluating `wf` predicates correctly.
+
+// check-pass
+
+struct X<T: B>(T)
+where
+    T::V: Clone;
+
+fn hide<T>(t: T) -> impl Sized {
+    t
+}
+
+trait A {
+    type U;
+}
+
+impl<T> A for T {
+    type U = T;
+}
+
+trait B {
+    type V;
+}
+
+impl<S: A<U = T>, T> B for S {
+    type V = T;
+}
+
+fn main() {
+    // Evaluating `typeof(x): Sized` requires
+    //
+    // - `wf(typeof(x))` because we use a projection candidate.
+    // - `<i32 as B>::V: Clone` because that's a bound on the trait.
+    // - `<i32 as B>::V` normalizes to `_#1` where `<i32 as A>::U == _#1`
+    //
+    // This all works if we evaluate `<i32 as A>::U == _#1` before
+    // `<i32 as B>::V`, but we previously had the opposite order.
+    let x = hide(X(0));
+}
index b6e3bb190ea7f7e16dabc9adc590b1a86883efe9..2f630c2c9ad71a2fafc2b61376d5493bdd011585 100644 (file)
@@ -8,12 +8,12 @@ LL | #![feature(impl_trait_in_bindings)]
    = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
 
 error[E0282]: type annotations needed for `impl Future`
-  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9
+  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20
    |
 LL |     let fut = async {
    |         --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified
 LL |         make_unit()?;
-   |         ^^^^^^^^^^^^ cannot infer type
+   |                    ^ cannot infer type
 
 error: aborting due to previous error; 1 warning emitted
 
index bf31fb85cf6db5c5eab50fd634a36a740621e01e..92a9045f6db503c5e57ffe4e80f85480e3a56ef7 100644 (file)
@@ -1,10 +1,10 @@
 error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-async.rs:11:9
+  --> $DIR/cannot-infer-async.rs:11:20
    |
 LL |     let fut = async {
    |         --- consider giving `fut` a type
 LL |         make_unit()?;
-   |         ^^^^^^^^^^^^ cannot infer type
+   |                    ^ cannot infer type
 
 error: aborting due to previous error
 
index c26c24f1dc573c9fabd5314e9e739b11ada3b27d..d5366e422dbff9e1d4db97fa1f5acf3240af4269 100644 (file)
@@ -1,8 +1,8 @@
 error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>`
-  --> $DIR/cannot-infer-closure.rs:3:9
+  --> $DIR/cannot-infer-closure.rs:3:15
    |
 LL |         Err(a)?;
-   |         ^^^^^^^ cannot infer type
+   |               ^ cannot infer type
    |
 help: give this closure an explicit return type without `_` placeholders
    |
index 867f8f0496c033a99b2cbab8ba61ce2860a06563..bbcdd3e37a96ef141c6b7dc1800362396c1b0a53 100644 (file)
@@ -9,11 +9,8 @@ error[E0277]: `u32` is not a future
    |
 LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
-LL |     *x
-   |     -- this returned value is of type `u32`
    |
    = help: the trait `Future` is not implemented for `u32`
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to 2 previous errors
 
index e8d16a55e926e512908122b1bf391aedc7801339..9940f43cc44404ce631f3d092015f4038da9edb5 100644 (file)
@@ -5,6 +5,7 @@ LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
    = note: required by `into_iter`
 
 error: aborting due to previous error
index d0e15cb393ae8b851d51da5747538174a4d5aa04..20d980763ea9cf65acf345f1c327099f509946fd 100644 (file)
@@ -28,9 +28,6 @@ impl<'a> Publisher<'a> for MyStruct<'a> {
     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
         // Not obvious, but there is an implicit lifetime here -------^
         //~^^ ERROR cannot infer
-        //~| ERROR cannot infer
-        //~| ERROR mismatched types
-        //~| ERROR mismatched types
         //
         // The fact that `Publisher` is using an implicit lifetime is
         // what was causing the debruijn accounting to be off, so
index 1ab89e818e31e5409482adbf3799b312b7a1fbd1..bcfb6b70b2e5f3c21d9e5645581876a4e2aee853 100644 (file)
@@ -1,77 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-20831-debruijn.rs:28:5
-   |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^ lifetime mismatch
-   |
-   = note: expected type `'a`
-              found type `'_`
-note: the anonymous lifetime #2 defined on the method body at 28:5...
-  --> $DIR/issue-20831-debruijn.rs:28:5
-   |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6
-  --> $DIR/issue-20831-debruijn.rs:26:6
-   |
-LL | impl<'a> Publisher<'a> for MyStruct<'a> {
-   |      ^^
-
-error[E0308]: mismatched types
-  --> $DIR/issue-20831-debruijn.rs:28:5
-   |
-LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-LL | |         // Not obvious, but there is an implicit lifetime here -------^
-LL | |
-LL | |
-...  |
-LL | |         self.sub = t;
-LL | |     }
-   | |_____^ lifetime mismatch
-   |
-   = note: expected type `'a`
-              found type `'_`
-note: the lifetime `'a` as defined on the impl at 26:6...
-  --> $DIR/issue-20831-debruijn.rs:26:6
-   |
-LL | impl<'a> Publisher<'a> for MyStruct<'a> {
-   |      ^^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5
-  --> $DIR/issue-20831-debruijn.rs:28:5
-   |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/issue-20831-debruijn.rs:28:33
-   |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
-  --> $DIR/issue-20831-debruijn.rs:28:5
-   |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6...
-  --> $DIR/issue-20831-debruijn.rs:26:6
-   |
-LL | impl<'a> Publisher<'a> for MyStruct<'a> {
-   |      ^^
-note: ...so that the types are compatible
-  --> $DIR/issue-20831-debruijn.rs:28:33
-   |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `Publisher<'_>`
-              found `Publisher<'_>`
-
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/issue-20831-debruijn.rs:28:33
    |
@@ -96,7 +22,6 @@ LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher
    = note: expected `Publisher<'_>`
               found `Publisher<'_>`
 
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0495.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0495`.
index 0a9f8f50bdcbea8b8f545c26c19735b89d41c822..d0c052cb2fd39fadc69593720402422e887a07fb 100644 (file)
@@ -5,7 +5,6 @@ trait Foo {
 struct FooStruct;
 
 impl Foo for FooStruct {
-    //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A == _`
     type A = <FooStruct as Foo>::A;
     //~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A == _`
 }
index 582ce393d7f5473a0aca178308d2f2ecfb072df6..0497bd20469a0e6bddaea19c5f4c408773890ca4 100644 (file)
@@ -1,15 +1,9 @@
 error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
-  --> $DIR/issue-21946.rs:7:6
-   |
-LL | impl Foo for FooStruct {
-   |      ^^^
-
-error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
-  --> $DIR/issue-21946.rs:9:5
+  --> $DIR/issue-21946.rs:8:5
    |
 LL |     type A = <FooStruct as Foo>::A;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
index d6f64650f36bb6332ce22692af622c369a93afd3..0937e029ef45e142299fdc08a9018403a8c535f7 100644 (file)
@@ -5,7 +5,6 @@ trait Next {
 struct GetNext<T: Next> { t: T }
 
 impl<T: Next> Next for GetNext<T> {
-    //~^ ERROR overflow evaluating the requirement
     type Next = <GetNext<T> as Next>::Next;
     //~^ ERROR overflow evaluating the requirement
 }
index 4e2e837c07c6ba5dd9c78363215ef7c32a0d8ef7..1f78b0d152d1b3adc0159b5b47a616df684db169 100644 (file)
@@ -1,15 +1,9 @@
 error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
-  --> $DIR/issue-23122-1.rs:7:15
-   |
-LL | impl<T: Next> Next for GetNext<T> {
-   |               ^^^^
-
-error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
-  --> $DIR/issue-23122-1.rs:9:5
+  --> $DIR/issue-23122-1.rs:8:5
    |
 LL |     type Next = <GetNext<T> as Next>::Next;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
index 695712d2cc929aea4a9466660cf9708ccf8f0be4..84abebf6b74a7cc1ba3fa92f87576fc0cdd386cb 100644 (file)
@@ -5,7 +5,6 @@ trait Next {
 struct GetNext<T: Next> { t: T }
 
 impl<T: Next> Next for GetNext<T> {
-    //~^ ERROR overflow evaluating the requirement
     type Next = <GetNext<T::Next> as Next>::Next;
     //~^ ERROR overflow evaluating the requirement
 }
index 60dbb15d0f9c376bcbac3431d4e9fedb6cebcef0..7ed04519b69caa15b341c285d5d3b867174e68a8 100644 (file)
@@ -1,14 +1,5 @@
-error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:7:15
-   |
-LL | impl<T: Next> Next for GetNext<T> {
-   |               ^^^^
-   |
-   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
-   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
-
 error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:9:5
+  --> $DIR/issue-23122-2.rs:8:5
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,6 +7,6 @@ LL |     type Next = <GetNext<T::Next> as Next>::Next;
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
    = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
index 61671b32e9b1540c46666feaf64c0d3e238cce7d..5a7b3459589eb77ea6a14457c02ad46b6c3f62b4 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 #![allow(dead_code)]
 
 trait MultiDispatch<T> {
@@ -8,10 +10,16 @@ trait Trait: Sized {
     type A: MultiDispatch<Self::B, O = Self>;
     type B;
 
-    fn new<U>(u: U) -> <Self::A as MultiDispatch<U>>::O where Self::A : MultiDispatch<U>;
+    fn new<U>(u: U) -> <Self::A as MultiDispatch<U>>::O
+    where
+        Self::A: MultiDispatch<U>;
 }
 
-fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
-//~^ ERROR type mismatch resolving
+fn test<T: Trait<B = i32>>(b: i32) -> T
+where
+    T::A: MultiDispatch<i32>,
+{
+    T::new(b)
+}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr
deleted file mode 100644 (file)
index d5cbcf7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0271]: type mismatch resolving `<<T as Trait>::A as MultiDispatch<i32>>::O == T`
-  --> $DIR/issue-24204.rs:14:12
-   |
-LL | trait Trait: Sized {
-   |       ----- required by a bound in this
-LL |     type A: MultiDispatch<Self::B, O = Self>;
-   |                                    -------- required by this bound in `Trait`
-...
-LL | fn test<T: Trait<B=i32>>(b: i32) -> T where T::A: MultiDispatch<i32> { T::new(b) }
-   |         -  ^^^^^^^^^^^^ expected type parameter `T`, found associated type
-   |         |
-   |         this type parameter
-   |
-   = note: expected type parameter `T`
-             found associated type `<<T as Trait>::A as MultiDispatch<i32>>::O`
-   = note: you might be missing a type parameter or trait bound
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
index df552fc2d0e2b89915e17c4e6eb7667fa5bba25a..4c927a0cb458f8c471b52398a0a024de39b5350c 100644 (file)
@@ -14,6 +14,7 @@ LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `bool`
+   = note: required because of the requirements on the impl of `IntoIterator` for `bool`
    = note: required by `into_iter`
 
 error[E0277]: `()` is not an iterator
@@ -58,6 +59,7 @@ LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `bool`
+   = note: required because of the requirements on the impl of `IntoIterator` for `bool`
    = note: required by `into_iter`
 
 error[E0277]: `()` is not an iterator
index aeab923d2df16d7d9c986febb553c76d6cc612eb..e91dae08b3a331b36eeee730681efd1c3f6fc6a0 100644 (file)
@@ -16,6 +16,8 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note:  expected tuple `(&_, &_)`
            found reference `&_`
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+   = note: required by `into_iter`
 
 error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
   --> $DIR/issue-33941.rs:4:14
@@ -26,6 +28,7 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note:  expected tuple `(&_, &_)`
            found reference `&_`
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+   = note: required by `std::iter::Iterator::next`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/issues/issue-38091.rs
deleted file mode 100644 (file)
index a84391b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
-
-trait Iterate<'a> {
-    type Ty: Valid;
-    fn iterate(self);
-}
-impl<'a, T> Iterate<'a> for T where T: Check {
-    default type Ty = ();
-    //~^ ERROR the trait bound `(): Valid` is not satisfied
-    default fn iterate(self) {}
-}
-
-trait Check {}
-impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
-
-trait Valid {}
-
-fn main() {
-    Iterate::iterate(0);
-}
diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/issues/issue-38091.stderr
deleted file mode 100644 (file)
index 81beec8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-38091.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-
-error[E0277]: the trait bound `(): Valid` is not satisfied
-  --> $DIR/issue-38091.rs:9:5
-   |
-LL |     type Ty: Valid;
-   |     --------------- required by `Iterate::Ty`
-...
-LL |     default type Ty = ();
-   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
index 4814232607cf8d16a7d1f98554bd39641506aa18..94c53216f50ac0f77560a4877b5c6223c824101d 100644 (file)
@@ -1,8 +1,12 @@
 trait Trait {}
 
-fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") }
+fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait {
+    panic!("")
+}
 
 fn main() {
-    let t : &dyn Trait = &get_function()();
-    //~^ ERROR cannot move a value of type dyn Trait
+    // This isn't great. The issue here is that `dyn Trait` is not sized, so
+    // `dyn Fn() -> dyn Trait` is not well-formed.
+    let t: &dyn Trait = &get_function()();
+    //~^ ERROR expected function, found `&dyn Fn() -> (dyn Trait + 'static)`
 }
index 829d0cfa72ca704d77af2279230d67993ea7448f..48b22bca20f067444040cd73b4c487343e31e8ee 100644 (file)
@@ -1,9 +1,14 @@
-error[E0161]: cannot move a value of type dyn Trait: the size of dyn Trait cannot be statically determined
-  --> $DIR/issue-41139.rs:6:27
+error[E0618]: expected function, found `&dyn Fn() -> (dyn Trait + 'static)`
+  --> $DIR/issue-41139.rs:10:26
    |
-LL |     let t : &dyn Trait = &get_function()();
-   |                           ^^^^^^^^^^^^^^^^
+LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait {
+   | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)`
+...
+LL |     let t: &dyn Trait = &get_function()();
+   |                          ^^^^^^^^^^^^^^--
+   |                          |
+   |                          call expression requires function
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0161`.
+For more information about this error, try `rustc --explain E0618`.
index 039852ad16596a13f092975b9a7e7b845d39818c..d5105ae3b58157bf3731a6edb0879715198376a8 100644 (file)
@@ -1,8 +1,11 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-43784-associated-type.rs:14:18
+  --> $DIR/issue-43784-associated-type.rs:14:5
    |
+LL |     type Assoc: Partial<Self>;
+   |                 ------------- required by this bound in `Complete::Assoc`
+...
 LL |     type Assoc = T;
-   |                  ^ the trait `Copy` is not implemented for `T`
+   |     ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index d92e4fa9e4a5d6f32f4b9ce89939eb1d0a90f803..c73536ba97332b3cbc715275a57cddf18ce04d6a 100644 (file)
@@ -1,6 +1,9 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/issue-43784-supertrait.rs:8:9
    |
+LL | pub trait Complete: Partial {
+   |                     ------- required by this bound in `Complete`
+...
 LL | impl<T> Complete for T {}
    |         ^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
index 9b184e296aa6fc237e3c94ec41fbf2ef99e6e2bd..0cb04dcb22a548c76459a20f3701b7d10a3e29f0 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 use std::ops::Add;
 
 trait Trait<T> {
@@ -18,7 +20,11 @@ enum Either<L, R> {
 }
 
 impl<L, R> Either<L, R> {
-    fn converge<T>(self) -> T where L: Trait<T>, R: Trait<T> {
+    fn converge<T>(self) -> T
+    where
+        L: Trait<T>,
+        R: Trait<T>,
+    {
         match self {
             Either::Left(val) => val.get(),
             Either::Right(val) => val.get(),
@@ -26,22 +32,16 @@ fn converge<T>(self) -> T where L: Trait<T>, R: Trait<T> {
     }
 }
 
-fn add_generic<A: Add<B>, B>(lhs: A, rhs: B) -> Either<
-    impl Trait<<A as Add<B>>::Output>,
-    impl Trait<<A as Add<B>>::Output>
-> {
-    if true {
-        Either::Left(Holder(lhs + rhs))
-    } else {
-        Either::Right(Holder(lhs + rhs))
-    }
+fn add_generic<A: Add<B>, B>(
+    lhs: A,
+    rhs: B,
+) -> Either<impl Trait<<A as Add<B>>::Output>, impl Trait<<A as Add<B>>::Output>> {
+    if true { Either::Left(Holder(lhs + rhs)) } else { Either::Right(Holder(lhs + rhs)) }
 }
 
 fn add_one(
     value: u32,
 ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
-    //~^ ERROR: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>`
-    //~| ERROR: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>`
     add_generic(value, 1u32)
 }
 
diff --git a/src/test/ui/issues/issue-58344.stderr b/src/test/ui/issues/issue-58344.stderr
deleted file mode 100644 (file)
index ade85d8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0277]: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>` is not satisfied
-  --> $DIR/issue-58344.rs:42:13
-   |
-LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as Add>::Output>`
-...
-LL |     add_generic(value, 1u32)
-   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as Add>::Output>, impl Trait<<u32 as Add>::Output>>`
-   |
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: the trait bound `impl Trait<<u32 as Add>::Output>: Trait<u32>` is not satisfied
-  --> $DIR/issue-58344.rs:42:52
-   |
-LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
-   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as Add>::Output>`
-...
-LL |     add_generic(value, 1u32)
-   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as Add>::Output>, impl Trait<<u32 as Add>::Output>>`
-   |
-   = note: the return type of a function must have a statically known size
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index 9c2b2dc9f4daec0b3fc68c30a25d26694002bdc1..c63b1544a5379d691feded61395b8610448b04b6 100644 (file)
@@ -16,4 +16,5 @@ pub fn foo<T, F>(_: T, _: F)
 fn main() {
     foo((), drop)
     //~^ ERROR type mismatch in function arguments
+    //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
 }
index ad679bfa22063cd39d21f78c34dd65002fba3cf5..650570b6471eb13266ce99e8273e68350eaaf272 100644 (file)
@@ -13,6 +13,24 @@ LL |     foo((), drop)
    |             expected signature of `fn(<() as Trait<'a>>::Item) -> _`
    |             found signature of `fn(()) -> _`
 
-error: aborting due to previous error
+error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+  --> $DIR/issue-60283.rs:17:13
+   |
+LL |     foo((), drop)
+   |             ^^^^ doesn't have a size known at compile-time
+   | 
+  ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL | pub fn drop<T>(_x: T) {}
+   |             - required by this bound in `std::mem::drop`
+   |
+   = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
+help: consider further restricting the associated type
+   |
+LL | fn main() where <() as Trait<'_>>::Item: Sized {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0631`.
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
index aa43ac9414f19e6ee75be86fbb3a04bfc24183d2..64cc0bab3f33c147724038ec3232b5c906a89bd7 100644 (file)
@@ -1,13 +1,11 @@
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/issue-65673.rs:9:16
+  --> $DIR/issue-65673.rs:9:5
    |
-LL | trait WithType {
-   |       -------- required by a bound in this
 LL |     type Ctx;
-   |     --------- required by this bound in `WithType`
+   |     --------- required by this bound in `WithType::Ctx`
 ...
 LL |     type Ctx = dyn Alias<T>;
-   |                ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
 
index 6271d8107bc05b74f945146cf965166b80c2cac7..601983a6153fd736e2ca2dd7a7103bf91dcdc78f 100644 (file)
@@ -6,6 +6,7 @@ LL |     for _ in [0..1] {}
    |
    = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
    = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator
@@ -16,6 +17,7 @@ LL |     for _ in [0..=1] {}
    |
    = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator
@@ -26,6 +28,7 @@ LL |     for _ in [0..] {}
    |
    = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator
@@ -36,6 +39,7 @@ LL |     for _ in [..1] {}
    |
    = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator
@@ -46,6 +50,7 @@ LL |     for _ in [..=1] {}
    |
    = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
@@ -56,6 +61,7 @@ LL |     for _ in [start..end] {}
    |
    = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
    = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator
@@ -66,6 +72,7 @@ LL |     for _ in array_of_range {}
    |
    = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]`
    = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]`
    = note: required by `into_iter`
 
 error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator
@@ -76,6 +83,7 @@ LL |     for _ in [0..1, 2..3] {}
    |
    = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]`
    = note: required by `into_iter`
 
 error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator
@@ -86,6 +94,7 @@ LL |     for _ in [0..=1] {}
    |
    = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]`
    = note: required by `into_iter`
 
 error: aborting due to 9 previous errors
index f86c82e4917e69f2e7d5d3d951df35c4bfecda02..68c6de5493f1343bfbf8b14f93b566b601780a60 100644 (file)
@@ -6,6 +6,7 @@ LL |     for _ in [1, 2] {}
    |
    = help: the trait `Iterator` is not implemented for `[{integer}; 2]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]`
    = note: required by `into_iter`
 
 error[E0277]: `[{integer}; 2]` is not an iterator
@@ -16,6 +17,7 @@ LL |     for _ in x {}
    |
    = help: the trait `Iterator` is not implemented for `[{integer}; 2]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]`
    = note: required by `into_iter`
 
 error[E0277]: `[{float}; 2]` is not an iterator
@@ -26,6 +28,7 @@ LL |     for _ in [1.0, 2.0] {}
    |
    = help: the trait `Iterator` is not implemented for `[{float}; 2]`
    = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
+   = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]`
    = note: required by `into_iter`
 
 error: aborting due to 3 previous errors
index c4c464126111df77296e5e81c171c0d0a1627374..e31ee59785c8b7ff48691be11a61a3fe184b661a 100644 (file)
@@ -6,6 +6,7 @@ LL |     for _ in 42 {}
    |
    = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `{integer}`
    = note: required by `into_iter`
 
 error[E0277]: `u8` is not an iterator
@@ -16,6 +17,7 @@ LL |     for _ in 42 as u8 {}
    |
    = help: the trait `Iterator` is not implemented for `u8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `u8`
    = note: required by `into_iter`
 
 error[E0277]: `i8` is not an iterator
@@ -26,6 +28,7 @@ LL |     for _ in 42 as i8 {}
    |
    = help: the trait `Iterator` is not implemented for `i8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `i8`
    = note: required by `into_iter`
 
 error[E0277]: `u16` is not an iterator
@@ -36,6 +39,7 @@ LL |     for _ in 42 as u16 {}
    |
    = help: the trait `Iterator` is not implemented for `u16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `u16`
    = note: required by `into_iter`
 
 error[E0277]: `i16` is not an iterator
@@ -46,6 +50,7 @@ LL |     for _ in 42 as i16 {}
    |
    = help: the trait `Iterator` is not implemented for `i16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `i16`
    = note: required by `into_iter`
 
 error[E0277]: `u32` is not an iterator
@@ -56,6 +61,7 @@ LL |     for _ in 42 as u32 {}
    |
    = help: the trait `Iterator` is not implemented for `u32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `u32`
    = note: required by `into_iter`
 
 error[E0277]: `i32` is not an iterator
@@ -66,6 +72,7 @@ LL |     for _ in 42 as i32 {}
    |
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `i32`
    = note: required by `into_iter`
 
 error[E0277]: `u64` is not an iterator
@@ -76,6 +83,7 @@ LL |     for _ in 42 as u64 {}
    |
    = help: the trait `Iterator` is not implemented for `u64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `u64`
    = note: required by `into_iter`
 
 error[E0277]: `i64` is not an iterator
@@ -86,6 +94,7 @@ LL |     for _ in 42 as i64 {}
    |
    = help: the trait `Iterator` is not implemented for `i64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `i64`
    = note: required by `into_iter`
 
 error[E0277]: `usize` is not an iterator
@@ -96,6 +105,7 @@ LL |     for _ in 42 as usize {}
    |
    = help: the trait `Iterator` is not implemented for `usize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `usize`
    = note: required by `into_iter`
 
 error[E0277]: `isize` is not an iterator
@@ -106,6 +116,7 @@ LL |     for _ in 42 as isize {}
    |
    = help: the trait `Iterator` is not implemented for `isize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+   = note: required because of the requirements on the impl of `IntoIterator` for `isize`
    = note: required by `into_iter`
 
 error[E0277]: `{float}` is not an iterator
@@ -115,6 +126,7 @@ LL |     for _ in 42.0 {}
    |              ^^^^ `{float}` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `{float}`
+   = note: required because of the requirements on the impl of `IntoIterator` for `{float}`
    = note: required by `into_iter`
 
 error: aborting due to 12 previous errors
index 0324d5f1a92a198d393047e49797c1a05cefa35b..4678bafd196b57c8b0124dd52adb975b371984da 100644 (file)
@@ -5,6 +5,7 @@ LL |     for _ in ..10 {}
    |              ^^^^ `RangeTo<{integer}>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>`
    = note: required by `into_iter`
 
 error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
@@ -14,6 +15,7 @@ LL |     for _ in ..=10 {}
    |              ^^^^^ `RangeToInclusive<{integer}>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>`
    = note: required by `into_iter`
 
 error: aborting due to 2 previous errors
index fecdbd1785f618df32164d5b4dc99d7062a5099d..1653006682427736a5e0a889248ebd0d8f06acfe 100644 (file)
@@ -5,6 +5,7 @@ LL |     for _ in "".to_owned() {}
    |              ^^^^^^^^^^^^^ `String` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `String`
+   = note: required because of the requirements on the impl of `IntoIterator` for `String`
    = note: required by `into_iter`
 
 error[E0277]: `&str` is not an iterator
@@ -14,6 +15,7 @@ LL |     for _ in "" {}
    |              ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
    |
    = help: the trait `Iterator` is not implemented for `&str`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&str`
    = note: required by `into_iter`
 
 error: aborting due to 2 previous errors
index e43fb6d0edfb9e730892d6cb0a3eef0fb090b8d2..c3d597bec2e406e7a86e2099631664f756430972 100644 (file)
@@ -3,11 +3,6 @@ error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisf
    |
 LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
-LL |
-LL |     Ok(())
-   |     ------ this returned value is of type `std::result::Result<(), _>`
-   |
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
 
index c652faafad4613444163815c748f2c564770b02e..670f76867ce45122b29e6ebba4a3c628318c9507 100644 (file)
@@ -3,11 +3,6 @@ error[E0277]: the trait bound `(): T` is not satisfied
    |
 LL | fn should_ret_unit() -> impl T {
    |                         ^^^^^^ the trait `T` is not implemented for `()`
-LL |
-LL |     panic!()
-   |     -------- this returned value is of type `!`
-   |
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
 
index c54cbe9b4d173ff9fa3b735653d0fd681b33c44f..16d93c18900a9f5000db201a8f5aeeb096a0f66d 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: `!` is not an iterator
   --> $DIR/issue-51506.rs:13:5
    |
 LL |     type Out: Iterator<Item = u32>;
-   |     ------------------------------- required by `Trait::Out`
+   |               -------------------- required by this bound in `Trait::Out`
 ...
 LL |     default type Out = !;
    |     ^^^^^^^^^^^^^^^^^^^^^ `!` is not an iterator
index d3964a7f515deee842f9d71fa08a2f93a2fe8dcf..44dcd191d1ba2d7aea1a1e5134858c982d2d219a 100644 (file)
@@ -32,5 +32,4 @@ fn main() {
     let _x = <fn(&())>::make_f();
     //~^ higher-ranked subtype error
     //~| higher-ranked subtype error
-    //~| higher-ranked subtype error
 }
index 70fb877d716899e276f49c13f99fe6f4c8b15bdc..190b520c6786c61bef25883f1606ecb589d1d1c4 100644 (file)
@@ -10,11 +10,5 @@ error: higher-ranked subtype error
 LL |     let _x = <fn(&())>::make_f();
    |              ^^^^^^^^^^^^^^^^^^^
 
-error: higher-ranked subtype error
-  --> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
-   |
-LL |     let _x = <fn(&())>::make_f();
-   |              ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/object-safety/object-safety-bounds.rs b/src/test/ui/object-safety/object-safety-bounds.rs
new file mode 100644 (file)
index 0000000..44bd369
--- /dev/null
@@ -0,0 +1,12 @@
+// Traits with bounds mentioning `Self` are not object safe
+
+trait X {
+    type U: PartialEq<Self>;
+}
+
+fn f() -> Box<dyn X<U = u32>> {
+    //~^ ERROR the trait `X` cannot be made into an object
+    loop {}
+}
+
+fn main() {}
diff --git a/src/test/ui/object-safety/object-safety-bounds.stderr b/src/test/ui/object-safety/object-safety-bounds.stderr
new file mode 100644 (file)
index 0000000..af45483
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/object-safety-bounds.rs:7:11
+   |
+LL | trait X {
+   |       - this trait cannot be made into an object...
+LL |     type U: PartialEq<Self>;
+   |             --------------- ...because it uses `Self` as a type parameter in this
+...
+LL | fn f() -> Box<dyn X<U = u32>> {
+   |           ^^^^^^^^^^^^^^^^^^^ the trait `X` cannot be made into an object
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
index 42f5f1e7e736da2ef81daf6dfc11a0f2d0d9ef74..fe9c113710c3c09f71508f7d0a14ff50977dbcdf 100644 (file)
@@ -24,6 +24,7 @@ LL | |     }.hi() {
    | |__________^ `bool` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `bool`
+   = note: required because of the requirements on the impl of `IntoIterator` for `bool`
    = note: required by `into_iter`
 
 error: aborting due to 2 previous errors
index 5238894a974f4bf0d2efeedfb8f6e25b278535d0..fba72c13170feafd8a227547155f3134fb4c1b3f 100644 (file)
@@ -21,15 +21,15 @@ impl PubTrAux2 for u8 {
     // "Private-in-public in associated types is hard error" in RFC 2145
     // applies only to the aliased types, not bounds.
     pub trait PubTr {
+        type Alias1: PrivTr;
         //~^ WARN private trait `PrivTr` in public interface
         //~| WARN this was previously accepted
-        //~| WARN private type `Priv` in public interface
-        //~| WARN private type `Priv` in public interface
-        //~| WARN this was previously accepted
-        //~| WARN this was previously accepted
-        type Alias1: PrivTr;
         type Alias2: PubTrAux1<Priv> = u8;
+        //~^ WARN private type `Priv` in public interface
+        //~| WARN this was previously accepted
         type Alias3: PubTrAux2<A = Priv> = u8;
+        //~^ WARN private type `Priv` in public interface
+        //~| WARN this was previously accepted
 
         type Alias4 = Priv;
         //~^ ERROR private type `Priv` in public interface
index acc6e20cf33e8b6fbe367a9f62e09760f8a4f387..430be143f918778a5839f8dfbada510cdaab2ec7 100644 (file)
@@ -8,47 +8,29 @@ LL |         type A = Priv;
    |         ^^^^^^^^^^^^^^ can't leak private type
 
 warning: private trait `PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-assoc-ty.rs:23:5
+  --> $DIR/private-in-public-assoc-ty.rs:24:9
    |
-LL | /     pub trait PubTr {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         fn infer_exist() -> Self::Exist;
-LL | |     }
-   | |_____^
+LL |         type Alias1: PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(private_in_public)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:23:5
+  --> $DIR/private-in-public-assoc-ty.rs:27:9
    |
-LL | /     pub trait PubTr {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         fn infer_exist() -> Self::Exist;
-LL | |     }
-   | |_____^
+LL |         type Alias2: PubTrAux1<Priv> = u8;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:23:5
+  --> $DIR/private-in-public-assoc-ty.rs:30:9
    |
-LL | /     pub trait PubTr {
-LL | |
-LL | |
-LL | |
-...  |
-LL | |         fn infer_exist() -> Self::Exist;
-LL | |     }
-   | |_____^
+LL |         type Alias3: PubTrAux2<A = Priv> = u8;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
index 3022b470b7d81674fcb8932e264328dc87c6cdd6..1c8706d8ad2e1d5bec3556829a998a4c8b807fa4 100644 (file)
@@ -55,9 +55,9 @@ pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public inte
     pub trait Tr2<T: PrivTr> {} //~ ERROR private trait `traits::PrivTr` in public interface
         //~^ WARNING hard error
     pub trait Tr3 {
+        type Alias: PrivTr;
         //~^ ERROR private trait `traits::PrivTr` in public interface
         //~| WARNING hard error
-        type Alias: PrivTr;
         fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface
         //~^ WARNING hard error
     }
index 36577a6010260e17ccbad6b2ef9832ad2e99a94f..f50dc48f8add36dc1c599e9df9f4977d7fcf0c9f 100644 (file)
@@ -130,16 +130,10 @@ LL |     pub trait Tr2<T: PrivTr> {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private trait `traits::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:57:5
-   |
-LL | /     pub trait Tr3 {
-LL | |
-LL | |
-LL | |         type Alias: PrivTr;
-LL | |         fn f<T: PrivTr>(arg: T) {}
-LL | |
-LL | |     }
-   | |_____^
+  --> $DIR/private-in-public-warn.rs:58:9
+   |
+LL |         type Alias: PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
index e485263affcf721f5178058bbd5e281159bcccb8..f926eee9d92b282deddff6f52ff1437bc6edb05e 100644 (file)
@@ -1,5 +1,5 @@
- // aux-crate:priv:priv_dep=priv_dep.rs
- // aux-build:pub_dep.rs
+// aux-crate:priv:priv_dep=priv_dep.rs
+// aux-build:pub_dep.rs
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
@@ -7,20 +7,20 @@
 // This crate is a public dependency
 extern crate pub_dep;
 
-use priv_dep::{OtherType, OtherTrait};
+use priv_dep::{OtherTrait, OtherType};
 use pub_dep::PubType;
 
 // Type from private dependency used in private
 // type - this is fine
 struct PrivateType {
-    field: OtherType
+    field: OtherType,
 }
 
 pub struct PublicType {
     pub field: OtherType,
     //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
-    priv_field: OtherType, // Private field - this is fine
-    pub other_field: PubType // Type from public dependency - this is fine
+    priv_field: OtherType,    // Private field - this is fine
+    pub other_field: PubType, // Type from public dependency - this is fine
 }
 
 impl PublicType {
@@ -33,13 +33,11 @@ fn priv_fn(param: OtherType) {}
 pub trait MyPubTrait {
     type Foo: OtherTrait;
 }
-//~^^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
 
 pub struct AllowedPrivType {
     #[allow(exported_private_dependencies)]
-    pub allowed: OtherType
+    pub allowed: OtherType,
 }
 
-
-
 fn main() {}
index 3b5b78234436e9264b66f9ac76c5697b04849963..e6b4d33f10316e4ee36e8644e0de76f4f9a2a819 100644 (file)
@@ -17,12 +17,10 @@ LL |     pub fn pub_fn(param: OtherType) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:33:1
+  --> $DIR/pub-priv1.rs:34:5
    |
-LL | / pub trait MyPubTrait {
-LL | |     type Foo: OtherTrait;
-LL | | }
-   | |_^
+LL |     type Foo: OtherTrait;
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
index f530534ec801febe23bf238bcb26422091371699..381959b7ae4cda8b497da308bf3c35ae7b7042eb 100644 (file)
@@ -1,10 +1,11 @@
-error[E0284]: type annotations needed
+error[E0283]: type annotations needed
   --> $DIR/question-mark-type-infer.rs:12:21
    |
 LL |     l.iter().map(f).collect()?
    |                     ^^^^^^^ cannot infer type
    |
-   = note: cannot satisfy `<_ as Try>::Ok == _`
+   = note: cannot satisfy `_: Try`
+   = note: required by `into_result`
 help: consider specifying the type argument in the method call
    |
 LL |     l.iter().map(f).collect::<B>()?
@@ -12,4 +13,4 @@ LL |     l.iter().map(f).collect::<B>()?
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0284`.
+For more information about this error, try `rustc --explain E0283`.
index a7557320faa4b854b3351d07d42ebec8a12beb79..2cebffec990f69177bf04e22d444b57824682c25 100644 (file)
@@ -11,6 +11,8 @@ LL |     for i in false..true {}
    |              ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`
    |
    = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<bool>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<bool>`
+   = note: required by `into_iter`
 
 error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
   --> $DIR/range-1.rs:14:17
index 26cb40bb5c2b1f681bc2683c13ddfe9165eb6be4..575dfafe15efc4dc9e17b07011560a114d027133 100644 (file)
@@ -3,7 +3,7 @@
 
 trait Foo<'a> {
     type Value: 'a;
-    fn dummy(&'a self) { }
+    fn dummy(&'a self) {}
 }
 
 impl<'a> Foo<'a> for &'a i16 {
@@ -12,13 +12,13 @@ impl<'a> Foo<'a> for &'a i16 {
 }
 
 impl<'a> Foo<'static> for &'a i32 {
-    //~^ ERROR cannot infer
     type Value = &'a i32;
+    //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
 }
 
-impl<'a,'b> Foo<'b> for &'a i64 {
-    //~^ ERROR cannot infer
+impl<'a, 'b> Foo<'b> for &'a i64 {
     type Value = &'a i32;
+    //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
 }
 
-fn main() { }
+fn main() {}
index c134b3b3ed554a01598e561b9d75b8de8e698d6c..03da33ae11ffe1ab5e15e8c7e02c5b4d95e0ffa2 100644 (file)
@@ -1,57 +1,23 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:5
    |
-LL | impl<'a> Foo<'static> for &'a i32 {
-   |          ^^^^^^^^^^^^
+LL |     type Value = &'a i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6...
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6
-   |
-LL | impl<'a> Foo<'static> for &'a i32 {
-   |      ^^
-note: ...so that the types are compatible
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
-   |
-LL | impl<'a> Foo<'static> for &'a i32 {
-   |          ^^^^^^^^^^^^
-   = note: expected `Foo<'static>`
-              found `Foo<'static>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the type `&i32` will meet its required lifetime bounds
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
-   |
-LL | impl<'a> Foo<'static> for &'a i32 {
-   |          ^^^^^^^^^^^^
+   = note: type must satisfy the static lifetime
 
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
-   |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
-   |             ^^^^^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6...
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6
-   |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
-   |      ^^
-note: ...so that the types are compatible
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:5
    |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
-   |             ^^^^^^^
-   = note: expected `Foo<'b>`
-              found `Foo<'_>`
-note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9...
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
+LL |     type Value = &'a i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
-   |         ^^
-note: ...so that the type `&i32` will meet its required lifetime bounds
-  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13
+note: type must outlive the lifetime `'b` as defined on the impl at 19:10
+  --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10
    |
-LL | impl<'a,'b> Foo<'b> for &'a i64 {
-   |             ^^^^^^^
+LL | impl<'a, 'b> Foo<'b> for &'a i64 {
+   |          ^^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0477`.
index 599cd0bb756ea85435cbeb3a4f383f120364f2e7..00100e0e9ea75d129c78f98bcceb31139c402637 100644 (file)
@@ -3,12 +3,12 @@
 
 trait Foo {
     type Value: 'static;
-    fn dummy(&self) { }
+    fn dummy(&self) {}
 }
 
 impl<'a> Foo for &'a i32 {
-    //~^ ERROR cannot infer
     type Value = &'a i32;
+    //~^ ERROR the type `&'a i32` does not fulfill the required lifetime
 }
 
 impl<'a> Foo for i32 {
@@ -16,4 +16,4 @@ impl<'a> Foo for i32 {
     type Value = i32;
 }
 
-fn main() { }
+fn main() {}
index ac8c55ccc8fd4c679f2ee9a22fc0e514d973860d..d8efeac5b8a30bc022ce72663bbc9148786ec3c9 100644 (file)
@@ -1,28 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
+error[E0477]: the type `&'a i32` does not fulfill the required lifetime
+  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:5
    |
-LL | impl<'a> Foo for &'a i32 {
-   |          ^^^
+LL |     type Value = &'a i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6...
-  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6
-   |
-LL | impl<'a> Foo for &'a i32 {
-   |      ^^
-note: ...so that the types are compatible
-  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
-   |
-LL | impl<'a> Foo for &'a i32 {
-   |          ^^^
-   = note: expected `Foo`
-              found `Foo`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the type `&i32` will meet its required lifetime bounds
-  --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
-   |
-LL | impl<'a> Foo for &'a i32 {
-   |          ^^^
+   = note: type must satisfy the static lifetime
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0477`.
index 781cdb7286a0ef0dcbf802d21eec8f34b4374edb..6de08f66d7536920d7e11f80a45e3848de497ab0 100644 (file)
@@ -5,17 +5,18 @@
 #![allow(dead_code)]
 
 trait Dummy<'a> {
-  type Out;
+    type Out;
 }
 impl<'a, T> Dummy<'a> for T
-where T: 'a
+where
+    T: 'a,
 {
-  type Out = ();
+    type Out = ();
 }
 type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
 
 enum Ref1<'a, T> {
-    Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+    Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
 enum Ref2<'a, T> {
@@ -23,18 +24,18 @@ enum Ref2<'a, T> {
     Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
-enum RefOk<'a, T:'a> {
-    RefOkVariant1(&'a T)
+enum RefOk<'a, T: 'a> {
+    RefOkVariant1(&'a T),
 }
 
 // This is now well formed. RFC 2093
 enum RefIndirect<'a, T> {
-    RefIndirectVariant1(isize, RefOk<'a,T>)
+    RefIndirectVariant1(isize, RefOk<'a, T>),
 }
 
-enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
-    RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-        //~^ the parameter type `T` may not live long enough [E0309]
+enum RefDouble<'a, 'b, T> {
+    RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+    //~^ the parameter type `T` may not live long enough [E0309]
 }
 
-fn main() { }
+fn main() {}
index e32a36f72cd14b003a9207d88fe5ee514c2a91e1..36686eaf92f3213baf668f4f6bc4ecaf9c749696 100644 (file)
@@ -1,13 +1,13 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:18:18
+  --> $DIR/regions-enum-not-wf.rs:19:18
    |
 LL | enum Ref1<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref1Variant1(RequireOutlives<'a, T>)
+LL |     Ref1Variant1(RequireOutlives<'a, T>),
    |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:23:25
+  --> $DIR/regions-enum-not-wf.rs:24:25
    |
 LL | enum Ref2<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
@@ -16,25 +16,13 @@ LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
    |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:35:1
-   |
-LL |   enum RefDouble<'a, 'b, T> {
-   |   ^                      - help: consider adding an explicit lifetime bound...: `T: 'b`
-   |  _|
-   | |
-LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
-   | |_^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:36:23
+  --> $DIR/regions-enum-not-wf.rs:37:23
    |
 LL | enum RefDouble<'a, 'b, T> {
    |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0309`.
index e912805d855d2b57a370a6f6bfda5d6c0599c728..9912e88c2ec57546cf7a75be8e3fb03d8a2823ac 100644 (file)
@@ -6,7 +6,8 @@ trait Project<'a, 'b> {
 }
 
 impl<'a, 'b> Project<'a, 'b> for ()
-    where 'a: 'b
+where
+    'a: 'b,
 {
     type Item = ();
 }
@@ -14,16 +15,18 @@ impl<'a, 'b> Project<'a, 'b> for ()
 // No error here, we have 'a: 'b. We used to report an error here
 // though, see https://github.com/rust-lang/rust/issues/45937.
 fn foo<'a: 'b, 'b>()
-    where <() as Project<'a, 'b>>::Item : Eq
+where
+    <() as Project<'a, 'b>>::Item: Eq,
 {
 }
 
 // Here we get an error: we need `'a: 'b`.
-fn bar<'a, 'b>() //~ ERROR cannot infer
-                 //~| ERROR cannot infer
-                 //~| ERROR cannot infer
-    where <() as Project<'a, 'b>>::Item : Eq
+fn bar<'a, 'b>()
+//~^ ERROR cannot infer
+//~| ERROR cannot infer
+where
+    <() as Project<'a, 'b>>::Item: Eq,
 {
 }
 
-fn main() { }
+fn main() {}
index 10ecb8d526292de9b6ecf0340bf5e3cb8b77e965..ddb2b31ce10959540a652fac8f6caa3f5db9cb97 100644 (file)
@@ -1,87 +1,59 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
    |
 LL | / fn bar<'a, 'b>()
 LL | |
 LL | |
-LL | |     where <() as Project<'a, 'b>>::Item : Eq
-   | |____________________________________________^
+LL | | where
+LL | |     <() as Project<'a, 'b>>::Item: Eq,
+   | |______________________________________^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
    |
 LL | fn bar<'a, 'b>()
    |        ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
    |
 LL | fn bar<'a, 'b>()
    |            ^^
 note: ...so that the types are compatible
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:1
    |
 LL | / fn bar<'a, 'b>()
 LL | |
 LL | |
-LL | |     where <() as Project<'a, 'b>>::Item : Eq
-   | |____________________________________________^
+LL | | where
+LL | |     <() as Project<'a, 'b>>::Item: Eq,
+   | |______________________________________^
    = note: expected `Project<'a, 'b>`
               found `Project<'_, '_>`
 
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
-   |
-LL | / fn bar<'a, 'b>()
-LL | |
-LL | |
-LL | |     where <() as Project<'a, 'b>>::Item : Eq
-   | |____________________________________________^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
-   |
-LL | fn bar<'a, 'b>()
-   |        ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
-   |
-LL | fn bar<'a, 'b>()
-   |            ^^
-note: ...so that the types are compatible
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
-   |
-LL | / fn bar<'a, 'b>()
-LL | |
-LL | |
-LL | |     where <() as Project<'a, 'b>>::Item : Eq
-   | |____________________________________________^
-   = note: expected `Project<'a, 'b>`
-              found `Project<'_, '_>`
-
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:4
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
    |
 LL | fn bar<'a, 'b>()
    |    ^^^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:8
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:8
    |
 LL | fn bar<'a, 'b>()
    |        ^^
-note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12...
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:12
+note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12...
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:12
    |
 LL | fn bar<'a, 'b>()
    |            ^^
 note: ...so that the types are compatible
-  --> $DIR/regions-normalize-in-where-clause-list.rs:22:4
+  --> $DIR/regions-normalize-in-where-clause-list.rs:24:4
    |
 LL | fn bar<'a, 'b>()
    |    ^^^
    = note: expected `Project<'a, 'b>`
               found `Project<'_, '_>`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0495`.
index 0da8ac53695e954078a01fe24e87c89e95bc132c..b6dab1c32e8b291e1212c9e322447d7afb926788 100644 (file)
@@ -1,30 +1,33 @@
-#![feature(box_syntax)]
+// check-pass
 
-struct Ctxt { v: usize }
+struct Ctxt {
+    v: usize,
+}
 
 trait GetCtxt {
     // Here the `&` is bound in the method definition:
     fn get_ctxt(&self) -> &Ctxt;
 }
 
-struct HasCtxt<'a> { c: &'a Ctxt }
+struct HasCtxt<'a> {
+    c: &'a Ctxt,
+}
 
 impl<'a> GetCtxt for HasCtxt<'a> {
-
-    // Here an error occurs because we used `&self` but
-    // the definition used `&`:
-    fn get_ctxt(&self) -> &'a Ctxt { //~ ERROR method not compatible with trait
+    // Ok: Have implied bound of WF(&'b HasCtxt<'a>)
+    // so know 'a: 'b
+    // so know &'a Ctxt <: &'b Ctxt
+    fn get_ctxt<'b>(&'b self) -> &'a Ctxt {
         self.c
     }
-
 }
 
-fn get_v(gc: Box<dyn GetCtxt>) -> usize {
+fn get_v(gc: Box<dyn GetCtxt + '_>) -> usize {
     gc.get_ctxt().v
 }
 
 fn main() {
     let ctxt = Ctxt { v: 22 };
     let hc = HasCtxt { c: &ctxt };
-    assert_eq!(get_v(box hc as Box<dyn GetCtxt>), 22);
+    assert_eq!(get_v(Box::new(hc) as Box<dyn GetCtxt>), 22);
 }
diff --git a/src/test/ui/regions/regions-trait-1.stderr b/src/test/ui/regions/regions-trait-1.stderr
deleted file mode 100644 (file)
index 92d96a7..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0308]: method not compatible with trait
-  --> $DIR/regions-trait-1.rs:16:5
-   |
-LL |     fn get_ctxt(&self) -> &'a Ctxt {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
-   |
-   = note: expected fn pointer `fn(&HasCtxt<'a>) -> &Ctxt`
-              found fn pointer `fn(&HasCtxt<'a>) -> &'a Ctxt`
-note: the lifetime `'a` as defined on the impl at 12:6...
-  --> $DIR/regions-trait-1.rs:12:6
-   |
-LL | impl<'a> GetCtxt for HasCtxt<'a> {
-   |      ^^
-note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 16:5
-  --> $DIR/regions-trait-1.rs:16:5
-   |
-LL |     fn get_ctxt(&self) -> &'a Ctxt {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
index 781cdb7286a0ef0dcbf802d21eec8f34b4374edb..6de08f66d7536920d7e11f80a45e3848de497ab0 100644 (file)
@@ -5,17 +5,18 @@
 #![allow(dead_code)]
 
 trait Dummy<'a> {
-  type Out;
+    type Out;
 }
 impl<'a, T> Dummy<'a> for T
-where T: 'a
+where
+    T: 'a,
 {
-  type Out = ();
+    type Out = ();
 }
 type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
 
 enum Ref1<'a, T> {
-    Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough
+    Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
 enum Ref2<'a, T> {
@@ -23,18 +24,18 @@ enum Ref2<'a, T> {
     Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
 }
 
-enum RefOk<'a, T:'a> {
-    RefOkVariant1(&'a T)
+enum RefOk<'a, T: 'a> {
+    RefOkVariant1(&'a T),
 }
 
 // This is now well formed. RFC 2093
 enum RefIndirect<'a, T> {
-    RefIndirectVariant1(isize, RefOk<'a,T>)
+    RefIndirectVariant1(isize, RefOk<'a, T>),
 }
 
-enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309]
-    RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-        //~^ the parameter type `T` may not live long enough [E0309]
+enum RefDouble<'a, 'b, T> {
+    RefDoubleVariant1(&'a RequireOutlives<'b, T>),
+    //~^ the parameter type `T` may not live long enough [E0309]
 }
 
-fn main() { }
+fn main() {}
index e32a36f72cd14b003a9207d88fe5ee514c2a91e1..36686eaf92f3213baf668f4f6bc4ecaf9c749696 100644 (file)
@@ -1,13 +1,13 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:18:18
+  --> $DIR/regions-enum-not-wf.rs:19:18
    |
 LL | enum Ref1<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref1Variant1(RequireOutlives<'a, T>)
+LL |     Ref1Variant1(RequireOutlives<'a, T>),
    |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:23:25
+  --> $DIR/regions-enum-not-wf.rs:24:25
    |
 LL | enum Ref2<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
@@ -16,25 +16,13 @@ LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
    |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:35:1
-   |
-LL |   enum RefDouble<'a, 'b, T> {
-   |   ^                      - help: consider adding an explicit lifetime bound...: `T: 'b`
-   |  _|
-   | |
-LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
-   | |_^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:36:23
+  --> $DIR/regions-enum-not-wf.rs:37:23
    |
 LL | enum RefDouble<'a, 'b, T> {
    |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
+LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0309`.
index 612e22c204fa604edf08506d5d334c0062dc6283..4c21f8db8fad864a88cb742ab75d3b61521ab213 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/deafult-associated-type-bound-1.rs:18:5
    |
 LL |     type U: Clone;
-   |     -------------- required by `X::U`
+   |             ----- required by this bound in `X::U`
 ...
 LL |     default type U = str;
    |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
index a14024c160f76f37b4d0060406be270493a289c1..8c9da81d277efd4b454d86ffdbff2978995ead12 100644 (file)
@@ -11,7 +11,7 @@ error[E0277]: can't compare `&'static B` with `B`
   --> $DIR/deafult-associated-type-bound-2.rs:16:5
    |
 LL |     type U: PartialEq<T>;
-   |     --------------------- required by `X::U`
+   |             ------------ required by this bound in `X::U`
 ...
 LL |     default type U = &'static B;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B`
index 8a94ea658d2d0c72f1d842fdfccc20e663fdd525..f14588e6e023c9aba6bad6125b87f4a1a7e6985a 100644 (file)
@@ -6,7 +6,7 @@
 //~^^ WARNING the feature `generic_associated_types` is incomplete
 
 trait X {
-    type U<'a>: PartialEq<&'a Self>;
+    type U<'a>: PartialEq<&'a Self> where Self: 'a;
     fn unsafe_compare<'b>(x: Option<Self::U<'b>>, y: Option<&'b Self>) {
         match (x, y) {
             (Some(a), Some(b)) => a == b,
index 556feda642b54953534459261e1bc267c2df7ba2..f145b90f216ab9df0651e26921cfa2bdd7ff9ed6 100644 (file)
@@ -18,8 +18,8 @@ LL | #![feature(generic_associated_types)]
 error[E0277]: can't compare `T` with `T`
   --> $DIR/deafult-generic-associated-type-bound.rs:19:5
    |
-LL |     type U<'a>: PartialEq<&'a Self>;
-   |     -------------------------------- required by `X::U`
+LL |     type U<'a>: PartialEq<&'a Self> where Self: 'a;
+   |                 ------------------- required by this bound in `X::U`
 ...
 LL |     default type U<'a> = &'a T;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T`
diff --git a/src/test/ui/specialization/issue-38091-2.rs b/src/test/ui/specialization/issue-38091-2.rs
new file mode 100644 (file)
index 0000000..9ed0b24
--- /dev/null
@@ -0,0 +1,28 @@
+// build-fail
+//~^ ERROR overflow evaluating the requirement `i32: Check`
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Iterate<'a> {
+    type Ty: Valid;
+    fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T
+where
+    T: Check,
+{
+    default type Ty = ();
+    default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+impl Valid for () {}
+
+fn main() {
+    Iterate::iterate(0);
+}
diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr
new file mode 100644 (file)
index 0000000..a314c26
--- /dev/null
@@ -0,0 +1,16 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-38091-2.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error[E0275]: overflow evaluating the requirement `i32: Check`
+   |
+   = note: required because of the requirements on the impl of `Iterate` for `i32`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/specialization/issue-38091.rs b/src/test/ui/specialization/issue-38091.rs
new file mode 100644 (file)
index 0000000..5b39836
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Iterate<'a> {
+    type Ty: Valid;
+    fn iterate(self);
+}
+impl<'a, T> Iterate<'a> for T
+where
+    T: Check,
+{
+    default type Ty = ();
+    //~^ ERROR the trait bound `(): Valid` is not satisfied
+    default fn iterate(self) {}
+}
+
+trait Check {}
+impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
+
+trait Valid {}
+
+fn main() {
+    Iterate::iterate(0);
+}
diff --git a/src/test/ui/specialization/issue-38091.stderr b/src/test/ui/specialization/issue-38091.stderr
new file mode 100644 (file)
index 0000000..6be0f26
--- /dev/null
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-38091.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error[E0277]: the trait bound `(): Valid` is not satisfied
+  --> $DIR/issue-38091.rs:12:5
+   |
+LL |     type Ty: Valid;
+   |              ----- required by this bound in `Iterate::Ty`
+...
+LL |     default type Ty = ();
+   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
index be7196a63ce1dd09bc94bf860b4d0f718431ccd8..3935a4a5f9931b863c1efb910c99f862f1b66bb7 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied
   --> $DIR/issue-44861.rs:21:5
    |
 LL |     type Data2: CoerceUnsized<*const [u8]>;
-   |     --------------------------------------- required by `Smartass::Data2`
+   |                 -------------------------- required by this bound in `Smartass::Data2`
 ...
 LL |     default type Data2 = ();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()`
index ee5c0615927a8c352261c098c668e7ed25168a48..f3f8b022b01e12309f19b125aa03bf9c352bbfcd 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `MyStruct: Default` is not satisfied
   --> $DIR/issue-59435.rs:11:5
    |
 LL |     type MyType: Default;
-   |     --------------------- required by `MyTrait::MyType`
+   |                  ------- required by this bound in `MyTrait::MyType`
 ...
 LL |     default type MyType = MyStruct;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `MyStruct`
index cc3a2b9419caf00b534f84325439ed7d00af08b9..d826222a06ae5d95fbd5838bc2b3fac95821e218 100644 (file)
@@ -5,8 +5,6 @@ LL | fn foo() -> impl Bar {
    |             ^^^^^^^^ the trait `Bar` is not implemented for `()`
 LL |     5;
    |      - consider removing this semicolon
-   |
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
 
index 394512c57947455366e35103fbc590c4e96d5145..4954a8a6965be828ed807a35323845ec784e9797 100644 (file)
@@ -1,5 +1,4 @@
-// Running rustfix would cause the same suggestion to be applied multiple times, which results in
-// invalid code.
+// check-pass
 
 trait Parent {
     type Ty;
@@ -15,11 +14,8 @@ impl<A, T> Child<A> for ChildWrapper<T> where T: Child<A> {}
 struct ParentWrapper<T>(T);
 
 impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
-    //~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
     type Ty = A;
     type Assoc = ChildWrapper<T::Assoc>;
-    //~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
-    //~| ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
 }
 
 fn main() {}
diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr
deleted file mode 100644 (file)
index a8ea214..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
-  --> $DIR/missing-assoc-type-bound-restriction.rs:17:19
-   |
-LL | trait Parent {
-   |       ------ required by a bound in this
-LL |     type Ty;
-LL |     type Assoc: Child<Self::Ty>;
-   |                 --------------- required by this bound in `Parent`
-...
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
-   |                   ^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
-   |
-help: consider further restricting the associated type
-   |
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> where <T as Parent>::Assoc: Child<A> {
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
-  --> $DIR/missing-assoc-type-bound-restriction.rs:20:18
-   |
-LL | trait Parent {
-   |       ------ required by a bound in this
-LL |     type Ty;
-LL |     type Assoc: Child<Self::Ty>;
-   |                 --------------- required by this bound in `Parent`
-...
-LL |     type Assoc = ChildWrapper<T::Assoc>;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
-   |
-   = note: required because of the requirements on the impl of `Child<A>` for `ChildWrapper<<T as Parent>::Assoc>`
-help: consider further restricting the associated type
-   |
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> where <T as Parent>::Assoc: Child<A> {
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
-  --> $DIR/missing-assoc-type-bound-restriction.rs:20:5
-   |
-LL | trait Parent {
-   |       ------ required by a bound in this
-LL |     type Ty;
-LL |     type Assoc: Child<Self::Ty>;
-   |                 --------------- required by this bound in `Parent`
-...
-LL |     type Assoc = ChildWrapper<T::Assoc>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
-   |
-help: consider further restricting the associated type
-   |
-LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> where <T as Parent>::Assoc: Child<A> {
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index 0dd1b2a59eb9adf26076f2c4aecc95b2fea70491..4aa0ad219cf25fc1c26e03255af628b6f9fdb4c3 100644 (file)
@@ -8,6 +8,7 @@ LL |     for (i, _) in &v.iter().enumerate() {
    |                   help: consider removing the leading `&`-reference
    |
    = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required by `into_iter`
 
 error: aborting due to previous error
index 5c2efdb197f8c3403e60b18ee7f366c46e03aa9c..15c4b7fcb8b3b089ba3950c18a06c84aec08b08d 100644 (file)
@@ -8,6 +8,7 @@ LL |     for (i, _) in & & & & &v.iter().enumerate() {
    |                   help: consider removing 5 leading `&`-references
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required by `into_iter`
 
 error: aborting due to previous error
index c7fbd3d9bd9617053bef6f2ba7ac8d3c2198aa12..0bd6d956aff97196e00bb9d17151f98feeba0814 100644 (file)
@@ -12,6 +12,7 @@ LL | |          .enumerate() {
    | |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
    = note: required by `into_iter`
 
 error: aborting due to previous error
diff --git a/src/test/ui/traits/check-trait-object-bounds-1.rs b/src/test/ui/traits/check-trait-object-bounds-1.rs
new file mode 100644 (file)
index 0000000..b1f124c
--- /dev/null
@@ -0,0 +1,14 @@
+// Check that we validate associated type bounds for trait objects
+
+trait X {
+    type Y: Clone;
+}
+
+fn f<T: X + ?Sized>() {
+    None::<T::Y>.clone();
+}
+
+fn main() {
+    f::<dyn X<Y = str>>();
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
diff --git a/src/test/ui/traits/check-trait-object-bounds-1.stderr b/src/test/ui/traits/check-trait-object-bounds-1.stderr
new file mode 100644 (file)
index 0000000..170ed6e
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `str: Clone` is not satisfied
+  --> $DIR/check-trait-object-bounds-1.rs:12:5
+   |
+LL | fn f<T: X + ?Sized>() {
+   |         - required by this bound in `f`
+...
+LL |     f::<dyn X<Y = str>>();
+   |     ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/check-trait-object-bounds-2-ok.rs b/src/test/ui/traits/check-trait-object-bounds-2-ok.rs
new file mode 100644 (file)
index 0000000..1422dda
--- /dev/null
@@ -0,0 +1,15 @@
+// Make sure that we're handling bound lifetimes correctly when validating trait
+// bounds.
+// run-pass
+
+trait X<'a> {
+    type F: FnOnce(&i32) -> &'a i32;
+}
+
+fn f<T: for<'r> X<'r> + ?Sized>() {
+    None::<T::F>.map(|f| f(&0));
+}
+
+fn main() {
+    f::<dyn for<'x> X<'x, F = fn(&i32) -> &'x i32>>();
+}
diff --git a/src/test/ui/traits/check-trait-object-bounds-2.rs b/src/test/ui/traits/check-trait-object-bounds-2.rs
new file mode 100644 (file)
index 0000000..eb2fb6e
--- /dev/null
@@ -0,0 +1,15 @@
+// Check that we validate associated type bounds for trait objects when they
+// have bound lifetimes
+
+trait X<'a> {
+    type F: FnOnce(&i32) -> &'a i32;
+}
+
+fn f<T: for<'r> X<'r> + ?Sized>() {
+    None::<T::F>.map(|f| f(&0));
+}
+
+fn main() {
+    f::<dyn for<'x> X<'x, F = i32>>();
+    //~^ expected a `FnOnce<(&i32,)>` closure, found `i32`
+}
diff --git a/src/test/ui/traits/check-trait-object-bounds-2.stderr b/src/test/ui/traits/check-trait-object-bounds-2.stderr
new file mode 100644 (file)
index 0000000..04e2348
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32`
+  --> $DIR/check-trait-object-bounds-2.rs:13:5
+   |
+LL | fn f<T: for<'r> X<'r> + ?Sized>() {
+   |         ------------- required by this bound in `f`
+...
+LL |     f::<dyn for<'x> X<'x, F = i32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
+   |
+   = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/check-trait-object-bounds-3.rs b/src/test/ui/traits/check-trait-object-bounds-3.rs
new file mode 100644 (file)
index 0000000..ba04fd9
--- /dev/null
@@ -0,0 +1,20 @@
+// Check that we validate associated type bounds for trait objects
+
+trait X<'a> {
+    type Y: Into<&'static str> + From<&'a str>;
+}
+
+fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str {
+    T::Y::from(s).into()
+}
+
+pub fn main() {
+    let z;
+    {
+        let s = String::from("abcdef");
+        z = f::<dyn X<Y = &str>>(&s);
+        //~^ ERROR `s` does not live long enough
+    }
+
+    println!("{}", z)
+}
diff --git a/src/test/ui/traits/check-trait-object-bounds-3.stderr b/src/test/ui/traits/check-trait-object-bounds-3.stderr
new file mode 100644 (file)
index 0000000..ade552c
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/check-trait-object-bounds-3.rs:15:34
+   |
+LL |         z = f::<dyn X<Y = &str>>(&s);
+   |             ---------------------^^-
+   |             |                    |
+   |             |                    borrowed value does not live long enough
+   |             argument requires that `s` is borrowed for `'static`
+LL |
+LL |     }
+   |     - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/traits/check-trait-object-bounds-4.rs b/src/test/ui/traits/check-trait-object-bounds-4.rs
new file mode 100644 (file)
index 0000000..e9ca156
--- /dev/null
@@ -0,0 +1,17 @@
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Super {
+    type Y: Clone;
+}
+
+trait X: Super {}
+
+fn f<T: X + ?Sized>() {
+    None::<T::Y>.clone();
+}
+
+fn main() {
+    f::<dyn X<Y = str>>();
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
+}
diff --git a/src/test/ui/traits/check-trait-object-bounds-4.stderr b/src/test/ui/traits/check-trait-object-bounds-4.stderr
new file mode 100644 (file)
index 0000000..fc9f31c
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `str: Clone` is not satisfied
+  --> $DIR/check-trait-object-bounds-4.rs:15:5
+   |
+LL | fn f<T: X + ?Sized>() {
+   |         - required by this bound in `f`
+...
+LL |     f::<dyn X<Y = str>>();
+   |     ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/check-trait-object-bounds-5.rs b/src/test/ui/traits/check-trait-object-bounds-5.rs
new file mode 100644 (file)
index 0000000..7d733ad
--- /dev/null
@@ -0,0 +1,27 @@
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Is {
+    type T;
+}
+
+impl<U> Is for U {
+    type T = U;
+}
+
+trait Super {
+    type V;
+}
+
+trait Obj: Super {
+    type U: Is<T = Self::V>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i64>) {
+    is_obj(x)
+    //~^ type mismatch resolving `<i32 as Is>::T == i64`
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/check-trait-object-bounds-5.stderr b/src/test/ui/traits/check-trait-object-bounds-5.stderr
new file mode 100644 (file)
index 0000000..bd2b789
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<i32 as Is>::T == i64`
+  --> $DIR/check-trait-object-bounds-5.rs:23:5
+   |
+LL | fn is_obj<T: ?Sized + Obj>(_: &T) {}
+   |                       --- required by this bound in `is_obj`
+...
+LL |     is_obj(x)
+   |     ^^^^^^ expected `i64`, found `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/traits/check-trait-object-bounds-6.rs b/src/test/ui/traits/check-trait-object-bounds-6.rs
new file mode 100644 (file)
index 0000000..cb196d6
--- /dev/null
@@ -0,0 +1,24 @@
+// Check that we validate associated type bounds on super traits for trait
+// objects
+
+trait Is {
+    type T;
+}
+
+impl<U> Is for U {
+    type T = U;
+}
+
+trait Obj {
+    type U: Is<T = Self::V>;
+    type V;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i64>) {
+    is_obj(x)
+    //~^ ERROR type mismatch resolving `<i32 as Is>::T == i64`
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/check-trait-object-bounds-6.stderr b/src/test/ui/traits/check-trait-object-bounds-6.stderr
new file mode 100644 (file)
index 0000000..ea1fdaf
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<i32 as Is>::T == i64`
+  --> $DIR/check-trait-object-bounds-6.rs:20:5
+   |
+LL | fn is_obj<T: ?Sized + Obj>(_: &T) {}
+   |                       --- required by this bound in `is_obj`
+...
+LL |     is_obj(x)
+   |     ^^^^^^ expected `i64`, found `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
index cbddef082be6732465e712fc4a213ecd20134c36..98bfcb8d67b516eafb8948ee05d6a0c8a48f32bb 100644 (file)
@@ -24,11 +24,13 @@ struct Runtime<DB: Database> {
     _storage: Box<DB::Storage>,
 }
 struct SalsaStorage {
-    _parse: <ParseQuery as Query<RootDatabase>>::Data, //~ ERROR overflow
+    _parse: <ParseQuery as Query<RootDatabase>>::Data,
 }
 
 impl Database for RootDatabase {
-    type Storage = SalsaStorage; //~ ERROR overflow
+    // This would also be an error if we didn't abort compilation on the error
+    // above.
+    type Storage = SalsaStorage;
 }
 impl HasQueryGroup for RootDatabase {}
 impl<DB> Query<DB> for ParseQuery
@@ -65,6 +67,7 @@ pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 {
     // we used to fail to report an error here because we got the
     // caching wrong.
     SourceDatabase::parse(db);
+    //~^ ERROR overflow
     22
 }
 
index 25b1f427f3a1685df0dcfc3dba1135cecb219ced..b2702d977f8b6c3152041abe0057f912e7d274e5 100644 (file)
@@ -1,27 +1,19 @@
-error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase`
-  --> $DIR/cycle-cache-err-60010.rs:27:13
+error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
+  --> $DIR/cycle-cache-err-60010.rs:69:5
    |
-LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
-
-error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
-  --> $DIR/cycle-cache-err-60010.rs:31:20
-   |
-LL | trait Database {
-   |       -------- required by a bound in this
-LL |     type Storage;
-   |     ------------- required by this bound in `Database`
+LL |     fn parse(&self) {
+   |     --------------- required by `SourceDatabase::parse`
 ...
-LL |     type Storage = SalsaStorage;
-   |                    ^^^^^^^^^^^^
+LL |     SourceDatabase::parse(db);
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: required because it appears within the type `*const SalsaStorage`
+   = note: required because it appears within the type `Unique<SalsaStorage>`
+   = note: required because it appears within the type `Box<SalsaStorage>`
+   = note: required because it appears within the type `Runtime<RootDatabase>`
    = note: required because it appears within the type `RootDatabase`
    = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase`
-   = note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
-   = note: required because it appears within the type `SalsaStorage`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/traits/trait-object-bounds-cycle-1.rs b/src/test/ui/traits/trait-object-bounds-cycle-1.rs
new file mode 100644 (file)
index 0000000..3146764
--- /dev/null
@@ -0,0 +1,24 @@
+// Check that we don't have a cycle when we try to normalize `Self::U` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+    type T;
+}
+
+impl<U> Is for U {
+    type T = U;
+}
+
+trait Obj {
+    type U: Is<T = Self::U>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32>) {
+    is_obj(x)
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-object-bounds-cycle-2.rs b/src/test/ui/traits/trait-object-bounds-cycle-2.rs
new file mode 100644 (file)
index 0000000..4c1df38
--- /dev/null
@@ -0,0 +1,28 @@
+// Check that we don't have a cycle when we try to normalize `Self::V` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+    type T;
+}
+
+impl<U> Is for U {
+    type T = U;
+}
+
+trait Super {
+    type V;
+}
+
+trait Obj: Super {
+    type U: Is<T = Self::V>;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i32>) {
+    is_obj(x)
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-object-bounds-cycle-3.rs b/src/test/ui/traits/trait-object-bounds-cycle-3.rs
new file mode 100644 (file)
index 0000000..55726a5
--- /dev/null
@@ -0,0 +1,25 @@
+// Check that we don't have a cycle when we try to normalize `Self::V` in the
+// bound below.
+
+// check-pass
+
+trait Is {
+    type T;
+}
+
+impl<U> Is for U {
+    type T = U;
+}
+
+trait Obj {
+    type U: Is<T = Self::V>;
+    type V;
+}
+
+fn is_obj<T: ?Sized + Obj>(_: &T) {}
+
+fn f(x: &dyn Obj<U = i32, V = i32>) {
+    is_obj(x)
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-object-bounds-cycle-4.rs b/src/test/ui/traits/trait-object-bounds-cycle-4.rs
new file mode 100644 (file)
index 0000000..f83cb75
--- /dev/null
@@ -0,0 +1,25 @@
+// Check that we don't have a cycle when we try to normalize `Self::U` in the
+// bound below. Make sure that having a lifetime on the trait object doesn't break things
+
+// check-pass
+
+trait Is {
+    type T;
+}
+
+impl<U> Is for U {
+    type T = U;
+}
+
+trait Obj<'a> {
+    type U: Is<T = Self::V>;
+    type V;
+}
+
+fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {}
+
+fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) {
+    is_obj(x)
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs b/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs
new file mode 100644 (file)
index 0000000..9d83472
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+
+use std::any::Any;
+
+trait A<T>: Any {
+    fn m(&self) {}
+}
+
+impl<S, T: 'static> A<S> for T {}
+
+fn call_obj<'a>() {
+    let obj: &dyn A<&'a ()> = &();
+    obj.m();
+}
+
+fn main() {}
index 63dd141920025a8a6ac7163ca84b1f52881eaebc..463b55d8581f8512d66b06ff0294f290fd6ac321 100644 (file)
@@ -9,6 +9,7 @@ pub trait Magic {
 }
 impl<T: Magic> Magic for T {
     type X = Self;
+    //~^ ERROR E0277
 }
 
 fn check<T: Trait>() {}
index f66cfce55c90316011b95c3be44dc4abf198ed17..996544ae5162da06080dfb7523766174a43e23d2 100644 (file)
@@ -1,5 +1,19 @@
+error[E0277]: `T` cannot be shared between threads safely
+  --> $DIR/traits-inductive-overflow-two-traits.rs:11:5
+   |
+LL |     type X: Trait;
+   |             ----- required by this bound in `Magic::X`
+...
+LL |     type X = Self;
+   |     ^^^^^^^^^^^^^^ `T` cannot be shared between threads safely
+   |
+help: consider further restricting this bound
+   |
+LL | impl<T: Magic + Sync> Magic for T {
+   |               ^^^^^^
+
 error[E0275]: overflow evaluating the requirement `*mut (): Magic`
-  --> $DIR/traits-inductive-overflow-two-traits.rs:19:5
+  --> $DIR/traits-inductive-overflow-two-traits.rs:20:5
    |
 LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
    |              ----- required by this bound in `wizard`
@@ -7,6 +21,7 @@ LL | fn wizard<T: Magic>() { check::<<T as Magic>::X>(); }
 LL |     wizard::<*mut ()>();
    |     ^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0275`.
+Some errors have detailed explanations: E0275, E0277.
+For more information about an error, try `rustc --explain E0275`.
index c338294913f6c798f7203d8c3442e14a24c92477..496ba145810fbc526e989d9a195abeedf05e3412 100644 (file)
@@ -14,7 +14,9 @@ pub fn main() {
 
     let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
 
-    let res: () = try { }; //~ the trait bound `(): Try` is not satisfied
+    let res: () = try { };
+    //~^ ERROR the trait bound `(): Try` is not satisfied
+    //~| ERROR the trait bound `(): Try` is not satisfied
 
     let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied
 }
index 03d5d3661ddf7088d92c1326a625959f6e7a72b1..cadf3a841c961e5ea94c58da5d0bdbf98dcf25b7 100644 (file)
@@ -26,22 +26,28 @@ LL |     let res: Result<i32, i32> = try { };
    |                                       ^ expected `i32`, found `()`
 
 error[E0277]: the trait bound `(): Try` is not satisfied
-  --> $DIR/try-block-bad-type.rs:17:23
+  --> $DIR/try-block-bad-type.rs:17:25
    |
 LL |     let res: () = try { };
-   |                       ^^^ the trait `Try` is not implemented for `()`
+   |                         ^ the trait `Try` is not implemented for `()`
    |
    = note: required by `from_ok`
 
+error[E0277]: the trait bound `(): Try` is not satisfied
+  --> $DIR/try-block-bad-type.rs:17:25
+   |
+LL |     let res: () = try { };
+   |                         ^ the trait `Try` is not implemented for `()`
+
 error[E0277]: the trait bound `i32: Try` is not satisfied
-  --> $DIR/try-block-bad-type.rs:19:24
+  --> $DIR/try-block-bad-type.rs:21:26
    |
 LL |     let res: i32 = try { 5 };
-   |                        ^^^^^ the trait `Try` is not implemented for `i32`
+   |                          ^ the trait `Try` is not implemented for `i32`
    |
    = note: required by `from_ok`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0271, E0277.
 For more information about an error, try `rustc --explain E0271`.
index bc0f5bb6505b2ad554bf515583b14831af1c8990..75a4e8d065cab65dcd42b632014f1ff47ac30610 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `bool: Try` is not satisfied
-  --> $DIR/try-block-in-while.rs:6:15
+  --> $DIR/try-block-in-while.rs:6:17
    |
 LL |     while try { false } {}
-   |               ^^^^^^^^^ the trait `Try` is not implemented for `bool`
+   |                 ^^^^^ the trait `Try` is not implemented for `bool`
    |
    = note: required by `from_ok`
 
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs
new file mode 100644 (file)
index 0000000..c035915
--- /dev/null
@@ -0,0 +1,19 @@
+// Make sure that we check that impl trait types implement the traits that they
+// claim to.
+
+#![feature(type_alias_impl_trait)]
+
+type X<T> = impl Clone;
+//~^ ERROR the trait bound `T: Clone` is not satisfied
+
+fn f<T: Clone>(t: T) -> X<T> {
+    t
+}
+
+fn g<T>(o: Option<X<T>>) -> Option<X<T>> {
+    o.clone()
+}
+
+fn main() {
+    g(None::<X<&mut ()>>);
+}
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
new file mode 100644 (file)
index 0000000..26a2f41
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `T: Clone` is not satisfied
+  --> $DIR/bounds-are-checked-2.rs:6:13
+   |
+LL | type X<T> = impl Clone;
+   |             ^^^^^^^^^^ the trait `Clone` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type X<T: Clone> = impl Clone;
+   |         ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs
new file mode 100644 (file)
index 0000000..759bf4f
--- /dev/null
@@ -0,0 +1,25 @@
+// Make sure that we check that impl trait types implement the traits that they
+// claim to.
+
+#![feature(type_alias_impl_trait)]
+
+type X<'a> = impl Into<&'static str> + From<&'a str>;
+//~^ ERROR mismatched types
+
+fn f<'a: 'static>(t: &'a str) -> X<'a> {
+    //~^ WARNING unnecessary lifetime parameter
+    t
+}
+
+fn extend_lt<'a>(o: &'a str) -> &'static str {
+    X::<'_>::from(o).into()
+}
+
+fn main() {
+    let r =
+    {
+        let s = "abcdef".to_string();
+        extend_lt(&s)
+    };
+    println!("{}", r);
+}
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr
new file mode 100644 (file)
index 0000000..d5fafe0
--- /dev/null
@@ -0,0 +1,26 @@
+warning: unnecessary lifetime parameter `'a`
+  --> $DIR/bounds-are-checked.rs:9:6
+   |
+LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
+   |      ^^^^^^^^^^^
+   |
+   = help: you can use the `'static` lifetime directly, in place of `'a`
+
+error[E0308]: mismatched types
+  --> $DIR/bounds-are-checked.rs:6:14
+   |
+LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected trait `From<&'a str>`
+              found trait `From<&'static str>`
+note: the lifetime `'a` as defined on the item at 6:8...
+  --> $DIR/bounds-are-checked.rs:6:8
+   |
+LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
+   |        ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
index 898dab1b0b9602808b58671eb45540e2e7b3be66..c17d595dbb3ad23e07b33f73bad8e6b4dee960d8 100644 (file)
@@ -1,11 +1,11 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![feature(type_alias_impl_trait)]
 
 use std::fmt::Debug;
 
 fn main() {}
 
-type Two<T, U> = impl Debug;
+type Two<T: Debug, U> = impl Debug;
 
 fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
     (t, 4u32)
index ac8773104147e21444b0b731bafdc45742cd26d0..dd2f202cf5dc0305b8d5283f31412de0093f5066 100644 (file)
@@ -6,12 +6,14 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
+//~| ERROR `U` doesn't implement `Debug`
 
 fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u)
 }
 
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-//~^ concrete type differs from previous
+    //~^ concrete type differs from previous
     (u, t)
 }
index 1ddbc0c8d6a8e25db73f5fd5a40bff4e595ad760..b4aed4a6323bff2728d37f629dd22e8df4b0815e 100644 (file)
@@ -1,14 +1,39 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use5.rs:14:1
+  --> $DIR/generic_duplicate_param_use5.rs:16:1
    |
 LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use5.rs:10:1
+  --> $DIR/generic_duplicate_param_use5.rs:12:1
    |
 LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use5.rs:8:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(T, U)`
+help: consider restricting type parameter `T`
+   |
+LL | type Two<T: Debug, U> = impl Debug;
+   |           ^^^^^^^
+
+error[E0277]: `U` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use5.rs:8:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(T, U)`
+help: consider restricting type parameter `U`
+   |
+LL | type Two<T, U: Debug> = impl Debug;
+   |              ^^^^^^^
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index 6cbb3069ecd4b88d2e6b142464b7489ac56e46d3..d54d3cd62e0209c91734996228a2c51b1c33b103 100644 (file)
@@ -6,12 +6,13 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
 
 fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, t)
 }
 
 fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-    //~^ concrete type differs from previous
+    //~^ ERROR concrete type differs from previous
     (u, t)
 }
index ebd07b7c300f1928c31de04650016a53571e079e..22e4d006674929a6a3f750583b0442a7f530e24a 100644 (file)
@@ -1,14 +1,27 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use6.rs:14:1
+  --> $DIR/generic_duplicate_param_use6.rs:15:1
    |
 LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use6.rs:10:1
+  --> $DIR/generic_duplicate_param_use6.rs:11:1
    |
 LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use6.rs:8:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(T, T)`
+help: consider restricting type parameter `T`
+   |
+LL | type Two<T: Debug, U> = impl Debug;
+   |           ^^^^^^^
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index 712a6539f0153720b887aaa6452e784221185b0d..feebf81eef2a7f87274fe42a3b7952fa261737f4 100644 (file)
@@ -1,11 +1,11 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 #![feature(type_alias_impl_trait)]
 
 use std::fmt::Debug;
 
 fn main() {}
 
-type Two<A, B> = impl Debug;
+type Two<A: Debug, B> = impl Debug;
 
 fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
     (t, t)
index 777ded52609b8abb4c217a0b896d5a4ab5c54f0e..4a723b64cdc4f372c517d0b808f9562c24683c8b 100644 (file)
@@ -5,12 +5,13 @@
 fn main() {}
 
 type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
 
 fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
     (t, 4u32)
 }
 
 fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-//~^ concrete type differs from previous
+    //~^ concrete type differs from previous
     (u, 4u32)
 }
index 4778ee5155cf058c17fa7df52fad2fd1e1a478cf..82da704c9ee22d8615ee2292de4b0fe184495619 100644 (file)
@@ -1,14 +1,27 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use8.rs:13:1
+  --> $DIR/generic_duplicate_param_use8.rs:14:1
    |
 LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use8.rs:9:1
+  --> $DIR/generic_duplicate_param_use8.rs:10:1
    |
 LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use8.rs:7:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(T, u32)`
+help: consider restricting type parameter `T`
+   |
+LL | type Two<T: Debug, U> = impl Debug;
+   |           ^^^^^^^
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index 491e6647f45d048085e256609b594d2d992d3a1b..747081933172b50aca38ca1e5efeaca93a347e5b 100644 (file)
@@ -5,6 +5,9 @@
 fn main() {}
 
 type Two<A, B> = impl Debug;
+//~^ ERROR the trait bound `A: Foo` is not satisfied in `(A, B, <A as Foo>::Bar)`
+//~| ERROR `A` doesn't implement `Debug`
+//~| ERROR `B` doesn't implement `Debug`
 
 trait Foo {
     type Bar: Debug;
index 247b042f61e058af52199e2ae069a4873d483da5..63aa0f8a81c9a7218972ce4fecb362d582297b81 100644 (file)
@@ -1,14 +1,51 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use9.rs:18:1
+  --> $DIR/generic_duplicate_param_use9.rs:21:1
    |
 LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use9.rs:14:1
+  --> $DIR/generic_duplicate_param_use9.rs:17:1
    |
 LL | fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, <A as Foo>::Bar)`
+  --> $DIR/generic_duplicate_param_use9.rs:7:18
+   |
+LL | type Two<A, B> = impl Debug;
+   |                  ^^^^^^^^^^ within `(A, B, <A as Foo>::Bar)`, the trait `Foo` is not implemented for `A`
+   |
+   = note: required because it appears within the type `(A, B, <A as Foo>::Bar)`
+help: consider restricting type parameter `A`
+   |
+LL | type Two<A: Foo, B> = impl Debug;
+   |           ^^^^^
+
+error[E0277]: `A` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use9.rs:7:18
+   |
+LL | type Two<A, B> = impl Debug;
+   |                  ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)`
+help: consider restricting type parameter `A`
+   |
+LL | type Two<A: Debug, B> = impl Debug;
+   |           ^^^^^^^
+
+error[E0277]: `B` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use9.rs:7:18
+   |
+LL | type Two<A, B> = impl Debug;
+   |                  ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(A, B, <A as Foo>::Bar)`
+help: consider restricting type parameter `B`
+   |
+LL | type Two<A, B: Debug> = impl Debug;
+   |              ^^^^^^^
+
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index 76654d7a718b8175f77b0fdfb44e16c2c77b2338..ffd6f34c4b00e6879ae81a40ce1d0ed05a8214f2 100644 (file)
@@ -18,6 +18,24 @@ LL | type WrongGeneric<T> = impl 'static;
    = note:     expected type `i32`
            found opaque type `impl Sized`
 
-error: aborting due to 2 previous errors
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/generic_type_does_not_live_long_enough.rs:14:30
+   |
+LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+   |                              ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+   |
+LL | type WrongGeneric<T> = impl 'static;
+   |                        ^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+   = note: ...so that the type `T` will meet its required lifetime bounds
+
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0310.
+For more information about an error, try `rustc --explain E0308`.
index c0f939a50482fa7f657aa65406d36c7dc46de792..f6d490960365adf64391a9c25ea909f45d7774ab 100644 (file)
@@ -8,7 +8,8 @@ fn main() {
 
 type WrongGeneric<T> = impl 'static;
 //~^ ERROR the parameter type `T` may not live long enough
-//~^^ ERROR: at least one trait must be specified
+//~| ERROR the parameter type `T` may not live long enough
+//~| ERROR: at least one trait must be specified
 
 fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
     t
index 18d8daa05e63d168fb413a3ca948c39316897749..4924c447d7e40485888cc313e9dc731ba6072012 100644 (file)
@@ -27,7 +27,16 @@ LL | type WrongGeneric<T> = impl 'static;
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
 
-error: aborting due to 3 previous errors
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
+   |
+LL | type WrongGeneric<T> = impl 'static;
+   |                        ^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+   = note: ...so that the type `T` will meet its required lifetime bounds
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
index 8c9cb742fac91f12814c64af1ed4806180b25a04..790aea87510e6306e864f8191ab44cb87a6a54e7 100644 (file)
@@ -1,14 +1,33 @@
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:21:9
+  --> $DIR/issue-57611-trait-alias.rs:25:9
    |
 LL |         |x| x
    |         ^^^^^
 
 error: higher-ranked subtype error
-  --> $DIR/issue-57611-trait-alias.rs:21:9
+  --> $DIR/issue-57611-trait-alias.rs:25:9
    |
 LL |         |x| x
    |         ^^^^^
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r> Fn<(&'r X,)>`
+              found type `Fn<(&'static X,)>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `FnOnce<(&X,)>`
+              found type `FnOnce<(&'static X,)>`
+
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
index 782eb0fb3df5e8993f02751fdc92f37471d1ef71..3372b81404ecb4da25879f625de145602ad95201 100644 (file)
@@ -16,6 +16,10 @@ trait Foo {
 impl Foo for X {
     type Bar = impl Baz<Self, Self>;
     //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
+    //~| ERROR mismatched types
 
     fn bar(&self) -> Self::Bar {
         |x| x
index a8706aa9a241f57821e142009185eb2b29ea1f94..5e2a8db02867f3b70b8d006914b995985ec26c7c 100644 (file)
@@ -7,6 +7,42 @@ LL |     type Bar = impl Baz<Self, Self>;
    = note: expected type `FnOnce<(&X,)>`
               found type `FnOnce<(&X,)>`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r> Fn<(&'r X,)>`
+              found type `Fn<(&'<empty> X,)>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `FnOnce<(&X,)>`
+              found type `FnOnce<(&'<empty> X,)>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r> Fn<(&'r X,)>`
+              found type `Fn<(&'<empty> X,)>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `FnOnce<(&X,)>`
+              found type `FnOnce<(&'<empty> X,)>`
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index bf2d612fcdb411511500d8dc3b6494582a040522..905248fb33755992d0ec2637edc0f48a0949304c 100644 (file)
@@ -15,7 +15,6 @@ LL |     type Item = impl Bug;
    |
    = help: the following implementations were found:
              <&() as Bug>
-   = note: the return type of a function must have a statically known size
 
 error: could not find defining uses
   --> $DIR/issue-60371.rs:8:17
index 9ad181b3684c6dd1382aeeccfd747b3e9a779e6b..8615b3f741bf53ea43ddb27cebcfe38b5b8f4b0d 100644 (file)
@@ -6,7 +6,6 @@ LL | type Closure = impl FnOnce();
    |
    = note: expected opaque type `impl FnOnce<()>`
                 found unit type `()`
-   = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
 
index 209134acf01f9723d50d9421bdf0caeb0074c306..80192d19af98b5cd9d63f5f89b664570a558dc1d 100644 (file)
@@ -70,14 +70,14 @@ fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
 }
 
 trait Trait {}
-type GenericBound<'a, T: Trait> = impl Sized + 'a;
+type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
 
 fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
     t
 }
 
 mod pass_through {
-    pub type Passthrough<T> = impl Sized + 'static;
+    pub type Passthrough<T: 'static> = impl Sized + 'static;
 
     fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
         t
index 9e710c15fdbcec2db66d7a897a60209cc61ffe20..a2bf963044582278e921e1872847b920b8de665f 100644 (file)
@@ -5,6 +5,7 @@ LL |     <i32 as Add<u32>>::add(1, 2);
    |     ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
+   = note: required by `add`
 
 error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:6:28
index 2ab257ca88e3bdedc0794f4ea18ea1c617e0a8ef..d2a322e1223c660c6ff0b5977769f0b71ee76750 100644 (file)
@@ -3,6 +3,7 @@
 use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{Opaque, PredicateAtom::Trait};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
@@ -62,9 +63,10 @@ fn check_fn(
         }
         let ret_ty = utils::return_ty(cx, hir_id);
         if let Opaque(id, subst) = *ret_ty.kind() {
-            let preds = cx.tcx.predicates_of(id).instantiate(cx.tcx, subst);
+            let preds = cx.tcx.explicit_item_bounds(id);
             let mut is_future = false;
-            for p in preds.predicates {
+            for &(p, _span) in preds {
+                let p = p.subst(cx.tcx, subst);
                 if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
                     if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
@@ -90,8 +92,13 @@ fn check_fn(
                         |db| {
                             cx.tcx.infer_ctxt().enter(|infcx| {
                                 for FulfillmentError { obligation, .. } in send_errors {
-                                    infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
-                                    if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
+                                    infcx.maybe_note_obligation_cause_for_async_await(
+                                        db,
+                                        &obligation,
+                                    );
+                                    if let Trait(trait_pred, _) =
+                                        obligation.predicate.skip_binders()
+                                    {
                                         db.note(&format!(
                                             "`{}` doesn't implement `{}`",
                                             trait_pred.self_ty(),
index dadd0f8ebb7c85992fde8064b4805f50201f7a77..e0651f9ab5d6c7e58b1c2840167ca394c72efb0b 100644 (file)
@@ -1667,8 +1667,10 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
             // if return type is impl trait, check the associated types
             if let ty::Opaque(def_id, _) = *ret_ty.kind() {
                 // one of the associated types must be Self
-                for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates {
-                    if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() {
+                for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
+                    if let ty::PredicateAtom::Projection(projection_predicate) =
+                        predicate.skip_binders()
+                    {
                         // walk the associated type and check for Self
                         if contains_ty(projection_predicate.ty, self_ty) {
                             return;
index 96d9905027b628e2f2c14ba8f0d20f2b2d77869f..247effde19b9c14302805ac6bc14f75fe74f5c94 100644 (file)
@@ -1285,9 +1285,10 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         },
         ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
         ty::Opaque(ref def_id, _) => {
-            for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates {
+            for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
                 if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() {
-                    if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
+                    if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some()
+                    {
                         return true;
                     }
                 }