diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3fbe8e39d1e3f..926044bd6a803 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -60,6 +60,20 @@ use rustc_middle::ty::print::with_no_trimmed_paths; mod candidate_assembly; mod confirmation; +/// Whether to consider the binder of higher ranked goals for the `leak_check` when +/// evaluating higher-ranked goals. See #119820 for more info. +/// +/// While this is a bit hacky, it is necessary to match the behavior of the new solver: +/// We eagerly instantiate binders in the new solver, outside of candidate selection, so +/// the leak check inside of candidates does not consider any bound vars from the higher +/// ranked goal. However, we do exit the binder once we're completely finished with a goal, +/// so the leak-check can be used in evaluate by causing nested higher-ranked goals to fail. +#[derive(Debug, Copy, Clone)] +enum LeakCheckHigherRankedGoal { + No, + Yes, +} + #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum IntercrateAmbiguityCause<'tcx> { DownstreamCrate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option> }, @@ -384,7 +398,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut no_candidates_apply = true; for c in candidate_set.vec.iter() { - if self.evaluate_candidate(stack, c)?.may_apply() { + if self + .evaluate_candidate(stack, c, LeakCheckHigherRankedGoal::No)? + .may_apply() + { no_candidates_apply = false; break; } @@ -455,7 +472,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // is needed for specialization. Propagate overflow if it occurs. let mut candidates = candidates .into_iter() - .map(|c| match self.evaluate_candidate(stack, &c) { + .map(|c| match self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::No) { Ok(eval) if eval.may_apply() => { Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) } @@ -545,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PredicateObligation<'tcx>, ) -> Result { debug_assert!(!self.infcx.next_trait_solver()); - self.evaluation_probe(|this| { + self.evaluation_probe(|this, _outer_universe| { let goal = this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); let mut result = this.evaluate_predicate_recursively( @@ -561,13 +578,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + /// Computes the evaluation result of `op`, discarding any constraints. + /// + /// This also runs for leak check to allow higher ranked region errors to impact + /// selection. By default it checks for leaks from all universes created inside of + /// `op`, but this can be overwritten if necessary. fn evaluation_probe( &mut self, - op: impl FnOnce(&mut Self) -> Result, + op: impl FnOnce(&mut Self, &mut ty::UniverseIndex) -> Result, ) -> Result { self.infcx.probe(|snapshot| -> Result { - let outer_universe = self.infcx.universe(); - let result = op(self)?; + let mut outer_universe = self.infcx.universe(); + let result = op(self, &mut outer_universe)?; match self.infcx.leak_check(outer_universe, Some(snapshot)) { Ok(()) => {} @@ -586,9 +608,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } - /// Evaluates the predicates in `predicates` recursively. Note that - /// this applies projections in the predicates, and therefore + /// Evaluates the predicates in `predicates` recursively. This may + /// guide inference. If this is not desired, run it inside of a /// is run within an inference probe. + /// `probe`. #[instrument(skip(self, stack), level = "debug")] fn evaluate_predicates_recursively<'o, I>( &mut self, @@ -1194,7 +1217,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self.candidate_from_obligation(stack) { - Ok(Some(c)) => self.evaluate_candidate(stack, &c), + Ok(Some(c)) => self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::Yes), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), Err(..) => Ok(EvaluatedToErr), @@ -1219,6 +1242,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Further evaluates `candidate` to decide whether all type parameters match and whether nested /// obligations are met. Returns whether `candidate` remains viable after this further /// scrutiny. + /// + /// Depending on the value of [LeakCheckHigherRankedGoal], we may ignore the binder of the goal + /// when eagerly detecting higher ranked region errors via the `leak_check`. See that enum for + /// more info. #[instrument( level = "debug", skip(self, stack), @@ -1229,10 +1256,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>, + leak_check_higher_ranked_goal: LeakCheckHigherRankedGoal, ) -> Result { - let mut result = self.evaluation_probe(|this| { - let candidate = (*candidate).clone(); - match this.confirm_candidate(stack.obligation, candidate) { + let mut result = self.evaluation_probe(|this, outer_universe| { + // We eagerly instantiate higher ranked goals to prevent universe errors + // from impacting candidate selection. This matches the behavior of the new + // solver. This slightly weakens type inference. + // + // In case there are no unresolved type or const variables this + // should still not be necessary to select a unique impl as any overlap + // relying on a universe error from higher ranked goals should have resulted + // in an overlap error in coherence. + let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate); + let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p)); + match leak_check_higher_ranked_goal { + LeakCheckHigherRankedGoal::No => *outer_universe = self.infcx.universe(), + LeakCheckHigherRankedGoal::Yes => {} + } + + match this.confirm_candidate(&obligation, candidate.clone()) { Ok(selection) => { debug!(?selection); this.evaluate_predicates_recursively( @@ -1657,8 +1699,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result { - self.evaluation_probe(|this| { - match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { + self.evaluation_probe(|this, outer_universe| { + // Eagerly instantiate higher ranked goals. + // + // See the comment in `evaluate_candidate` to see why. + let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate); + let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p)); + *outer_universe = self.infcx.universe(); + match this.match_where_clause_trait_ref(&obligation, where_clause_trait_ref) { Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations), Err(()) => Ok(EvaluatedToErr), } diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 6e8452493421d..874c15ce41da8 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1132,7 +1132,6 @@ "ui/generics/issue-98432.rs", "ui/higher-ranked/trait-bounds/issue-100689.rs", "ui/higher-ranked/trait-bounds/issue-102899.rs", -"ui/higher-ranked/trait-bounds/issue-30786.rs", "ui/higher-ranked/trait-bounds/issue-36139-normalize-closure-sig.rs", "ui/higher-ranked/trait-bounds/issue-39292.rs", "ui/higher-ranked/trait-bounds/issue-42114.rs", diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs new file mode 100644 index 0000000000000..b448f0bdc7778 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.rs @@ -0,0 +1,28 @@ +// cc #119820 + +trait Trait {} + +impl Trait for &T {} +impl Trait for u32 {} + +fn hr_bound() +where + for<'a> &'a T: Trait, +{ +} + +fn foo() +where + T: Trait, + for<'a> &'a &'a T: Trait, +{ + // We get a universe error when using the `param_env` candidate + // but are able to successfully use the impl candidate. Without + // the leak check both candidates may apply and we prefer the + // `param_env` candidate in winnowing. + hr_bound::<&T>(); + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR implementation of `Trait` is not general enough +} + +fn main() {} diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr new file mode 100644 index 0000000000000..febe252d7d1d5 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-1.stderr @@ -0,0 +1,26 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/candidate-from-env-universe-err-1.rs:23:5 + | +LL | hr_bound::<&T>(); + | ^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | T: Trait + 'static, + | +++++++++ + +error: implementation of `Trait` is not general enough + --> $DIR/candidate-from-env-universe-err-1.rs:23:5 + | +LL | hr_bound::<&T>(); + | ^^^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `Trait` would have to be implemented for the type `&'0 &T`, for any lifetime `'0`... + = note: ...but `Trait` is actually implemented for the type `&'1 &'1 T`, for some specific lifetime `'1` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr new file mode 100644 index 0000000000000..22ce87c024861 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.current.stderr @@ -0,0 +1,25 @@ +error: lifetime may not live long enough + --> $DIR/candidate-from-env-universe-err-2.rs:14:5 + | +LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() { + | -- lifetime `'a` defined here +LL | impl_hr::(); + | ^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/candidate-from-env-universe-err-2.rs:11:19 + | +LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of `Trait` is not general enough + --> $DIR/candidate-from-env-universe-err-2.rs:14:5 + | +LL | impl_hr::(); + | ^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `T` must implement `Trait<'0, '_>`, for any lifetime `'0`... + = note: ...but it actually implements `Trait<'1, '_>`, for some specific lifetime `'1` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr new file mode 100644 index 0000000000000..a61bc748bea2d --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied + --> $DIR/candidate-from-env-universe-err-2.rs:14:5 + | +LL | impl_hr::(); + | ^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T` + | +note: required by a bound in `impl_hr` + --> $DIR/candidate-from-env-universe-err-2.rs:11:19 + | +LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {} + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impl_hr` +help: consider further restricting this bound + | +LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static> + for<'a> Trait<'a, '_>>() { + | +++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr new file mode 100644 index 0000000000000..29a72b1c1b641 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.old.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/candidate-from-env-universe-err-2.rs:14:5 + | +LL | fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() { + | -- lifetime `'a` defined here +LL | impl_hr::(); + | ^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/candidate-from-env-universe-err-2.rs:11:19 + | +LL | fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/candidate-from-env-universe-err-2.rs:14:5 + | +LL | impl_hr::(); + | ^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Trait<'a, '_>` + found trait `for<'b> Trait<'_, 'b>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs new file mode 100644 index 0000000000000..56fa70469ccf8 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.rs @@ -0,0 +1,20 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +// cc #119820 + +trait Trait<'a, 'b> {} + +trait OtherTrait<'b> {} +impl<'a, 'b, T: OtherTrait<'b>> Trait<'a, 'b> for T {} + +fn impl_hr<'b, T: for<'a> Trait<'a, 'b>>() {} + +fn not_hr<'a, T: for<'b> Trait<'a, 'b> + OtherTrait<'static>>() { + impl_hr::(); + //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied + //[current]~^^ERROR lifetime may not live long enough + //[current]~| ERROR implementation of `Trait` is not general enough +} + +fn main() {} diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr new file mode 100644 index 0000000000000..bb0b2de788e83 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr @@ -0,0 +1,54 @@ +error: implementation of `Trait` is not general enough + --> $DIR/candidate-from-env-universe-err-project.rs:28:5 + | +LL | trait_bound::(); + | ^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `T` must implement `Trait<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Trait<'static>` + +error: implementation of `Trait` is not general enough + --> $DIR/candidate-from-env-universe-err-project.rs:39:5 + | +LL | projection_bound::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `T` must implement `Trait<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Trait<'static>` + +error[E0308]: mismatched types + --> $DIR/candidate-from-env-universe-err-project.rs:39:5 + | +LL | projection_bound::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected associated type `>::Assoc` + found associated type `>::Assoc` +note: the lifetime requirement is introduced here + --> $DIR/candidate-from-env-universe-err-project.rs:18:42 + | +LL | fn projection_bound Trait<'a, Assoc = usize>>() {} + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/candidate-from-env-universe-err-project.rs:55:30 + | +LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected associated type `>::Assoc` + found associated type `>::Assoc` + +error[E0308]: mismatched types + --> $DIR/candidate-from-env-universe-err-project.rs:55:30 + | +LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected associated type `>::Assoc` + found associated type `>::Assoc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr new file mode 100644 index 0000000000000..2804d5bbe9408 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr @@ -0,0 +1,67 @@ +error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied + --> $DIR/candidate-from-env-universe-err-project.rs:28:19 + | +LL | trait_bound::(); + | ^ the trait `for<'a> Trait<'a>` is not implemented for `T` + | +note: required by a bound in `trait_bound` + --> $DIR/candidate-from-env-universe-err-project.rs:17:19 + | +LL | fn trait_bound Trait<'a>>() {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `trait_bound` +help: consider further restricting this bound + | +LL | fn function1 + for<'a> Trait<'a>>() { + | +++++++++++++++++++ + +error[E0277]: the trait bound `for<'a> T: Trait<'a>` is not satisfied + --> $DIR/candidate-from-env-universe-err-project.rs:39:24 + | +LL | projection_bound::(); + | ^ the trait `for<'a> Trait<'a>` is not implemented for `T` + | +note: required by a bound in `projection_bound` + --> $DIR/candidate-from-env-universe-err-project.rs:18:24 + | +LL | fn projection_bound Trait<'a, Assoc = usize>>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `projection_bound` +help: consider further restricting this bound + | +LL | fn function2 + for<'a> Trait<'a>>() { + | +++++++++++++++++++ + +error[E0271]: type mismatch resolving `>::Assoc == usize` + --> $DIR/candidate-from-env-universe-err-project.rs:39:24 + | +LL | projection_bound::(); + | ^ type mismatch resolving `>::Assoc == usize` + | +note: types differ + --> $DIR/candidate-from-env-universe-err-project.rs:14:18 + | +LL | type Assoc = usize; + | ^^^^^ +note: required by a bound in `projection_bound` + --> $DIR/candidate-from-env-universe-err-project.rs:18:42 + | +LL | fn projection_bound Trait<'a, Assoc = usize>>() {} + | ^^^^^^^^^^^^^ required by this bound in `projection_bound` + +error: higher-ranked subtype error + --> $DIR/candidate-from-env-universe-err-project.rs:55:30 + | +LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/candidate-from-env-universe-err-project.rs:55:30 + | +LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs new file mode 100644 index 0000000000000..2f53bd019b78c --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs @@ -0,0 +1,62 @@ +//@ revisions: next current +//@[next] compile-flags: -Znext-solver + +// cc #119820 the previous behavior here was inconsistent as we discarded +// the where-bound candidate for trait goals due to the leak check, but did +// not do so for projection candidates and during normalization. +// +// This results in an inconsistency between `Trait` and `Projection` goals as +// normalizing always constraints the normalized-to term. +trait Trait<'a> { + type Assoc; +} +impl<'a, T> Trait<'a> for T { + type Assoc = usize; +} + +fn trait_bound Trait<'a>>() {} +fn projection_bound Trait<'a, Assoc = usize>>() {} + +// We use a function with a trivial where-bound which is more +// restrictive than the impl. +fn function1>() { + // err + // + // Proving `for<'a> T: Trait<'a>` using the where-bound does not + // result in a leak check failure even though it does not apply. + // We prefer env candidates over impl candidatescausing this to succeed. + trait_bound::(); + //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied + //[current]~^^ ERROR implementation of `Trait` is not general enough +} + +fn function2>() { + // err + // + // Proving the `Projection` goal `for<'a> T: Trait<'a, Assoc = usize>` + // does not use the leak check when trying the where-bound, causing us + // to prefer it over the impl, resulting in a placeholder error. + projection_bound::(); + //[next]~^ ERROR type mismatch resolving `>::Assoc == usize` + //[next]~| ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied + //[current]~^^^ ERROR implementation of `Trait` is not general enough + //[current]~| ERROR mismatched types +} + +fn function3>() { + // err + // + // Trying to normalize the type `for<'a> fn(>::Assoc)` + // only gets to `>::Assoc` once `'a` has been already + // instantiated, causing us to prefer the where-bound over the impl + // resulting in a placeholder error. Even if were were to also use the + // leak check during candidate selection for normalization, this + // case would still not compile. + let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); + //[next]~^ ERROR higher-ranked subtype error + //[next]~| ERROR higher-ranked subtype error + //[current]~^^^ ERROR mismatched types + //[current]~| ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/higher-ranked/leak-check-in-selection.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs similarity index 100% rename from tests/ui/higher-ranked/leak-check-in-selection.rs rename to tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr new file mode 100644 index 0000000000000..a840304e49c1f --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.next.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-2.rs:16:5 + | +LL | impls_trait::<(), _>(); + | ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` + | +note: multiple `impl`s satisfying `for<'a> (): Trait<&'a str, _>` found + --> $DIR/leak-check-in-selection-2.rs:9:1 + | +LL | impl<'a> Trait<&'a str, &'a str> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | impl<'a> Trait<&'a str, String> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_trait` + --> $DIR/leak-check-in-selection-2.rs:13:19 + | +LL | fn impls_trait Trait<&'a str, U>, U>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.old.stderr new file mode 100644 index 0000000000000..a840304e49c1f --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.old.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-2.rs:16:5 + | +LL | impls_trait::<(), _>(); + | ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `impls_trait` + | +note: multiple `impl`s satisfying `for<'a> (): Trait<&'a str, _>` found + --> $DIR/leak-check-in-selection-2.rs:9:1 + | +LL | impl<'a> Trait<&'a str, &'a str> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | impl<'a> Trait<&'a str, String> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_trait` + --> $DIR/leak-check-in-selection-2.rs:13:19 + | +LL | fn impls_trait Trait<&'a str, U>, U>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs new file mode 100644 index 0000000000000..48dd569f201b9 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-2.rs @@ -0,0 +1,18 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +// cc #119820 + +trait Trait {} + +// using this impl results in a higher-ranked region error. +impl<'a> Trait<&'a str, &'a str> for () {} + +impl<'a> Trait<&'a str, String> for () {} + +fn impls_trait Trait<&'a str, U>, U>() {} + +fn main() { + impls_trait::<(), _>(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr new file mode 100644 index 0000000000000..8a8118dea859b --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr @@ -0,0 +1,35 @@ +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-3.rs:18:5 + | +LL | impls_leak::>(); + | ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_leak` + | +note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found + --> $DIR/leak-check-in-selection-3.rs:9:1 + | +LL | impl Leak<'_> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Leak<'static> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_leak` + --> $DIR/leak-check-in-selection-3.rs:12:18 + | +LL | fn impls_leak Leak<'a>>() {} + | ^^^^^^^^^^^^^^^^ required by this bound in `impls_leak` + +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-3.rs:35:5 + | +LL | impls_indirect_leak::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` + | + = note: cannot satisfy `for<'a> Box<_>: IndirectLeak<'a>` +note: required by a bound in `impls_indirect_leak` + --> $DIR/leak-check-in-selection-3.rs:25:27 + | +LL | fn impls_indirect_leak IndirectLeak<'a>>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_indirect_leak` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr new file mode 100644 index 0000000000000..662a06537401a --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.old.stderr @@ -0,0 +1,48 @@ +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-3.rs:18:5 + | +LL | impls_leak::>(); + | ^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_leak` + | +note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found + --> $DIR/leak-check-in-selection-3.rs:9:1 + | +LL | impl Leak<'_> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Leak<'static> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `impls_leak` + --> $DIR/leak-check-in-selection-3.rs:12:18 + | +LL | fn impls_leak Leak<'a>>() {} + | ^^^^^^^^^^^^^^^^ required by this bound in `impls_leak` + +error[E0283]: type annotations needed + --> $DIR/leak-check-in-selection-3.rs:35:5 + | +LL | impls_indirect_leak::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` + | +note: multiple `impl`s satisfying `Box<_>: Leak<'_>` found + --> $DIR/leak-check-in-selection-3.rs:9:1 + | +LL | impl Leak<'_> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Leak<'static> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required for `Box<_>` to implement `for<'a> IndirectLeak<'a>` + --> $DIR/leak-check-in-selection-3.rs:23:23 + | +LL | impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {} + | -------- ^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `impls_indirect_leak` + --> $DIR/leak-check-in-selection-3.rs:25:27 + | +LL | fn impls_indirect_leak IndirectLeak<'a>>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `impls_indirect_leak` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs new file mode 100644 index 0000000000000..9e99b6c527d9d --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.rs @@ -0,0 +1,39 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +// cc #119820, the previous behavior here was inconsistent, +// using the leak check to guide inference for `for<'a> Box<_>: Leak<'a>` +// but not for `for<'a> Box<_>: IndirectLeak<'a>` + +trait Leak<'a> {} +impl Leak<'_> for Box {} +impl Leak<'static> for Box {} + +fn impls_leak Leak<'a>>() {} +fn direct() { + // ok + // + // The `Box` impls fails the leak check, + // meaning that we apply the `Box` impl. + impls_leak::>(); + //~^ ERROR type annotations needed +} + +trait IndirectLeak<'a> {} +impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {} + +fn impls_indirect_leak IndirectLeak<'a>>() {} +fn indirect() { + // error: type annotations needed + // + // While the `Box` impl would fail the leak check + // we have already instantiated the binder while applying + // the generic `IndirectLeak` impl, so during candidate + // selection of `Leak` we do not detect the placeholder error. + // Evaluation of `Box<_>: Leak<'!a>` is therefore ambiguous, + // resulting in `for<'a> Box<_>: Leak<'a>` also being ambiguous. + impls_indirect_leak::>(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs new file mode 100644 index 0000000000000..8d87bdd064a06 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs @@ -0,0 +1,29 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// cc #119820. While the leak check does not consider the binder +// of the current goal, leaks from higher-ranked nested goals are +// considered. +// +// We enter and exit the binder of the nested goal while evaluating +// the candidate. + +trait LeakCheckFailure<'a> {} +impl LeakCheckFailure<'static> for () {} + +trait Trait {} +impl Trait for () where for<'a> (): LeakCheckFailure<'a> {} +impl Trait for () {} +fn impls_trait, U>() {} +fn main() { + // ok + // + // It does not matter whether candidate assembly + // considers the placeholders from higher-ranked goal. + // + // Either `for<'a> (): LeakCheckFailure<'a>` has no applicable + // candidate or it has a single applicable candidate which then later + // results in an error. This allows us to infer `U` to `u16`. + impls_trait::<(), _>() +} diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs similarity index 86% rename from tests/ui/higher-ranked/trait-bounds/issue-30786.rs rename to tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs index ffb2b306ae76a..799df8cae9fd7 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.rs @@ -1,6 +1,6 @@ //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" -// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream &'b mut A: Stream` // should act as assertion that item does not borrow from its stream; // but an earlier buggy rustc allowed `.map(|x: &_| x)` which does // have such an item. @@ -97,10 +97,6 @@ where impl StreamExt for T where for<'a> &'a mut T: Stream {} -fn identity(x: &T) -> &T { - x -} - fn variant1() { let source = Repeat(10); @@ -118,19 +114,7 @@ fn variant1() { // guess. let map = source.mapx(|x: &_| x); let filter = map.filterx(|x: &_| true); - //~^ ERROR the method -} - -fn variant2() { - let source = Repeat(10); - - // Here, we use a function, which is not subject to the vagaries - // of closure signature inference. In this case, we get the error - // on `countx` as, I think, the test originally expected. - let map = source.mapx(identity); - let filter = map.filterx(|x: &_| true); - let count = filter.countx(); - //~^ ERROR the method + //~^ ERROR the method `filterx` exists for struct } fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr new file mode 100644 index 0000000000000..ae364de8cc061 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-1.stderr @@ -0,0 +1,27 @@ +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied + --> $DIR/hrtb-doesnt-borrow-self-1.rs:116:22 + | +LL | pub struct Map { + | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt` +... +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method cannot be called due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&'a mut &Map: Stream` + `&'a mut &mut Map: Stream` + `&'a mut Map: Stream` + --> $DIR/hrtb-doesnt-borrow-self-1.rs:98:50 + | +LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} + | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `filterx`, perhaps you need to implement it + --> $DIR/hrtb-doesnt-borrow-self-1.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs new file mode 100644 index 0000000000000..92e2e7f796eaa --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs @@ -0,0 +1,116 @@ +//@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream Option; +} + +// Example stream +pub struct Repeat(u64); + +impl<'a> Stream for &'a mut Repeat { + type Item = &'a u64; + fn next(self) -> Option { + Some(&self.0) + } +} + +pub struct Map { + stream: S, + func: F, +} + +impl<'a, A, F, T> Stream for &'a mut Map +where + &'a mut A: Stream, + F: FnMut(<&'a mut A as Stream>::Item) -> T, +{ + type Item = T; + fn next(self) -> Option { + match self.stream.next() { + Some(item) => Some((self.func)(item)), + None => None, + } + } +} + +pub struct Filter { + stream: S, + func: F, +} + +impl<'a, A, F, T> Stream for &'a mut Filter +where + for<'b> &'b mut A: Stream, // <---- BAD + F: FnMut(&T) -> bool, +{ + type Item = <&'a mut A as Stream>::Item; + fn next(self) -> Option { + while let Some(item) = self.stream.next() { + if (self.func)(&item) { + return Some(item); + } + } + None + } +} + +pub trait StreamExt +where + for<'b> &'b mut Self: Stream, +{ + fn mapx(self, func: F) -> Map + where + Self: Sized, + for<'a> &'a mut Map: Stream, + { + Map { func: func, stream: self } + } + + fn filterx(self, func: F) -> Filter + where + Self: Sized, + for<'a> &'a mut Filter: Stream, + { + Filter { func: func, stream: self } + } + + fn countx(mut self) -> usize + where + Self: Sized, + { + let mut count = 0; + while let Some(_) = self.next() { + count += 1; + } + count + } +} + +impl StreamExt for T where for<'a> &'a mut T: Stream {} + +fn identity(x: &T) -> &T { + x +} + +fn variant2() { + let source = Repeat(10); + + // Here, we use a function, which is not subject to the vagaries + // of closure signature inference. In this case, we get the error + // on `countx` as, I think, the test originally expected. + let map = source.mapx(identity); + let filter = map.filterx(|x: &_| true); + let count = filter.countx(); + //~^ ERROR the method +} + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr new file mode 100644 index 0000000000000..eeb4e12fa8b31 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr @@ -0,0 +1,27 @@ +error[E0599]: the method `countx` exists for struct `Filter &u64 {identity::}>, {closure@hrtb-doesnt-borrow-self-2.rs:111:30}>`, but its trait bounds were not satisfied + --> $DIR/hrtb-doesnt-borrow-self-2.rs:112:24 + | +LL | pub struct Filter { + | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method cannot be called due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream` + `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream` + `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream` + --> $DIR/hrtb-doesnt-borrow-self-2.rs:98:50 + | +LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} + | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `countx`, perhaps you need to implement it + --> $DIR/hrtb-doesnt-borrow-self-2.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr index e10da26665ebb..be19bf85bd2f3 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,23 +1,11 @@ -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26 +error: implementation of `Bar` is not general enough + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | LL | want_bar_for_any_ccx(b); - | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | -note: required by a bound in `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15 - | -LL | fn want_bar_for_any_ccx(b: &B) - | -------------------- required by a bound in this function -LL | where B : for<'ccx> Bar<'ccx> - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` -help: consider further restricting this bound - | -LL | where B : Qux + for<'ccx> Bar<'ccx> - | +++++++++++++++++++++ + = note: `B` must implement `Bar<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Bar<'static>` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs index 33e0ec4635b66..70ce580258d43 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs @@ -1,43 +1,37 @@ // Test a trait (`Bar`) with a higher-ranked supertrait. +#![allow(unconditional_recursion)] -trait Foo<'tcx> -{ +trait Foo<'tcx> { fn foo(&'tcx self) -> &'tcx isize; } -trait Bar<'ccx> - : for<'tcx> Foo<'tcx> -{ +trait Bar<'ccx>: for<'tcx> Foo<'tcx> { fn bar(&'ccx self) -> &'ccx isize; } -fn want_foo_for_some_tcx<'x,F>(f: &'x F) - where F : Foo<'x> -{ +fn want_foo_for_some_tcx<'x, F: Foo<'x>>(f: &'x F) { want_foo_for_some_tcx(f); - want_foo_for_any_tcx(f); //~ ERROR not satisfied + want_foo_for_any_tcx(f); + //~^ ERROR lifetime may not live long enough + //~| ERROR implementation of `Foo` is not general enough } -fn want_foo_for_any_tcx(f: &F) //~ WARN cannot return without recursing - where F : for<'tcx> Foo<'tcx> -{ +fn want_foo_for_any_tcx Foo<'tcx>>(f: &F) { want_foo_for_some_tcx(f); want_foo_for_any_tcx(f); } -fn want_bar_for_some_ccx<'x,B>(b: &B) - where B : Bar<'x> -{ +fn want_bar_for_some_ccx<'x, B: Bar<'x>>(b: &B) { want_foo_for_some_tcx(b); want_foo_for_any_tcx(b); want_bar_for_some_ccx(b); - want_bar_for_any_ccx(b); //~ ERROR not satisfied + want_bar_for_any_ccx(b); + //~^ ERROR lifetime may not live long enough + //~| ERROR implementation of `Bar` is not general enough } -fn want_bar_for_any_ccx(b: &B) //~ WARN cannot return without recursing - where B : for<'ccx> Bar<'ccx> -{ +fn want_bar_for_any_ccx Bar<'ccx>>(b: &B) { want_foo_for_some_tcx(b); want_foo_for_any_tcx(b); diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr index f220ba6f33893..dd760926ea117 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -1,68 +1,50 @@ -error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26 +error: lifetime may not live long enough + --> $DIR/hrtb-higher-ranker-supertraits.rs:14:5 | +LL | fn want_foo_for_some_tcx<'x, F: Foo<'x>>(f: &'x F) { + | -- lifetime `'x` defined here +LL | want_foo_for_some_tcx(f); LL | want_foo_for_any_tcx(f); - | -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static` | -note: required by a bound in `want_foo_for_any_tcx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15 +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-higher-ranker-supertraits.rs:19:28 | -LL | fn want_foo_for_any_tcx(f: &F) - | -------------------- required by a bound in this function -LL | where F : for<'tcx> Foo<'tcx> - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo_for_any_tcx` -help: consider further restricting this bound - | -LL | where F : Foo<'x> + for<'tcx> Foo<'tcx> - | +++++++++++++++++++++ +LL | fn want_foo_for_any_tcx Foo<'tcx>>(f: &F) { + | ^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied - --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 - | -LL | want_bar_for_any_ccx(b); - | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | | - | required by a bound introduced by this call +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-higher-ranker-supertraits.rs:14:5 | -note: required by a bound in `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15 - | -LL | fn want_bar_for_any_ccx(b: &B) - | -------------------- required by a bound in this function -LL | where B : for<'ccx> Bar<'ccx> - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` -help: consider further restricting this bound +LL | want_foo_for_any_tcx(f); + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | -LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> - | +++++++++++++++++++++ + = note: `F` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` -warning: function cannot return without recursing - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 +error: lifetime may not live long enough + --> $DIR/hrtb-higher-ranker-supertraits.rs:29:5 | -LL | / fn want_foo_for_any_tcx(f: &F) -LL | | where F : for<'tcx> Foo<'tcx> - | |_________________________________^ cannot return without recursing +LL | fn want_bar_for_some_ccx<'x, B: Bar<'x>>(b: &B) { + | -- lifetime `'x` defined here ... -LL | want_foo_for_any_tcx(f); - | ----------------------- recursive call site +LL | want_bar_for_any_ccx(b); + | ^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-higher-ranker-supertraits.rs:34:28 | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default +LL | fn want_bar_for_any_ccx Bar<'ccx>>(b: &B) { + | ^^^^^^^^^^^^^^^^^^^ -warning: function cannot return without recursing - --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 +error: implementation of `Bar` is not general enough + --> $DIR/hrtb-higher-ranker-supertraits.rs:29:5 | -LL | / fn want_bar_for_any_ccx(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> - | |_________________________________^ cannot return without recursing -... -LL | want_bar_for_any_ccx(b); - | ----------------------- recursive call site +LL | want_bar_for_any_ccx(b); + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | - = help: a `loop` may express intention better if this is on purpose + = note: `B` must implement `Bar<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Bar<'1>`, for some specific lifetime `'1` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr deleted file mode 100644 index 699a4ecc42bb9..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ /dev/null @@ -1,51 +0,0 @@ -error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied - --> $DIR/issue-30786.rs:120:22 - | -LL | pub struct Map { - | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt` -... -LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds - | -note: the following trait bounds were not satisfied: - `&'a mut &Map: Stream` - `&'a mut &mut Map: Stream` - `&'a mut Map: Stream` - --> $DIR/issue-30786.rs:98:50 - | -LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | --------- - ^^^^^^ unsatisfied trait bound introduced here - = help: items from traits can only be used if the trait is implemented and in scope -note: `StreamExt` defines an item `filterx`, perhaps you need to implement it - --> $DIR/issue-30786.rs:66:1 - | -LL | pub trait StreamExt - | ^^^^^^^^^^^^^^^^^^^ - -error[E0599]: the method `countx` exists for struct `Filter &u64 {identity::}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied - --> $DIR/issue-30786.rs:132:24 - | -LL | pub struct Filter { - | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt` -... -LL | let count = filter.countx(); - | ^^^^^^ method cannot be called due to unsatisfied trait bounds - | -note: the following trait bounds were not satisfied: - `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream` - `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream` - `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, {closure@$DIR/issue-30786.rs:131:30: 131:37}>: Stream` - --> $DIR/issue-30786.rs:98:50 - | -LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | --------- - ^^^^^^ unsatisfied trait bound introduced here - = help: items from traits can only be used if the trait is implemented and in scope -note: `StreamExt` defines an item `countx`, perhaps you need to implement it - --> $DIR/issue-30786.rs:66:1 - | -LL | pub trait StreamExt - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/implied-bounds/issue-100690.rs b/tests/ui/implied-bounds/issue-100690.rs index ea33c9f423b77..041c687ec9430 100644 --- a/tests/ui/implied-bounds/issue-100690.rs +++ b/tests/ui/implied-bounds/issue-100690.rs @@ -4,11 +4,8 @@ use std::io; fn real_dispatch(f: F) -> Result<(), io::Error> -//~^ NOTE required by a bound in this where F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, - //~^ NOTE required by this bound in `real_dispatch` - //~| NOTE required by a bound in `real_dispatch` { todo!() } @@ -35,10 +32,10 @@ impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandl F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static, { real_dispatch(f) - //~^ ERROR expected a `FnOnce(&mut UIView<'_, T>)` closure, found `F` - //~| NOTE expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F` - //~| NOTE expected a closure with arguments - //~| NOTE required by a bound introduced by this call + //~^ ERROR lifetime may not live long enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR mismatched types + // } } diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index df069d875cebc..2cfd028f2559b 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -1,22 +1,41 @@ -error[E0277]: expected a `FnOnce(&mut UIView<'_, T>)` closure, found `F` - --> $DIR/issue-100690.rs:37:23 +error: lifetime may not live long enough + --> $DIR/issue-100690.rs:34:9 | +LL | impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle { + | -- lifetime `'a` defined here +... LL | real_dispatch(f) - | ------------- ^ expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F` - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` | - = note: expected a closure with arguments `(&mut UIView<'a, _>,)` - found a closure with arguments `(&mut UIView<'_, _>,)` -note: required by a bound in `real_dispatch` - --> $DIR/issue-100690.rs:9:8 +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/issue-100690.rs:8:8 + | +LL | F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-100690.rs:34:9 + | +LL | real_dispatch(f) + | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `F` must implement `FnOnce<(&mut UIView<'0, T>,)>`, for any lifetime `'0`... + = note: ...but it actually implements `FnOnce<(&mut UIView<'1, T>,)>`, for some specific lifetime `'1` + +error[E0308]: mismatched types + --> $DIR/issue-100690.rs:34:9 + | +LL | real_dispatch(f) + | ^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected associated type `,)>>::Output` + found associated type `,)>>::Output` +note: the lifetime requirement is introduced here + --> $DIR/issue-100690.rs:8:34 | -LL | fn real_dispatch(f: F) -> Result<(), io::Error> - | ------------- required by a bound in this function -... LL | F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch` + | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`.