From 57b8688c27d39291e2a47089102f7f0f6ce33224 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Mar 2024 16:57:18 +0000 Subject: [PATCH 01/10] Consolidate WF for aliases --- .../rustc_trait_selection/src/traits/wf.rs | 28 ++++++------------- .../in-trait/return-dont-satisfy-bounds.rs | 1 + .../return-dont-satisfy-bounds.stderr | 18 +++++++++++- .../ui/lifetimes/issue-76168-hr-outlives-3.rs | 1 + .../issue-76168-hr-outlives-3.stderr | 23 ++++++++++++--- .../type-match-with-late-bound.stderr | 23 ++++++++++++++- 6 files changed, 68 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f89daf033f6cd..64f02bfd32116 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -164,7 +164,7 @@ pub fn clause_obligations<'tcx>( wf.compute(ty.into()); } ty::ClauseKind::Projection(t) => { - wf.compute_projection(t.projection_ty); + wf.compute_alias(t.projection_ty); wf.compute(match t.term.unpack() { ty::TermKind::Ty(ty) => ty.into(), ty::TermKind::Const(c) => c.into(), @@ -436,9 +436,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } - /// Pushes the obligations required for `trait_ref::Item` to be WF + /// Pushes the obligations required for an alias (except inherent) to be WF /// into `self.out`. - fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) { + fn compute_alias(&mut self, data: ty::AliasTy<'tcx>) { // A projection is well-formed if // // (a) its predicates hold (*) @@ -466,6 +466,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.compute_projection_args(data.args); } + /// Pushes the obligations required for an inherent alias to be WF + /// into `self.out`. + // FIXME(inherent_associated_types): Merge this function with `fn compute_alias`. fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) { // An inherent projection is well-formed if // @@ -688,8 +691,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // Simple cases that are WF if their type args are WF. } - ty::Alias(ty::Projection, data) => { - self.compute_projection(data); + ty::Alias(ty::Projection | ty::Opaque | ty::Weak, data) => { + self.compute_alias(data); return; // Subtree handled by compute_projection. } ty::Alias(ty::Inherent, data) => { @@ -791,21 +794,6 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // types appearing in the fn signature. } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - // All of the requirements on type parameters - // have already been checked for `impl Trait` in - // return position. We do need to check type-alias-impl-trait though. - if self.tcx().is_type_alias_impl_trait(def_id) { - let obligations = self.nominal_obligations(def_id, args); - self.out.extend(obligations); - } - } - - ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => { - let obligations = self.nominal_obligations(def_id, args); - self.out.extend(obligations); - } - ty::Dynamic(data, r, _) => { // WfObject // diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index ff265e576b90f..84bc39d926307 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -9,6 +9,7 @@ impl Foo for Bar { //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] //~| ERROR: the trait bound `Bar: Foo` is not satisfied [E0277] //~| ERROR: impl has stricter requirements than trait + //~| ERROR: the trait bound `F2: Foo` is not satisfied self } } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index 12725c3456fd5..fbf82a24b5015 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -11,6 +11,22 @@ note: required by a bound in `Foo::{synthetic#0}` LL | fn foo(self) -> impl Foo; | ^^^^^^ required by this bound in `Foo::{synthetic#0}` +error[E0277]: the trait bound `F2: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:8:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `F2` + | +note: required by a bound in `>::foo` + --> $DIR/return-dont-satisfy-bounds.rs:8:16 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^ required by this bound in `>::foo` +help: consider further restricting this bound + | +LL | fn foo + Foo>(self) -> impl Foo { + | +++++++++ + error[E0276]: impl has stricter requirements than trait --> $DIR/return-dont-satisfy-bounds.rs:8:16 | @@ -32,7 +48,7 @@ LL | self = help: the trait `Foo` is implemented for `Bar` = help: for that trait implementation, expected `char`, found `u8` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs index 85eeb5d4c901e..eab436fa3419d 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs @@ -7,6 +7,7 @@ async fn wrapper(f: F) //~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` //~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` //~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` +//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` where F:, for<'a> >::Output: Future + 'a, diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index 578ba149baf3f..e9f97d1d93bde 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -5,7 +5,7 @@ LL | / async fn wrapper(f: F) LL | | LL | | LL | | -LL | | where +... | LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` @@ -27,7 +27,7 @@ LL | / async fn wrapper(f: F) LL | | LL | | LL | | -LL | | where +... | LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` @@ -35,7 +35,22 @@ LL | | for<'a> >::Output: Future + 'a = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` - --> $DIR/issue-76168-hr-outlives-3.rs:13:1 + --> $DIR/issue-76168-hr-outlives-3.rs:6:1 + | +LL | / async fn wrapper(f: F) +LL | | +LL | | +LL | | +... | +LL | | F:, +LL | | for<'a> >::Output: Future + 'a, + | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` + | + = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` + --> $DIR/issue-76168-hr-outlives-3.rs:14:1 | LL | / { LL | | @@ -46,6 +61,6 @@ LL | | } | = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr index 6c259621466d3..40e16dde6e4a4 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr @@ -7,6 +7,27 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default +error[E0309]: the placeholder type `!1_"F"` may not live long enough + --> $DIR/type-match-with-late-bound.rs:8:1 + | +LL | async fn walk2<'a, T: 'a>(_: T) + | ^ -- the placeholder type `!1_"F"` must be valid for the lifetime `'a` as defined here... + | _| + | | +LL | | where +LL | | for F: 'a, + | |_________________^ ...so that the type `F` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/type-match-with-late-bound.rs:10:15 + | +LL | for F: 'a, + | ^^ +help: consider adding an explicit lifetime bound + | +LL | for F: 'a, !1_"F": 'a + | ~~~~~~~~~~~~ + error[E0309]: the placeholder type `!1_"F"` may not live long enough --> $DIR/type-match-with-late-bound.rs:11:1 | @@ -35,6 +56,6 @@ help: consider adding an explicit lifetime bound LL | for F: 'a, !2_"F": 'a | ~~~~~~~~~~~~ -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0309`. From a440b1602be78d5987e2e4373c1f3a9cbb7bf97e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 14 Mar 2024 12:44:27 -0400 Subject: [PATCH 02/10] Recurse into args in WF even if they have escaping bound vars --- .../rustc_trait_selection/src/traits/wf.rs | 73 ++++------------- .../ui/implied-bounds/from-trait-impl.stderr | 10 +-- .../ui/inference/issue-80409.no-compat.stderr | 14 ---- tests/ui/inference/issue-80409.rs | 17 +--- tests/ui/trait-bounds/unsized-bound.stderr | 80 +++++++++---------- .../traits/copy-impl-cannot-normalize.stderr | 14 ++-- .../normalize/normalize-param-env-2.stderr | 8 +- .../normalize-param-env-4.next.stderr | 8 +- 8 files changed, 69 insertions(+), 155 deletions(-) delete mode 100644 tests/ui/inference/issue-80409.no-compat.stderr diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 64f02bfd32116..58ed5688b5479 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -396,36 +396,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.out.extend(obligations); } - self.out.extend( - trait_ref - .args - .iter() - .enumerate() - .filter(|(_, arg)| { - matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) - }) - .filter(|(_, arg)| !arg.has_escaping_bound_vars()) - .map(|(i, arg)| { - let mut cause = traits::ObligationCause::misc(self.span, self.body_id); - // The first arg is the self ty - use the correct span for it. - if i == 0 { - if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) = - item.map(|i| &i.kind) - { - cause.span = self_ty.span; - } - } - traits::Obligation::with_depth( - tcx, - cause, - depth, - param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - arg, - ))), - ) - }), - ); + if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) = item.map(|i| &i.kind) { + // FIXME: Could generalize this hack. + let span = std::mem::replace(&mut self.span, self_ty.span); + // make sure that the trait ref is WF. + trait_ref.args[0].visit_with(self); + self.span = span; + (&trait_ref.args[1..]).visit_with(self); + } else { + // make sure that the trait ref is WF. + trait_ref.visit_with(self); + } } // Compute the obligations that are required for `trait_ref` to be WF, @@ -463,7 +444,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let obligations = self.nominal_obligations(data.def_id, data.args); self.out.extend(obligations); - self.compute_projection_args(data.args); + // Make sure that projection args are WF. + data.visit_with(self); } /// Pushes the obligations required for an inherent alias to be WF @@ -493,33 +475,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.out.extend(obligations); } - self.compute_projection_args(data.args); - } - - fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) { - let tcx = self.tcx(); - let cause = self.cause(traits::WellFormed(None)); - let param_env = self.param_env; - let depth = self.recursion_depth; - - self.out.extend( - args.iter() - .filter(|arg| { - matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) - }) - .filter(|arg| !arg.has_escaping_bound_vars()) - .map(|arg| { - traits::Obligation::with_depth( - tcx, - cause.clone(), - depth, - param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - arg, - ))), - ) - }), - ); + // Make sure that projection args are WF. + data.visit_with(self); } fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { diff --git a/tests/ui/implied-bounds/from-trait-impl.stderr b/tests/ui/implied-bounds/from-trait-impl.stderr index 4151d206ae25f..a456c5a230761 100644 --- a/tests/ui/implied-bounds/from-trait-impl.stderr +++ b/tests/ui/implied-bounds/from-trait-impl.stderr @@ -7,13 +7,13 @@ LL | fn func1(foo: Foo<(&str,)>) { = note: type must satisfy the static lifetime error[E0310]: the parameter type `X` may not live long enough - --> $DIR/from-trait-impl.rs:20:23 + --> $DIR/from-trait-impl.rs:20:9 | LL | impl TestTrait for [Foo<(X,)>; 1] {} - | ^^^^^^^^^^^^^^ - | | - | the parameter type `X` must be valid for the static lifetime... - | ...so that the type `X` will meet its required lifetime bounds + | ^^^^^^^^^ + | | + | the parameter type `X` must be valid for the static lifetime... + | ...so that the type `X` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr deleted file mode 100644 index 523ca229b06f4..0000000000000 --- a/tests/ui/inference/issue-80409.no-compat.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } } - --> $DIR/issue-80409.rs:49:30 - | -LL | builder.state().on_entry(|_| {}); - | ^^^ - | -note: - --> $DIR/issue-80409.rs:49:30 - | -LL | builder.state().on_entry(|_| {}); - | ^^^ - -query stack during panic: -end of query stack diff --git a/tests/ui/inference/issue-80409.rs b/tests/ui/inference/issue-80409.rs index dfb84563e6d80..0979c21e3ee14 100644 --- a/tests/ui/inference/issue-80409.rs +++ b/tests/ui/inference/issue-80409.rs @@ -1,19 +1,3 @@ -// This should not pass, because `usize: Fsm` does not hold. However, it currently ICEs. - -// ignore-tidy-linelength - -//@ revisions: compat no-compat -//@[compat] check-pass -//@[no-compat] compile-flags: -Zno-implied-bounds-compat -//@[no-compat] check-fail -//@[no-compat] known-bug: #80409 -//@[no-compat] failure-status: 101 -//@[no-compat] normalize-stderr-test "delayed at.*" -> "" -//@[no-compat] normalize-stderr-test "note: .*\n\n" -> "" -//@[no-compat] normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" -//@[no-compat] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@[no-compat] rustc-env:RUST_BACKTRACE=0 - #![allow(unreachable_code, unused)] use std::marker::PhantomData; @@ -34,6 +18,7 @@ struct FsmStateBuilder { impl FsmStateBuilder { fn on_entry)>(&self, _action: TAction) {} + //~^ ERROR the trait bound `TFsm: Fsm` is not satisfied } trait Fsm { diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr index c8049ebee1173..ed7299b933102 100644 --- a/tests/ui/trait-bounds/unsized-bound.stderr +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -1,3 +1,18 @@ +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:2:30 + | +LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} +LL + impl Trait<(A, B)> for (A, B) where B: ?Sized, {} + | + error[E0277]: the size for values of type `B` cannot be known at compilation time --> $DIR/unsized-bound.rs:2:30 | @@ -23,18 +38,29 @@ LL | trait Trait {} | ++++++++ error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/unsized-bound.rs:2:30 + --> $DIR/unsized-bound.rs:5:52 | -LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} - | - ^^^^^^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `Sized` +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - this type parameter needs to be `Sized` ^^^^^^^^^ doesn't have a size known at compile-time | = note: only the last element of a tuple may have a dynamically sized type help: consider removing the `?Sized` bound to make the type parameter `Sized` | -LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} -LL + impl Trait<(A, B)> for (A, B) where B: ?Sized, {} +LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +LL + impl Trait<(A, B, C)> for (A, B, C) {} + | + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:52 + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - this type parameter needs to be `Sized` ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +LL + impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} | error[E0277]: the size for values of type `C` cannot be known at compilation time @@ -62,29 +88,18 @@ LL | trait Trait {} | ++++++++ error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/unsized-bound.rs:5:52 - | -LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} - | - this type parameter needs to be `Sized` ^^^^^^^^^ doesn't have a size known at compile-time - | - = note: only the last element of a tuple may have a dynamically sized type -help: consider removing the `?Sized` bound to make the type parameter `Sized` - | -LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} -LL + impl Trait<(A, B, C)> for (A, B, C) {} - | - -error[E0277]: the size for values of type `B` cannot be known at compilation time - --> $DIR/unsized-bound.rs:5:52 + --> $DIR/unsized-bound.rs:10:47 | -LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} - | - this type parameter needs to be `Sized` ^^^^^^^^^ doesn't have a size known at compile-time +LL | impl Trait2<(A, B)> for (A, B) {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` | = note: only the last element of a tuple may have a dynamically sized type help: consider removing the `?Sized` bound to make the type parameter `Sized` | -LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} -LL + impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +LL - impl Trait2<(A, B)> for (A, B) {} +LL + impl Trait2<(A, B)> for (A, B) {} | error[E0277]: the size for values of type `B` cannot be known at compilation time @@ -111,21 +126,6 @@ help: consider relaxing the implicit `Sized` restriction LL | trait Trait2 {} | ++++++++ -error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/unsized-bound.rs:10:47 - | -LL | impl Trait2<(A, B)> for (A, B) {} - | - ^^^^^^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `Sized` - | - = note: only the last element of a tuple may have a dynamically sized type -help: consider removing the `?Sized` bound to make the type parameter `Sized` - | -LL - impl Trait2<(A, B)> for (A, B) {} -LL + impl Trait2<(A, B)> for (A, B) {} - | - error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/unsized-bound.rs:14:23 | diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr index a98bb47f54fc1..a1b13d126c69f 100644 --- a/tests/ui/traits/copy-impl-cannot-normalize.stderr +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -2,18 +2,16 @@ error[E0277]: the trait bound `T: TraitFoo` is not satisfied --> $DIR/copy-impl-cannot-normalize.rs:22:18 | LL | impl Copy for Foo {} - | ^^^^^^ the trait `TraitFoo` is not implemented for `T`, which is required by `Foo: Clone` + | ^^^^^^ the trait `TraitFoo` is not implemented for `T` | -note: required for `Foo` to implement `Clone` - --> $DIR/copy-impl-cannot-normalize.rs:12:9 +note: required by a bound in `Foo` + --> $DIR/copy-impl-cannot-normalize.rs:7:8 | -LL | impl Clone for Foo - | ^^^^^ ^^^^^^ +LL | struct Foo + | --- required by a bound in this struct LL | where LL | T: TraitFoo, - | -------- unsatisfied trait bound introduced here -note: required by a bound in `Copy` - --> $SRC_DIR/core/src/marker.rs:LL:COL + | ^^^^^^^^ required by this bound in `Foo` help: consider restricting type parameter `T` | LL | impl Copy for Foo {} diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index 74a0a90885da5..a14c11f426c82 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -19,12 +19,6 @@ error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` LL | Self::Assoc: A, | ^^^^ -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc well-formed` - --> $DIR/normalize-param-env-2.rs:24:22 - | -LL | Self::Assoc: A, - | ^^^^ - error[E0275]: overflow evaluating the requirement `(): A` --> $DIR/normalize-param-env-2.rs:27:10 | @@ -46,6 +40,6 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index e91a48f62aec3..2f41330d99121 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,12 +4,6 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error[E0275]: overflow evaluating the requirement `::Assoc well-formed` - --> $DIR/normalize-param-env-4.rs:19:26 - | -LL | ::Assoc: Trait, - | ^^^^^ - error[E0275]: overflow evaluating the requirement `T: Trait` --> $DIR/normalize-param-env-4.rs:32:19 | @@ -22,6 +16,6 @@ note: required by a bound in `impls_trait` LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. From a6185d67ebad68bd15456d48e9cf6ac0ad95caa6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Mar 2024 10:21:27 +0000 Subject: [PATCH 03/10] Pass list of defineable opaque types into canonical queries --- .../src/region_infer/opaque_types.rs | 11 +++++++++ .../src/infer/canonical/canonicalizer.rs | 9 +++++++- compiler/rustc_infer/src/infer/mod.rs | 16 ++++++------- .../rustc_infer/src/infer/opaque_types/mod.rs | 2 -- compiler/rustc_middle/src/infer/canonical.rs | 11 ++++----- compiler/rustc_middle/src/query/plumbing.rs | 8 +++---- compiler/rustc_middle/src/traits/mod.rs | 15 ++++++------ compiler/rustc_middle/src/traits/solve.rs | 3 +-- compiler/rustc_middle/src/ty/context.rs | 1 + .../src/canonicalizer.rs | 3 ++- compiler/rustc_trait_selection/src/infer.rs | 7 +++--- .../src/solve/eval_ctxt/canonical.rs | 1 - .../src/solve/eval_ctxt/mod.rs | 1 - .../rustc_trait_selection/src/solve/mod.rs | 1 + compiler/rustc_type_ir/src/canonical.rs | 10 ++++---- compiler/rustc_type_ir/src/debug.rs | 4 ++++ compiler/rustc_type_ir/src/infcx.rs | 2 ++ compiler/rustc_type_ir/src/interner.rs | 1 + .../equality-in-canonical-query.clone.stderr | 23 ------------------- .../impl-trait/equality-in-canonical-query.rs | 11 +-------- .../issue-53398-cyclic-types.rs | 3 +-- .../issue-53398-cyclic-types.stderr | 9 ++++++++ ...equality_in_canonical_query.current.stderr | 23 ------------------- .../rpit_tait_equality_in_canonical_query.rs | 12 +--------- .../type-alias-impl-trait-with-cycle-error.rs | 6 ++--- ...e-alias-impl-trait-with-cycle-error.stderr | 11 ++++----- ...type-alias-impl-trait-with-cycle-error2.rs | 2 +- ...-alias-impl-trait-with-cycle-error2.stderr | 11 ++++----- 28 files changed, 88 insertions(+), 129 deletions(-) delete mode 100644 tests/ui/impl-trait/equality-in-canonical-query.clone.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr delete mode 100644 tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 8a17223303718..2be455f35695d 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -146,6 +146,17 @@ impl<'tcx> RegionInferenceContext<'tcx> { opaque_type_key, universal_concrete_type, ); + + // Sometimes, when the hidden type is an inference variable, it can happen that + // the hidden type becomes the opaque type itself. In this case, this was an opaque + // usage of the opaque type and we can ignore it. This check is mirrored in typeck's + // writeback. + if let ty::Alias(ty::Opaque, alias_ty) = universal_concrete_type.ty.kind() + && alias_ty.def_id == opaque_type_key.def_id.to_def_id() + && alias_ty.args == opaque_type_key.args + { + continue; + } // Sometimes two opaque types are the same only after we remap the generic parameters // back to the opaque type definition. E.g. we may have `OpaqueType` mapped to `(X, Y)` // and `OpaqueType` mapped to `(Y, X)`, and those are the same, but we only know that diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 9f70fee993dfe..370028db88b6b 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -45,6 +45,7 @@ impl<'tcx> InferCtxt<'tcx> { let param_env = self.tcx.canonical_param_env_cache.get_or_insert( self.tcx, param_env, + self.defining_use_anchor, query_state, |tcx, param_env, query_state| { // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the @@ -540,6 +541,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: (), + defining_anchor: infcx.map(|i| i.defining_use_anchor).unwrap_or_default(), }; Canonicalizer::canonicalize_with_base( base, @@ -609,7 +611,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { .max() .unwrap_or(ty::UniverseIndex::ROOT); - Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) } + Canonical { + max_universe, + variables: canonical_variables, + value: (base.value, out_value), + defining_anchor: base.defining_anchor, + } } /// Creates a canonical variable replacing `kind` from the input, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 89e4e88b3df24..0201f7df26a35 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -234,13 +234,7 @@ impl<'tcx> InferCtxtInner<'tcx> { pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, - /// The `DefId` of the item in whose context we are performing inference or typeck. - /// It is used to check whether an opaque type use is a defining use. - /// - /// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up - /// the obligation. This frequently happens for - /// short lived InferCtxt within queries. The opaque type obligations are forwarded - /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. + /// The `DefIds` of the opaque types that may have their hidden types constrained. /// /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined. /// This way it is easier to catch errors that @@ -392,6 +386,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { fn probe_ct_var(&self, vid: ConstVid) -> Option> { self.probe_const_var(vid).ok() } + + fn defining_anchor(&self) -> DefiningAnchor<'tcx> { + self.defining_use_anchor + } } /// See the `error_reporting` module for more details. @@ -670,14 +668,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// the bound values in `C` to their instantiated values in `V` /// (in other words, `S(C) = V`). pub fn build_with_canonical( - &mut self, + self, span: Span, canonical: &Canonical<'tcx, T>, ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>) where T: TypeFoldable>, { - let infcx = self.build(); + let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build(); let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); (infcx, value, args) } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index a6f8115c27e2d..13ec261969309 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -149,7 +149,6 @@ impl<'tcx> InferCtxt<'tcx> { return None; } } - DefiningAnchor::Bubble => {} } if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't @@ -376,7 +375,6 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { let defined_opaque_types = match self.defining_use_anchor { - DefiningAnchor::Bubble => return None, DefiningAnchor::Bind(bind) => bind, }; diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 7b65c11bc3c82..333da403ab42a 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -33,6 +33,7 @@ use std::ops::Index; use crate::infer::MemberConstraint; use crate::mir::ConstraintCategory; +use crate::traits::DefiningAnchor; use crate::ty::GenericArg; use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; @@ -153,11 +154,6 @@ pub struct QueryResponse<'tcx, R> { pub var_values: CanonicalVarValues<'tcx>, pub region_constraints: QueryRegionConstraints<'tcx>, pub certainty: Certainty, - /// List of opaque types which we tried to compare to another type. - /// Inside the query we don't know yet whether the opaque type actually - /// should get its hidden type inferred. So we bubble the opaque type - /// and the type it was compared against upwards and let the query caller - /// handle it. pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, pub value: R, } @@ -316,6 +312,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: ty::ParamEnv<'tcx>, + defining_anchor: DefiningAnchor<'tcx>, state: &mut OriginalQueryValues<'tcx>, canonicalize_op: fn( TyCtxt<'tcx>, @@ -330,6 +327,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: key, + defining_anchor, }; } @@ -344,7 +342,8 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { *canonical } Entry::Vacant(e) => { - let canonical = canonicalize_op(tcx, key, state); + let mut canonical = canonicalize_op(tcx, key, state); + canonical.defining_anchor = defining_anchor; let OriginalQueryValues { var_values, universe_map } = state; assert_eq!(universe_map.len(), 1); e.insert((canonical, tcx.arena.alloc_slice(var_values))); diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 8d88488e1675d..3c79bbe93a272 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -340,10 +340,10 @@ macro_rules! define_callbacks { <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>> >::Cache; - // Ensure that keys grow no larger than 64 bytes + // Ensure that keys grow no larger than 72 bytes #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 64 { + if mem::size_of::>() > 72 { panic!("{}", concat!( "the query `", stringify!($name), @@ -354,10 +354,10 @@ macro_rules! define_callbacks { } }; - // Ensure that values grow no larger than 64 bytes + // Ensure that values grow no larger than 72 bytes #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 64 { + if mem::size_of::>() > 72 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index aea5865335124..becbf868d9257 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -1001,6 +1001,7 @@ pub enum CodegenObligationError { /// opaques are replaced with inference vars eagerly in the old solver (e.g. /// in projection, and in the signature during function type-checking). #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable)] pub enum DefiningAnchor<'tcx> { /// Define opaques which are in-scope of the current item being analyzed. /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`. @@ -1009,14 +1010,12 @@ pub enum DefiningAnchor<'tcx> { /// errors when handling opaque types, and also should be used when we would /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). Bind(&'tcx ty::List), - /// In contexts where we don't currently know what opaques are allowed to be - /// defined, such as (old solver) canonical queries, we will simply allow - /// opaques to be defined, but "bubble" them up in the canonical response or - /// otherwise treat them to be handled later. - /// - /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`, - /// which may affect what predicates pass and fail in the old trait solver. - Bubble, +} + +impl Default for DefiningAnchor<'_> { + fn default() -> Self { + Self::Bind(ty::List::empty()) + } } impl<'tcx> DefiningAnchor<'tcx> { diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index dc4cd2034156e..0e4412c9ba527 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -4,7 +4,7 @@ use rustc_span::def_id::DefId; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; -use crate::traits::{Canonical, DefiningAnchor}; +use crate::traits::Canonical; use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, @@ -114,7 +114,6 @@ impl MaybeCause { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct QueryInput<'tcx, T> { pub goal: Goal<'tcx, T>, - pub anchor: DefiningAnchor<'tcx>, pub predefined_opaques_in_body: PredefinedOpaques<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5362b6d8b24ca..a340e396bd144 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -81,6 +81,7 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; + type DefiningAnchor = traits::DefiningAnchor<'tcx>; type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; type GenericArg = ty::GenericArg<'tcx>; diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 95b3006666202..6875993617b3a 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -69,7 +69,8 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc let (max_universe, variables) = canonicalizer.finalize(); - Canonical { max_universe, variables, value } + let defining_anchor = infcx.defining_anchor(); + Canonical { defining_anchor, max_universe, variables, value } } fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index f694dd0070363..e5ff8c899a13e 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,5 +1,5 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, DefiningAnchor, ObligationCtxt, SelectionContext}; +use crate::traits::{self, ObligationCtxt, SelectionContext}; use crate::traits::TraitEngineExt as _; use rustc_hir::def_id::DefId; @@ -133,9 +133,8 @@ impl<'tcx> InferCtxtBuilder<'tcx> { R: Debug + TypeFoldable>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, { - let (infcx, key, canonical_inference_vars) = self - .with_opaque_type_inference(DefiningAnchor::Bubble) - .build_with_canonical(DUMMY_SP, canonical_key); + let (infcx, key, canonical_inference_vars) = + self.build_with_canonical(DUMMY_SP, canonical_key); let ocx = ObligationCtxt::new(&infcx); let value = operation(&ocx, key)?; ocx.make_canonicalized_query_response(canonical_inference_vars, value) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 251b0a193f1bb..b6c1a24a9b135 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -65,7 +65,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut orig_values, QueryInput { goal, - anchor: self.infcx.defining_use_anchor, predefined_opaques_in_body: self .tcx() .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }), diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 3b858cb449fa1..5111bb6e416f4 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -226,7 +226,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { .infer_ctxt() .intercrate(intercrate) .with_next_trait_solver(true) - .with_opaque_type_inference(canonical_input.value.anchor) .build_with_canonical(DUMMY_SP, &canonical_input); let mut ecx = EvalCtxt { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 0bf28f520a4d2..ddb9b9979113e 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -320,5 +320,6 @@ fn response_no_constraints_raw<'tcx>( external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()), certainty, }, + defining_anchor: Default::default(), } } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index ad18ef249842f..85b32be80606f 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -16,6 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex}; pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, + pub defining_anchor: I::DefiningAnchor, pub variables: I::CanonicalVars, } @@ -44,8 +45,8 @@ impl Canonical { /// let b: Canonical)> = a.unchecked_map(|v| (v, ty)); /// ``` pub fn unchecked_map(self, map_op: impl FnOnce(V) -> W) -> Canonical { - let Canonical { max_universe, variables, value } = self; - Canonical { max_universe, variables, value: map_op(value) } + let Canonical { defining_anchor, max_universe, variables, value } = self; + Canonical { defining_anchor, max_universe, variables, value: map_op(value) } } /// Allows you to map the `value` of a canonical while keeping the same set of @@ -54,8 +55,8 @@ impl Canonical { /// **WARNING:** This function is very easy to mis-use, hence the name! See /// the comment of [Canonical::unchecked_map] for more details. pub fn unchecked_rebind(self, value: W) -> Canonical { - let Canonical { max_universe, variables, value: _ } = self; - Canonical { max_universe, variables, value } + let Canonical { defining_anchor, max_universe, variables, value: _ } = self; + Canonical { defining_anchor, max_universe, variables, value } } } @@ -100,6 +101,7 @@ where value: self.value.try_fold_with(folder)?, max_universe: self.max_universe.try_fold_with(folder)?, variables: self.variables.try_fold_with(folder)?, + defining_anchor: self.defining_anchor, }) } } diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 9c8e45b4338c6..aced3b53fde29 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -43,6 +43,10 @@ impl InferCtxtLike for NoInfcx { fn probe_ct_var(&self, _vid: ConstVid) -> Option { None } + + fn defining_anchor(&self) -> ::DefiningAnchor { + Default::default() + } } pub trait DebugWithInfcx: fmt::Debug { diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index 28b71f0ea13f8..bdfa010c00035 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -37,4 +37,6 @@ pub trait InferCtxtLike { /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type. fn probe_ct_var(&self, vid: ConstVid) -> Option<::Const>; + + fn defining_anchor(&self) -> ::DefiningAnchor; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 373540de05e0e..e57204777843c 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -10,6 +10,7 @@ use crate::{ pub trait Interner: Sized { type DefId: Copy + Debug + Hash + Ord; + type DefiningAnchor: Copy + Debug + Hash + Default; type AdtDef: Copy + Debug + Hash + Ord; type GenericArgs: Copy diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr deleted file mode 100644 index e4c8aec397365..0000000000000 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ /dev/null @@ -1,23 +0,0 @@ -note: no errors encountered even though delayed bugs were created - -note: those delayed bugs will now be shown as internal compiler errors - -error: internal compiler error: {OpaqueTypeKey { def_id: DefId(rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }) } }} - | - = - - -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(foo::{opaque#0}) }))), bound_vars: [] } } } - --> $DIR/equality-in-canonical-query.rs:21:5 - | -LL | same_output(foo, rpit); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - - --> $DIR/equality-in-canonical-query.rs:21:5 - | -LL | same_output(foo, rpit); - | ^^^^^^^^^^^^^^^^^^^^^^ - -query stack during panic: -end of query stack diff --git a/tests/ui/impl-trait/equality-in-canonical-query.rs b/tests/ui/impl-trait/equality-in-canonical-query.rs index 6a32f4bec76d4..2b8f6ce1b0753 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.rs +++ b/tests/ui/impl-trait/equality-in-canonical-query.rs @@ -1,15 +1,6 @@ // issue: #116877 //@ revisions: sized clone -//@[sized] check-pass -//@[clone] known-bug: #108498 -//@[clone] failure-status: 101 -//@[clone] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//@[clone] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> "" -//@[clone] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> "" -//@[clone] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> "" -//@[clone] normalize-stderr-test: "(?m)note: delayed at.*$" -> "" -//@[clone] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" -//@[clone] normalize-stderr-test: "(?m)^ *at .*\n" -> "" +//@ check-pass #[cfg(sized)] fn rpit() -> impl Sized {} #[cfg(clone)] fn rpit() -> impl Clone {} diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs index ae463b6ef5b8e..9cc8546afbce7 100644 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -1,10 +1,9 @@ #![feature(type_alias_impl_trait)] -//@ check-pass - type Foo = impl Fn() -> Foo; fn foo() -> Foo { + //~^ ERROR: overflow foo } diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr new file mode 100644 index 0000000000000..1358c3e2a98b8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == Foo` + --> $DIR/issue-53398-cyclic-types.rs:5:13 + | +LL | fn foo() -> Foo { + | ^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr deleted file mode 100644 index 1c36fda4ae14b..0000000000000 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ /dev/null @@ -1,23 +0,0 @@ -note: no errors encountered even though delayed bugs were created - -note: those delayed bugs will now be shown as internal compiler errors - -error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque#0}), args: [] }: OpaqueTypeDecl { hidden_type: OpaqueHiddenType { span: no-location (#0), ty: Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }) } }} - | - = - - -error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } - --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - | - - --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5 - | -LL | query(get_rpit); - | ^^^^^^^^^^^^^^^ - -query stack during panic: -end of query stack diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs index 7524cebf9e638..6f50703aca24d 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs @@ -8,17 +8,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass - -//@[current] known-bug: #108498 -//@[current] failure-status: 101 -//@[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" -//@[current] normalize-stderr-test: "(?m)note: we would appreciate a bug report.*\n\n" -> "" -//@[current] normalize-stderr-test: "(?m)note: rustc.*running on.*\n\n" -> "" -//@[current] normalize-stderr-test: "(?m)note: compiler flags.*\n\n" -> "" -//@[current] normalize-stderr-test: "(?m)note: delayed at.*$" -> "" -//@[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" -//@[current] normalize-stderr-test: "(?m)^ *at .*\n" -> "" +//@ check-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs index e5e7fb677ede9..80ab53881a328 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs @@ -1,12 +1,10 @@ #![feature(type_alias_impl_trait)] type Foo = impl Fn() -> Foo; -//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { + //~^ ERROR: overflow x } -fn main() { - -} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr index 3d43fbe0dbccb..21779c7d1284a 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12 +error[E0275]: overflow evaluating the requirement `>::Output == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error.rs:5:21 | -LL | type Foo = impl Fn() -> Foo; - | ^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs index 7c7a1b405bcdc..87b2d6765f4e2 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs @@ -5,9 +5,9 @@ pub trait Bar { } type Foo = impl Bar; -//~^ ERROR: unconstrained opaque type fn crash(x: Foo) -> Foo { + //~^ ERROR: overflow x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr index e2dc887989b29..d1c620968ba90 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12 +error[E0275]: overflow evaluating the requirement `>::Item == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:9:21 | -LL | type Foo = impl Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. From 4dcc78db59ae9dc107ee4d62209e89ff5dbc509f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 10:29:11 +0000 Subject: [PATCH 04/10] Eliminate `DefiningAnchor` now that is just a single-variant enum --- compiler/rustc_borrowck/src/consumers.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 3 +- .../src/region_infer/opaque_types.rs | 7 +- .../rustc_hir_analysis/src/check/check.rs | 9 +- compiler/rustc_hir_typeck/src/inherited.rs | 7 +- compiler/rustc_infer/src/infer/at.rs | 2 +- .../src/infer/canonical/canonicalizer.rs | 6 +- compiler/rustc_infer/src/infer/mod.rs | 34 ++++---- .../rustc_infer/src/infer/opaque_types/mod.rs | 85 +++++++++---------- compiler/rustc_middle/src/infer/canonical.rs | 8 +- compiler/rustc_middle/src/traits/mod.rs | 31 +------ compiler/rustc_middle/src/ty/codec.rs | 6 ++ compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/list.rs | 6 ++ .../src/canonicalizer.rs | 4 +- .../rustc_trait_selection/src/solve/mod.rs | 2 +- compiler/rustc_type_ir/src/canonical.rs | 12 +-- compiler/rustc_type_ir/src/debug.rs | 2 +- compiler/rustc_type_ir/src/infcx.rs | 2 +- compiler/rustc_type_ir/src/interner.rs | 2 +- 20 files changed, 101 insertions(+), 132 deletions(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 31307ef14102e..64726eacca74a 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -4,7 +4,6 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::{Body, Promoted}; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::TyCtxt; use std::rc::Rc; @@ -106,7 +105,7 @@ pub fn get_body_with_borrowck_facts( options: ConsumerOptions, ) -> BodyWithBorrowckFacts<'_> { let (input_body, promoted) = tcx.mir_promoted(def); - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap() diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 415ba095a1b24..78e092d3c2308 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -32,7 +32,6 @@ use rustc_infer::infer::{ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; @@ -126,7 +125,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(def).build(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 2be455f35695d..33082b9bb8048 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -7,7 +7,6 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_macros::extension; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{GenericArgKind, GenericArgs}; @@ -322,13 +321,13 @@ fn check_opaque_type_well_formed<'tcx>( parent_def_id = tcx.local_parent(parent_def_id); } - // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])` + // FIXME(-Znext-solver): We probably should use `&[]` instead of // and prepopulate this `InferCtxt` with known opaque values, rather than - // using the `Bind` anchor here. For now it's fine. + // allowing opaque types to be defined and checking them after the fact. let infcx = tcx .infer_ctxt() .with_next_trait_solver(next_trait_solver) - .with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id)) + .with_opaque_type_inference(parent_def_id) .build(); let ocx = ObligationCtxt::new(&infcx); let identity_args = GenericArgs::identity_for_item(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d1fed13ee9feb..9066d6c1e4c9a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -13,7 +13,7 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode}; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; @@ -345,10 +345,7 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - let infcx = tcx - .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor)) - .build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build(); let ocx = ObligationCtxt::new(&infcx); let args = match *origin { @@ -1564,7 +1561,7 @@ pub(super) fn check_coroutine_obligations( .ignoring_regions() // Bind opaque types to type checking root, as they should have been checked by borrowck, // but may show up in some cases, like when (root) obligations are stalled in the new solver. - .with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id)) + .with_opaque_type_inference(typeck.hir_owner.def_id) .build(); let mut fulfillment_cx = >::new(&infcx); diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index b0950ed280084..e22e14a0a9e57 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -5,7 +5,6 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; -use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefIdMap; @@ -76,11 +75,7 @@ impl<'tcx> Inherited<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; - let infcx = tcx - .infer_ctxt() - .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id)) - .build(); + let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); Inherited { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 94088216c029a..f2222eec76af2 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -75,7 +75,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn fork_with_intercrate(&self, intercrate: bool) -> Self { Self { tcx: self.tcx, - defining_use_anchor: self.defining_use_anchor, + defining_opaque_types: self.defining_opaque_types, considering_regions: self.considering_regions, skip_leak_check: self.skip_leak_check, inner: self.inner.clone(), diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 370028db88b6b..9986fdfd15d1c 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -45,7 +45,7 @@ impl<'tcx> InferCtxt<'tcx> { let param_env = self.tcx.canonical_param_env_cache.get_or_insert( self.tcx, param_env, - self.defining_use_anchor, + self.defining_opaque_types, query_state, |tcx, param_env, query_state| { // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the @@ -541,7 +541,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: (), - defining_anchor: infcx.map(|i| i.defining_use_anchor).unwrap_or_default(), + defining_opaque_types: infcx.map(|i| i.defining_opaque_types).unwrap_or_default(), }; Canonicalizer::canonicalize_with_base( base, @@ -615,7 +615,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { max_universe, variables: canonical_variables, value: (base.value, out_value), - defining_anchor: base.defining_anchor, + defining_opaque_types: base.defining_opaque_types, } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0201f7df26a35..403d2eb299a18 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -34,7 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::traits::{select, DefiningAnchor}; +use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -235,11 +235,7 @@ pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, /// The `DefIds` of the opaque types that may have their hidden types constrained. - /// - /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined. - /// This way it is easier to catch errors that - /// might come up during inference or typeck. - pub defining_use_anchor: DefiningAnchor<'tcx>, + pub defining_opaque_types: &'tcx ty::List, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -387,8 +383,8 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { self.probe_const_var(vid).ok() } - fn defining_anchor(&self) -> DefiningAnchor<'tcx> { - self.defining_use_anchor + fn defining_opaque_types(&self) -> &'tcx ty::List { + self.defining_opaque_types } } @@ -604,7 +600,7 @@ impl fmt::Display for FixupError { /// Used to configure inference contexts before their creation. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, - defining_use_anchor: DefiningAnchor<'tcx>, + defining_opaque_types: &'tcx ty::List, considering_regions: bool, skip_leak_check: bool, /// Whether we are in coherence mode. @@ -619,7 +615,7 @@ impl<'tcx> TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, - defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()), + defining_opaque_types: ty::List::empty(), considering_regions: true, skip_leak_check: false, intercrate: false, @@ -635,8 +631,16 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// It is only meant to be called in two places, for typeck /// (via `Inherited::build`) and for the inference context used /// in mir borrowck. - pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self { - self.defining_use_anchor = defining_use_anchor; + pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self { + self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor); + self + } + + pub fn with_defining_opaque_types( + mut self, + defining_opaque_types: &'tcx ty::List, + ) -> Self { + self.defining_opaque_types = defining_opaque_types; self } @@ -675,7 +679,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { where T: TypeFoldable>, { - let infcx = self.with_opaque_type_inference(canonical.defining_anchor).build(); + let infcx = self.with_defining_opaque_types(canonical.defining_opaque_types).build(); let (value, args) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); (infcx, value, args) } @@ -683,7 +687,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { pub fn build(&mut self) -> InferCtxt<'tcx> { let InferCtxtBuilder { tcx, - defining_use_anchor, + defining_opaque_types, considering_regions, skip_leak_check, intercrate, @@ -691,7 +695,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } = *self; InferCtxt { tcx, - defining_use_anchor, + defining_opaque_types, considering_regions, skip_leak_check, inner: RefCell::new(InferCtxtInner::new()), diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 13ec261969309..d95a34d17e00a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -8,7 +8,7 @@ use hir::OpaqueTyOrigin; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_middle::traits::{DefiningAnchor, ObligationCause}; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::GenericArgKind; @@ -109,47 +109,44 @@ impl<'tcx> InferCtxt<'tcx> { b, )); } - match self.defining_use_anchor { - DefiningAnchor::Bind(_) => { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - if self.opaque_type_origin(def_id).is_none() { - return None; - } - } + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + if self.opaque_type_origin(def_id).is_none() { + return None; } + if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't // want to make a decision on it right now. Likely this case is so super rare anyway, that @@ -374,13 +371,9 @@ impl<'tcx> InferCtxt<'tcx> { /// in its defining scope. #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - let defined_opaque_types = match self.defining_use_anchor { - DefiningAnchor::Bind(bind) => bind, - }; - let origin = self.tcx.opaque_type_origin(def_id); - defined_opaque_types.contains(&def_id).then_some(origin) + self.defining_opaque_types.contains(&def_id).then_some(origin) } } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 333da403ab42a..aec26ec651d79 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -23,6 +23,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; +use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; use rustc_type_ir::Canonical as IrCanonical; use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo; @@ -33,7 +34,6 @@ use std::ops::Index; use crate::infer::MemberConstraint; use crate::mir::ConstraintCategory; -use crate::traits::DefiningAnchor; use crate::ty::GenericArg; use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; @@ -312,7 +312,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: ty::ParamEnv<'tcx>, - defining_anchor: DefiningAnchor<'tcx>, + defining_opaque_types: &'tcx ty::List, state: &mut OriginalQueryValues<'tcx>, canonicalize_op: fn( TyCtxt<'tcx>, @@ -327,7 +327,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { max_universe: ty::UniverseIndex::ROOT, variables: List::empty(), value: key, - defining_anchor, + defining_opaque_types, }; } @@ -343,7 +343,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> { } Entry::Vacant(e) => { let mut canonical = canonicalize_op(tcx, key, state); - canonical.defining_anchor = defining_anchor; + canonical.defining_opaque_types = defining_opaque_types; let OriginalQueryValues { var_values, universe_map } = state; assert_eq!(universe_map.len(), 1); e.insert((canonical, tcx.arena.alloc_slice(var_values))); diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index becbf868d9257..d21ee8ca62816 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -12,8 +12,8 @@ pub mod util; use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; +use crate::ty::GenericArgsRef; use crate::ty::{self, AdtKind, Ty}; -use crate::ty::{GenericArgsRef, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diag, EmissionGuarantee}; @@ -994,32 +994,3 @@ pub enum CodegenObligationError { Unimplemented, FulfillmentError, } - -/// Defines the treatment of opaque types in a given inference context. -/// -/// This affects both what opaques are allowed to be defined, but also whether -/// opaques are replaced with inference vars eagerly in the old solver (e.g. -/// in projection, and in the signature during function type-checking). -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -#[derive(TyEncodable, TyDecodable)] -pub enum DefiningAnchor<'tcx> { - /// Define opaques which are in-scope of the current item being analyzed. - /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`. - /// - /// If the list is empty, do not allow any opaques to be defined. This is used to catch type mismatch - /// errors when handling opaque types, and also should be used when we would - /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). - Bind(&'tcx ty::List), -} - -impl Default for DefiningAnchor<'_> { - fn default() -> Self { - Self::Bind(ty::List::empty()) - } -} - -impl<'tcx> DefiningAnchor<'tcx> { - pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { - Self::Bind(tcx.opaque_types_defined_by(item)) - } -} diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index ddbc0bffaedde..eff9cc2f8fb1b 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -441,6 +441,12 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List>> Decodable for &'tcx ty::List { + fn decode(d: &mut D) -> Self { + RefDecodable::decode(d) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List<(VariantIdx, FieldIdx)> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a340e396bd144..dcef2f1488cde 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -81,7 +81,7 @@ use std::ops::{Bound, Deref}; #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Interner for TyCtxt<'tcx> { type DefId = DefId; - type DefiningAnchor = traits::DefiningAnchor<'tcx>; + type DefiningOpaqueTypes = &'tcx ty::List; type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; type GenericArg = ty::GenericArg<'tcx>; diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 336c2dce1141c..615f34bc6207e 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -39,6 +39,12 @@ pub struct List { opaque: OpaqueListContents, } +impl Default for &List { + fn default() -> Self { + List::empty() + } +} + extern "C" { /// A dummy type used to force `List` to be unsized while not requiring /// references to it be wide pointers. diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 6875993617b3a..0269801869098 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -69,8 +69,8 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc let (max_universe, variables) = canonicalizer.finalize(); - let defining_anchor = infcx.defining_anchor(); - Canonical { defining_anchor, max_universe, variables, value } + let defining_opaque_types = infcx.defining_opaque_types(); + Canonical { defining_opaque_types, max_universe, variables, value } } fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index ddb9b9979113e..ffe109720dddd 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -320,6 +320,6 @@ fn response_no_constraints_raw<'tcx>( external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()), certainty, }, - defining_anchor: Default::default(), + defining_opaque_types: Default::default(), } } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 85b32be80606f..b2701ae744e09 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -16,7 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex}; pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, - pub defining_anchor: I::DefiningAnchor, + pub defining_opaque_types: I::DefiningOpaqueTypes, pub variables: I::CanonicalVars, } @@ -45,8 +45,8 @@ impl Canonical { /// let b: Canonical)> = a.unchecked_map(|v| (v, ty)); /// ``` pub fn unchecked_map(self, map_op: impl FnOnce(V) -> W) -> Canonical { - let Canonical { defining_anchor, max_universe, variables, value } = self; - Canonical { defining_anchor, max_universe, variables, value: map_op(value) } + let Canonical { defining_opaque_types, max_universe, variables, value } = self; + Canonical { defining_opaque_types, max_universe, variables, value: map_op(value) } } /// Allows you to map the `value` of a canonical while keeping the same set of @@ -55,8 +55,8 @@ impl Canonical { /// **WARNING:** This function is very easy to mis-use, hence the name! See /// the comment of [Canonical::unchecked_map] for more details. pub fn unchecked_rebind(self, value: W) -> Canonical { - let Canonical { defining_anchor, max_universe, variables, value: _ } = self; - Canonical { defining_anchor, max_universe, variables, value } + let Canonical { defining_opaque_types, max_universe, variables, value: _ } = self; + Canonical { defining_opaque_types, max_universe, variables, value } } } @@ -101,7 +101,7 @@ where value: self.value.try_fold_with(folder)?, max_universe: self.max_universe.try_fold_with(folder)?, variables: self.variables.try_fold_with(folder)?, - defining_anchor: self.defining_anchor, + defining_opaque_types: self.defining_opaque_types, }) } } diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index aced3b53fde29..9298360f749ac 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -44,7 +44,7 @@ impl InferCtxtLike for NoInfcx { None } - fn defining_anchor(&self) -> ::DefiningAnchor { + fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes { Default::default() } } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index bdfa010c00035..a53287c19878b 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -38,5 +38,5 @@ pub trait InferCtxtLike { /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type. fn probe_ct_var(&self, vid: ConstVid) -> Option<::Const>; - fn defining_anchor(&self) -> ::DefiningAnchor; + fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index e57204777843c..9d01c9243c02a 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -10,7 +10,7 @@ use crate::{ pub trait Interner: Sized { type DefId: Copy + Debug + Hash + Ord; - type DefiningAnchor: Copy + Debug + Hash + Default; + type DefiningOpaqueTypes: Copy + Debug + Hash + Default; type AdtDef: Copy + Debug + Hash + Ord; type GenericArgs: Copy From 1b499c8e035371268d9fd46f467e2bf4a6e07354 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 Mar 2024 12:27:58 +0000 Subject: [PATCH 05/10] Shrink the size of ClosureTypeInfo to fit into 64 bytes again --- compiler/rustc_middle/src/query/plumbing.rs | 8 +++++--- compiler/rustc_middle/src/ty/closure.rs | 12 ++++++------ compiler/rustc_middle/src/ty/context.rs | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 3c79bbe93a272..bdd399578dcdb 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -340,7 +340,8 @@ macro_rules! define_callbacks { <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>> >::Cache; - // Ensure that keys grow no larger than 72 bytes + // Ensure that keys grow no larger than 72 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] const _: () = { if mem::size_of::>() > 72 { @@ -354,10 +355,11 @@ macro_rules! define_callbacks { } }; - // Ensure that values grow no larger than 72 bytes + // Ensure that values grow no larger than 64 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] const _: () = { - if mem::size_of::>() > 72 { + if mem::size_of::>() > 64 { panic!("{}", concat!( "the query `", stringify!($name), diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 7db64504f85ea..95d1e08b58b51 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -45,7 +45,7 @@ impl UpvarId { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub enum UpvarCapture { /// Upvar is captured by value. This is always true when the @@ -73,7 +73,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap = Vec>; /// A composite describing a `Place` that is captured by a closure. -#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(Eq, PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub struct CapturedPlace<'tcx> { /// Name and span where the binding happens. @@ -192,7 +192,7 @@ impl<'tcx> CapturedPlace<'tcx> { #[derive(Copy, Clone, Debug, HashStable)] pub struct ClosureTypeInfo<'tcx> { user_provided_sig: ty::CanonicalPolyFnSig<'tcx>, - captures: &'tcx [&'tcx ty::CapturedPlace<'tcx>], + captures: &'tcx ty::List<&'tcx ty::CapturedPlace<'tcx>>, kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>, } @@ -201,7 +201,7 @@ fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo let typeck_results = tcx.typeck(def); let user_provided_sig = typeck_results.user_provided_sigs[&def]; let captures = typeck_results.closure_min_captures_flattened(def); - let captures = tcx.arena.alloc_from_iter(captures); + let captures = tcx.mk_captures_from_iter(captures); let hir_id = tcx.local_def_id_to_hir_id(def); let kind_origin = typeck_results.closure_kind_origins().get(hir_id); ClosureTypeInfo { user_provided_sig, captures, kind_origin } @@ -253,7 +253,7 @@ pub fn is_ancestor_or_same_capture( /// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move) /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. -#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] +#[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub struct CaptureInfo { /// Expr Id pointing to use that resulted in selecting the current capture kind @@ -332,7 +332,7 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc curr_string } -#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] +#[derive(Eq, Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index dcef2f1488cde..4aabefc88e4fd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -162,6 +162,7 @@ pub struct CtxtInterners<'tcx> { predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>, fields: InternedSet<'tcx, List>, local_def_ids: InternedSet<'tcx, List>, + captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>, offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>, } @@ -189,6 +190,7 @@ impl<'tcx> CtxtInterners<'tcx> { predefined_opaques_in_body: Default::default(), fields: Default::default(), local_def_ids: Default::default(), + captures: Default::default(), offset_of: Default::default(), } } @@ -1778,6 +1780,7 @@ slice_interners!( bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), fields: pub mk_fields(FieldIdx), local_def_ids: intern_local_def_ids(LocalDefId), + captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>), offset_of: pub mk_offset_of((VariantIdx, FieldIdx)), ); @@ -2028,6 +2031,17 @@ impl<'tcx> TyCtxt<'tcx> { T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs)) } + pub fn mk_captures_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: CollectAndApply< + &'tcx ty::CapturedPlace<'tcx>, + &'tcx List<&'tcx ty::CapturedPlace<'tcx>>, + >, + { + T::collect_and_apply(iter, |xs| self.intern_captures(xs)) + } + pub fn mk_const_list_from_iter(self, iter: I) -> T::Output where I: Iterator, From 9d7b1946549d433a19ee9f18bd842fd9bbaa368f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 11:40:28 +0000 Subject: [PATCH 06/10] Avoid fetching the opaque type origin when only "is this in the defining scope" is actually needed --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +-- compiler/rustc_infer/src/infer/mod.rs | 8 ++++++- .../rustc_infer/src/infer/opaque_types/mod.rs | 21 ++++--------------- .../src/solve/eval_ctxt/mod.rs | 6 +++--- .../src/solve/trait_goals.rs | 5 +---- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index dd44fdd889328..83275bc91a30a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -719,8 +719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ty in ret_ty.walk() { if let ty::GenericArgKind::Type(ty) = ty.unpack() && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind() - && let Some(def_id) = def_id.as_local() - && self.opaque_type_origin(def_id).is_some() + && self.can_define_opaque_ty(def_id) { return None; } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 403d2eb299a18..1ba022d39df08 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -235,7 +235,7 @@ pub struct InferCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, /// The `DefIds` of the opaque types that may have their hidden types constrained. - pub defining_opaque_types: &'tcx ty::List, + defining_opaque_types: &'tcx ty::List, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -1219,6 +1219,12 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow().opaque_type_storage.opaque_types.clone() } + #[inline(always)] + pub fn can_define_opaque_ty(&self, id: impl Into) -> bool { + let Some(id) = id.into().as_local() else { return false }; + self.defining_opaque_types.contains(&id) + } + pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { self.resolve_vars_if_possible(t).to_string() } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index d95a34d17e00a..3ef3c8b93664c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -4,7 +4,6 @@ use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, PredicateObligation}; use hir::def_id::{DefId, LocalDefId}; -use hir::OpaqueTyOrigin; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; @@ -54,16 +53,13 @@ impl<'tcx> InferCtxt<'tcx> { } let mut obligations = vec![]; - let replace_opaque_type = |def_id: DefId| { - def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some()) - }; let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, ct_op: |ct| ct, ty_op: |ty| match *ty.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) - if replace_opaque_type(def_id) && !ty.has_escaping_bound_vars() => + if self.can_define_opaque_ty(def_id) && !ty.has_escaping_bound_vars() => { let def_span = self.tcx.def_span(def_id); let span = if span.contains(def_span) { def_span } else { span }; @@ -143,7 +139,7 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - if self.opaque_type_origin(def_id).is_none() { + if !self.can_define_opaque_ty(def_id) { return None; } @@ -153,8 +149,8 @@ impl<'tcx> InferCtxt<'tcx> { // no one encounters it in practice. // It does occur however in `fn fut() -> impl Future { async { 42 } }`, // where it is of no concern, so we only check for TAITs. - if let Some(OpaqueTyOrigin::TyAlias { .. }) = - b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id)) + if self.can_define_opaque_ty(b_def_id) + && self.tcx.is_type_alias_impl_trait(b_def_id) { self.tcx.dcx().emit_err(OpaqueHiddenTypeDiag { span: cause.span, @@ -366,15 +362,6 @@ impl<'tcx> InferCtxt<'tcx> { op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions), }); } - - /// Returns the origin of the opaque type `def_id` if we're currently - /// in its defining scope. - #[instrument(skip(self), level = "trace", ret)] - pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option { - let origin = self.tcx.opaque_type_origin(def_id); - - self.defining_opaque_types.contains(&def_id).then_some(origin) - } } /// Visitor that requires that (almost) all regions in the type visited outlive diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 5111bb6e416f4..50b9e71ecc3ff 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1,5 +1,5 @@ use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -883,8 +883,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool { - self.infcx.opaque_type_origin(def_id).is_some() + pub(super) fn can_define_opaque_ty(&self, def_id: impl Into) -> bool { + self.infcx.can_define_opaque_ty(def_id) } pub(super) fn insert_hidden_type( diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 281f5cc5685d6..e5b318cebeb6c 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -149,10 +149,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { if matches!(goal.param_env.reveal(), Reveal::All) || matches!(ecx.solver_mode(), SolverMode::Coherence) - || opaque_ty - .def_id - .as_local() - .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) + || ecx.can_define_opaque_ty(opaque_ty.def_id) { return Err(NoSolution); } From 49e9cff8b6749cc51174cc7f20d594e7ebdc9943 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 12:16:51 +0000 Subject: [PATCH 07/10] Mark some tests as known-bugs and add the test case from the corresponding issue --- src/tools/tidy/src/issues.txt | 1 - .../issue-53398-cyclic-types.rs | 10 ----- .../issue-53398-cyclic-types.stderr | 9 ----- ...pe-alias-impl-trait-with-cycle-error-1.rs} | 2 +- ...lias-impl-trait-with-cycle-error-1.stderr} | 2 +- ...pe-alias-impl-trait-with-cycle-error-2.rs} | 2 +- ...lias-impl-trait-with-cycle-error-2.stderr} | 2 +- ...ype-alias-impl-trait-with-cycle-error-3.rs | 10 +++++ ...alias-impl-trait-with-cycle-error-3.stderr | 9 +++++ ...ype-alias-impl-trait-with-cycle-error-4.rs | 16 ++++++++ ...alias-impl-trait-with-cycle-error-4.stderr | 39 +++++++++++++++++++ 11 files changed, 78 insertions(+), 24 deletions(-) delete mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs delete mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error.rs => type-alias-impl-trait-with-cycle-error-1.rs} (82%) rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error.stderr => type-alias-impl-trait-with-cycle-error-1.stderr} (81%) rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error2.rs => type-alias-impl-trait-with-cycle-error-2.rs} (86%) rename tests/ui/type-alias-impl-trait/{type-alias-impl-trait-with-cycle-error2.stderr => type-alias-impl-trait-with-cycle-error-2.stderr} (80%) create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 91bbf5041ff58..5e80eee933a26 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -4147,7 +4147,6 @@ "ui/type-alias-impl-trait/issue-53092-2.rs", "ui/type-alias-impl-trait/issue-53092.rs", "ui/type-alias-impl-trait/issue-53096.rs", -"ui/type-alias-impl-trait/issue-53398-cyclic-types.rs", "ui/type-alias-impl-trait/issue-53598.rs", "ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs", "ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs", diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs deleted file mode 100644 index 9cc8546afbce7..0000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(type_alias_impl_trait)] - -type Foo = impl Fn() -> Foo; - -fn foo() -> Foo { - //~^ ERROR: overflow - foo -} - -fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr deleted file mode 100644 index 1358c3e2a98b8..0000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0275]: overflow evaluating the requirement ` Foo {foo} as FnOnce<()>>::Output == Foo` - --> $DIR/issue-53398-cyclic-types.rs:5:13 - | -LL | fn foo() -> Foo { - | ^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs similarity index 82% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs index 80ab53881a328..19986247d40df 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs @@ -1,9 +1,9 @@ #![feature(type_alias_impl_trait)] +//@ known-bug: #109268 type Foo = impl Fn() -> Foo; fn crash(x: Foo) -> Foo { - //~^ ERROR: overflow x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr similarity index 81% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr index 21779c7d1284a..ee8922b673e2f 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `>::Output == Foo` - --> $DIR/type-alias-impl-trait-with-cycle-error.rs:5:21 + --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21 | LL | fn crash(x: Foo) -> Foo { | ^^^ diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs similarity index 86% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs index 87b2d6765f4e2..761cc83af5106 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs @@ -1,4 +1,5 @@ #![feature(type_alias_impl_trait)] +//@ known-bug: #109268 pub trait Bar { type Item; @@ -7,7 +8,6 @@ pub trait Bar { type Foo = impl Bar; fn crash(x: Foo) -> Foo { - //~^ ERROR: overflow x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr similarity index 80% rename from tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr rename to tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr index d1c620968ba90..3d0f1d30ca2b0 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `>::Item == Foo` - --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:9:21 + --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:10:21 | LL | fn crash(x: Foo) -> Foo { | ^^^ diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs new file mode 100644 index 0000000000000..52942afd63922 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] +//@ known-bug: #109268 + +type Foo<'a> = impl Fn() -> Foo<'a>; + +fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + x +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr new file mode 100644 index 0000000000000..675689bac4295 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` + --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:6:40 + | +LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs new file mode 100644 index 0000000000000..e866b45a8e61d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] +//@ known-bug: trait-system-refactor-initiative#43 + +trait Id { + type Assoc; +} +impl Id for T { + type Assoc = T; +} + +type Ty +where + Ty: Id, += impl Sized; +fn define() -> Ty {} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr new file mode 100644 index 0000000000000..aedb78bf5e7a1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr @@ -0,0 +1,39 @@ +error[E0275]: overflow evaluating the requirement `Ty: Id` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:11:1 + | +LL | type Ty + | ^^^^^^^ + | +note: required by a bound on the type alias `Ty` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 + | +LL | Ty: Id, + | ^^^^^^^^^^^^^^ required by this bound + +error[E0275]: overflow evaluating the requirement `Ty: Id` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:19 + | +LL | fn define() -> Ty {} + | ^^ + | +note: required by a bound on the type alias `Ty` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 + | +LL | Ty: Id, + | ^^^^^^^^^^^^^^ required by this bound + +error[E0275]: overflow evaluating the requirement `Ty: Id` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:16 + | +LL | fn define() -> Ty {} + | ^^ + | +note: required by a bound on the type alias `Ty` + --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 + | +LL | Ty: Id, + | ^^^^^^^^^^^^^^ required by this bound + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. From aac18a84cd794a21de3565036f18db95a8789239 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 16:28:14 +0000 Subject: [PATCH 08/10] Add a FIXME for something that requires touching too much code for this PR --- compiler/rustc_type_ir/src/canonical.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index b2701ae744e09..d0ac6877bd79c 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -16,6 +16,7 @@ use crate::{Interner, PlaceholderLike, UniverseIndex}; pub struct Canonical { pub value: V, pub max_universe: UniverseIndex, + // FIXME(lcnr, oli-obk): try moving this into the query inputs instead pub defining_opaque_types: I::DefiningOpaqueTypes, pub variables: I::CanonicalVars, } From a3f98bb0c9d70ae0ca40118b95caa25e008c5a90 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 18:50:55 +0000 Subject: [PATCH 09/10] Some early clean-ups in method probe --- compiler/rustc_hir_typeck/src/method/probe.rs | 59 +++---------------- 1 file changed, 8 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index bdc796aca3a46..d7d0783cc8432 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::lint; use rustc_span::def_id::DefId; @@ -738,7 +738,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id); - let impl_ty = impl_ty.instantiate(self.tcx, impl_args); debug!("impl_ty: {:?}", impl_ty); @@ -811,7 +810,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return; } - let new_trait_ref = this.instantiate_bound_regions_with_erased(new_trait_ref); + let new_trait_ref = this.tcx.instantiate_bound_regions_with_erased(new_trait_ref); let (xform_self_ty, xform_ret_ty) = this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args); @@ -922,27 +921,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - fn matches_return_type( - &self, - method: ty::AssocItem, - self_ty: Option>, - expected: Ty<'tcx>, - ) -> bool { + fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool { match method.kind { ty::AssocKind::Fn => self.probe(|_| { let args = self.fresh_args_for_item(self.span, method.def_id); let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args); let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty); - - if let Some(self_ty) = self_ty { - if self - .at(&ObligationCause::dummy(), self.param_env) - .sup(DefineOpaqueTypes::No, fty.inputs()[0], self_ty) - .is_err() - { - return false; - } - } self.can_sub(self.param_env, fty.output(), expected) }), _ => false, @@ -1033,7 +1017,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .filter(|candidate| candidate_filter(&candidate.item)) .filter(|candidate| { if let Some(return_ty) = self.return_type { - self.matches_return_type(candidate.item, None, return_ty) + self.matches_return_type(candidate.item, return_ty) } else { true } @@ -1890,40 +1874,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn_sig.instantiate(self.tcx, args) }; - self.instantiate_bound_regions_with_erased(xform_fn_sig) + self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig) } /// Gets the type of an impl and generate generic parameters with inference vars. - fn impl_ty_and_args( - &self, - impl_def_id: DefId, - ) -> (ty::EarlyBinder>, GenericArgsRef<'tcx>) { - (self.tcx.type_of(impl_def_id), self.fresh_args_for_item(self.span, impl_def_id)) - } - - /// Replaces late-bound-regions bound by `value` with `'static` using - /// `ty::instantiate_bound_regions_with_erased`. - /// - /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of - /// method matching. It is reasonable during the probe phase because we don't consider region - /// relationships at all. Therefore, we can just replace all the region variables with 'static - /// rather than creating fresh region variables. This is nice for two reasons: - /// - /// 1. Because the numbers of the region variables would otherwise be fairly unique to this - /// particular method call, it winds up creating fewer types overall, which helps for memory - /// usage. (Admittedly, this is a rather small effect, though measurable.) - /// - /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any - /// late-bound regions with 'static. Otherwise, if we were going to replace late-bound - /// regions with actual region variables as is proper, we'd have to ensure that the same - /// region got replaced with the same variable, which requires a bit more coordination - /// and/or tracking the instantiations and - /// so forth. - fn instantiate_bound_regions_with_erased(&self, value: ty::Binder<'tcx, T>) -> T - where - T: TypeFoldable>, - { - self.tcx.instantiate_bound_regions_with_erased(value) + fn impl_ty_and_args(&self, impl_def_id: DefId) -> (Ty<'tcx>, GenericArgsRef<'tcx>) { + let args = self.fresh_args_for_item(self.span, impl_def_id); + (self.tcx.type_of(impl_def_id).instantiate(self.tcx, args), args) } /// Determine if the given associated item type is relevant in the current context. From fea073f4fb5e060520642154082ef25ad1bf905f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 19:43:20 -0400 Subject: [PATCH 10/10] Use fulfillment, not evaluate, during method probe --- compiler/rustc_hir_typeck/src/demand.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 419 ++++++------------ .../src/traits/engine.rs | 13 + tests/ui/derives/issue-91550.stderr | 27 +- ...gat-bound-during-assoc-ty-selection.stderr | 13 +- .../trait-bounds/issue-30786.stderr | 6 +- tests/ui/impl-trait/issues/issue-62742.stderr | 50 ++- tests/ui/impl-trait/issues/issue-84073.stderr | 28 +- .../option-as_deref.stderr | 1 + .../option-as_deref_mut.stderr | 1 + .../result-as_deref.stderr | 1 + .../result-as_deref_mut.stderr | 1 + tests/ui/issues/issue-57362-2.stderr | 6 +- .../ui/mismatched_types/issue-36053-2.stderr | 10 +- .../missing-trait-bounds/issue-35677.stderr | 2 - .../issue-57642-higher-ranked-subtype.stderr | 6 +- .../derive-trait-for-method-call.stderr | 24 +- ...t-trait-alias-bound-on-generic-impl.stderr | 7 - .../method-on-unbounded-type-param.stderr | 2 +- tests/ui/traits/track-obligations.stderr | 30 +- tests/ui/typeck/derive-sugg-arg-arity.stderr | 4 +- tests/ui/typeck/issue-31173.stderr | 2 +- 22 files changed, 245 insertions(+), 410 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 71da655434032..73a11335d7f64 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -894,7 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [candidate] => format!( "the method of the same name on {} `{}`", match candidate.kind { - probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for", + probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for", _ => "trait", }, self.tcx.def_path_str(candidate.item.container_id(self.tcx)) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index d7d0783cc8432..25bcfce3275a2 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -31,13 +31,12 @@ use rustc_span::edit_distance::{ }; use rustc_span::symbol::sym; use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP}; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; use rustc_trait_selection::traits::query::method_autoderef::{ CandidateStep, MethodAutoderefStepsResult, }; use rustc_trait_selection::traits::query::CanonicalTyGoal; -use rustc_trait_selection::traits::NormalizeExt; +use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::cell::RefCell; use std::cmp::max; @@ -99,39 +98,6 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { #[derive(Debug, Clone)] pub(crate) struct Candidate<'tcx> { - // Candidates are (I'm not quite sure, but they are mostly) basically - // some metadata on top of a `ty::AssocItem` (without args). - // - // However, method probing wants to be able to evaluate the predicates - // for a function with the args applied - for example, if a function - // has `where Self: Sized`, we don't want to consider it unless `Self` - // is actually `Sized`, and similarly, return-type suggestions want - // to consider the "actual" return type. - // - // The way this is handled is through `xform_self_ty`. It contains - // the receiver type of this candidate, but `xform_self_ty`, - // `xform_ret_ty` and `kind` (which contains the predicates) have the - // generic parameters of this candidate instantiated with the *same set* - // of inference variables, which acts as some weird sort of "query". - // - // When we check out a candidate, we require `xform_self_ty` to be - // a subtype of the passed-in self-type, and this equates the type - // variables in the rest of the fields. - // - // For example, if we have this candidate: - // ``` - // trait Foo { - // fn foo(&self) where Self: Sized; - // } - // ``` - // - // Then `xform_self_ty` will be `&'erased ?X` and `kind` will contain - // the predicate `?X: Sized`, so if we are evaluating `Foo` for a - // the receiver `&T`, we'll do the subtyping which will make `?X` - // get the right value, then when we evaluate the predicate we'll check - // if `T: Sized`. - xform_self_ty: Ty<'tcx>, - xform_ret_ty: Option>, pub(crate) item: ty::AssocItem, pub(crate) kind: CandidateKind<'tcx>, pub(crate) import_ids: SmallVec<[LocalDefId; 1]>, @@ -139,17 +105,10 @@ pub(crate) struct Candidate<'tcx> { #[derive(Debug, Clone)] pub(crate) enum CandidateKind<'tcx> { - InherentImplCandidate( - GenericArgsRef<'tcx>, - // Normalize obligations - Vec>, - ), - ObjectCandidate, - TraitCandidate(ty::TraitRef<'tcx>), - WhereClauseCandidate( - // Trait - ty::PolyTraitRef<'tcx>, - ), + InherentImplCandidate(DefId), + ObjectCandidate(ty::PolyTraitRef<'tcx>), + TraitCandidate(ty::PolyTraitRef<'tcx>), + WhereClauseCandidate(ty::PolyTraitRef<'tcx>), } #[derive(Debug, PartialEq, Eq, Copy, Clone)] @@ -736,41 +695,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.record_static_candidate(CandidateSource::Impl(impl_def_id)); continue; } - - let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id); - - debug!("impl_ty: {:?}", impl_ty); - - // Determine the receiver type that the method itself expects. - let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args); - debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty); - - // We can't use `FnCtxt::normalize` as it will pollute the - // fcx's fulfillment context after this probe is over. - // - // Note: we only normalize `xform_self_ty` here since the normalization - // of the return type can lead to inference results that prohibit - // valid candidates from being found, see issue #85671 - // - // FIXME Postponing the normalization of the return type likely only hides a deeper bug, - // which might be caused by the `param_env` itself. The clauses of the `param_env` - // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized, - // see issue #89650 - let cause = traits::ObligationCause::misc(self.span, self.body_id); - let InferOk { value: xform_self_ty, obligations } = - self.fcx.at(&cause, self.param_env).normalize(xform_self_ty); - - debug!( - "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}", - xform_self_ty, xform_ret_ty - ); - self.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, - kind: InherentImplCandidate(impl_args, obligations), + kind: InherentImplCandidate(impl_def_id), import_ids: smallvec![], }, true, @@ -802,26 +730,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // a `&self` method will wind up with an argument type like `&dyn Trait`. let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { - if new_trait_ref.has_non_region_bound_vars() { - this.dcx().span_delayed_bug( - this.span, - "tried to select method from HRTB with non-lifetime bound vars", - ); - return; - } - - let new_trait_ref = this.tcx.instantiate_bound_regions_with_erased(new_trait_ref); - - let (xform_self_ty, xform_ret_ty) = - this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args); this.push_candidate( - Candidate { - xform_self_ty, - xform_ret_ty, - item, - kind: ObjectCandidate, - import_ids: smallvec![], - }, + Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] }, true, ); }); @@ -852,19 +762,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { - let trait_ref = this.instantiate_binder_with_fresh_vars( - this.span, - infer::BoundRegionConversionTime::FnCall, - poly_trait_ref, - ); - - let (xform_self_ty, xform_ret_ty) = - this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.args); - this.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, kind: WhereClauseCandidate(poly_trait_ref), import_ids: smallvec![], @@ -955,21 +854,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { bound_trait_ref.def_id(), )); } else { - let new_trait_ref = self.instantiate_binder_with_fresh_vars( - self.span, - infer::BoundRegionConversionTime::FnCall, - bound_trait_ref, - ); - - let (xform_self_ty, xform_ret_ty) = - self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args); self.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, import_ids: import_ids.clone(), - kind: TraitCandidate(new_trait_ref), + kind: TraitCandidate(bound_trait_ref), }, false, ); @@ -988,16 +877,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.record_static_candidate(CandidateSource::Trait(trait_def_id)); continue; } - - let (xform_self_ty, xform_ret_ty) = - self.xform_self_ty(item, trait_ref.self_ty(), trait_args); self.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, import_ids: import_ids.clone(), - kind: TraitCandidate(trait_ref), + kind: TraitCandidate(ty::Binder::dummy(trait_ref)), }, false, ); @@ -1430,16 +1314,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { match candidate.kind { - InherentImplCandidate(..) => { + InherentImplCandidate(_) => { CandidateSource::Impl(candidate.item.container_id(self.tcx)) } - ObjectCandidate | WhereClauseCandidate(_) => { + ObjectCandidate(_) | WhereClauseCandidate(_) => { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { + let trait_ref = + self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, trait_ref); + let (xform_self_ty, _) = + self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args); let _ = self.at(&ObligationCause::dummy(), self.param_env).sup( DefineOpaqueTypes::No, - candidate.xform_self_ty, + xform_self_ty, self_ty, ); match self.select_trait_candidate(trait_ref) { @@ -1466,54 +1354,38 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); - self.probe(|_| { - // First check that the self type can be related. - let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup( - DefineOpaqueTypes::No, - probe.xform_self_ty, - self_ty, - ) { - Ok(InferOk { obligations, value: () }) => obligations, - Err(err) => { - debug!("--> cannot relate self-types {:?}", err); - return ProbeResult::NoMatch; - } - }; + self.probe(|snapshot| { + let outer_universe = self.universe(); let mut result = ProbeResult::Match; - let mut xform_ret_ty = probe.xform_ret_ty; - debug!(?xform_ret_ty); + let cause = &self.misc(self.span); + let ocx = ObligationCtxt::new(self); - let cause = traits::ObligationCause::misc(self.span, self.body_id); + let mut trait_predicate = None; + let (mut xform_self_ty, mut xform_ret_ty); - let mut parent_pred = None; - - // If so, impls may carry other conditions (e.g., where - // clauses) that must be considered. Make sure that those - // match as well (or at least may match, sometimes we - // don't have enough information to fully evaluate). match probe.kind { - InherentImplCandidate(args, ref ref_obligations) => { - // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`, - // see the reasons mentioned in the comments in `assemble_inherent_impl_probe` - // for why this is necessary - let InferOk { - value: normalized_xform_ret_ty, - obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); - xform_ret_ty = normalized_xform_ret_ty; - debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); - + InherentImplCandidate(impl_def_id) => { + let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id); + (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(probe.item, impl_ty, impl_args); + xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); + // FIXME: Weirdly, we normalize the ret ty in this candidate, but no other candidates. + xform_ret_ty = ocx.normalize(cause, self.param_env, xform_ret_ty); + match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + } // Check whether the impl imposes obligations we have to worry about. let impl_def_id = probe.item.container_id(self.tcx); - let impl_bounds = self.tcx.predicates_of(impl_def_id); - let impl_bounds = impl_bounds.instantiate(self.tcx, args); - - let InferOk { value: impl_bounds, obligations: norm_obligations } = - self.fcx.at(&cause, self.param_env).normalize(impl_bounds); - + let impl_bounds = + self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args); + let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds); // Convert the bounds into obligations. - let impl_obligations = traits::predicates_for_generics( + ocx.register_obligations(traits::predicates_for_generics( |idx, span| { let code = if span.is_dummy() { traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx) @@ -1529,106 +1401,56 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }, self.param_env, impl_bounds, - ); - - let candidate_obligations = impl_obligations - .chain(norm_obligations) - .chain(ref_obligations.iter().cloned()) - .chain(normalization_obligations); - - // Evaluate those obligations to see if they might possibly hold. - for o in candidate_obligations { - let o = self.resolve_vars_if_possible(o); - if !self.predicate_may_hold(&o) { - result = ProbeResult::NoMatch; - let parent_o = o.clone(); - let implied_obligations = traits::elaborate(self.tcx, vec![o]); - for o in implied_obligations { - let parent = if o == parent_o { - None - } else { - if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id()) - == self.tcx.lang_items().sized_trait() - { - // We don't care to talk about implicit `Sized` bounds. - continue; - } - Some(parent_o.predicate) - }; - if !self.predicate_may_hold(&o) { - possibly_unsatisfied_predicates.push(( - o.predicate, - parent, - Some(o.cause), - )); - } - } - } - } + )); } - - ObjectCandidate | WhereClauseCandidate(..) => { - // These have no additional conditions to check. - } - - TraitCandidate(trait_ref) => { + TraitCandidate(poly_trait_ref) => { + // Some trait methods are excluded for arrays before 2021. + // (`array.into_iter()` wants a slice iterator for compatibility.) if let Some(method_name) = self.method_name { - // Some trait methods are excluded for arrays before 2021. - // (`array.into_iter()` wants a slice iterator for compatibility.) if self_ty.is_array() && !method_name.span.at_least_rust_2021() { - let trait_def = self.tcx.trait_def(trait_ref.def_id); + let trait_def = self.tcx.trait_def(poly_trait_ref.def_id()); if trait_def.skip_array_during_method_dispatch { return ProbeResult::NoMatch; } } } - let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx); - parent_pred = Some(predicate); - let obligation = - traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate); - if !self.predicate_may_hold(&obligation) { - result = ProbeResult::NoMatch; - if self.probe(|_| { - match self.select_trait_candidate(trait_ref) { - Err(_) => return true, - Ok(Some(impl_source)) - if !impl_source.borrow_nested_obligations().is_empty() => - { - for obligation in impl_source.borrow_nested_obligations() { - // Determine exactly which obligation wasn't met, so - // that we can give more context in the error. - if !self.predicate_may_hold(obligation) { - let nested_predicate = - self.resolve_vars_if_possible(obligation.predicate); - let predicate = - self.resolve_vars_if_possible(predicate); - let p = if predicate == nested_predicate { - // Avoid "`MyStruct: Foo` which is required by - // `MyStruct: Foo`" in E0599. - None - } else { - Some(predicate) - }; - possibly_unsatisfied_predicates.push(( - nested_predicate, - p, - Some(obligation.cause.clone()), - )); - } - } - } - _ => { - // Some nested subobligation of this predicate - // failed. - let predicate = self.resolve_vars_if_possible(predicate); - possibly_unsatisfied_predicates.push((predicate, None, None)); - } - } - false - }) { - // This candidate's primary obligation doesn't even - // select - don't bother registering anything in - // `potentially_unsatisfied_predicates`. + + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + infer::FnCall, + poly_trait_ref, + ); + (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); + xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); + match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + } + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause.clone(), + self.param_env, + ty::Binder::dummy(trait_ref), + )); + trait_predicate = Some(ty::Binder::dummy(trait_ref).to_predicate(self.tcx)); + } + ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => { + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + infer::FnCall, + poly_trait_ref, + ); + (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); + xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); + match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); return ProbeResult::NoMatch; } } @@ -1636,11 +1458,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } // Evaluate those obligations to see if they might possibly hold. - for o in sub_obligations { - let o = self.resolve_vars_if_possible(o); - if !self.predicate_may_hold(&o) { - result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause))); + for error in ocx.select_where_possible() { + result = ProbeResult::NoMatch; + if let Some(trait_predicate) = trait_predicate + && self.resolve_vars_if_possible(error.obligation.predicate) + == self.resolve_vars_if_possible(trait_predicate) + { + // Don't report possibly unsatisfied predicates if the root + // trait obligation from a `TraitCandidate` is unsatisfied. + // That just means the candidate doesn't hold. + } else { + possibly_unsatisfied_predicates.push(( + error.obligation.predicate, + Some(error.root_obligation.predicate) + .filter(|predicate| *predicate != error.obligation.predicate), + Some(error.obligation.cause), + )); } } @@ -1652,38 +1485,34 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // We don't normalize the other candidates for perf/backwards-compat reasons... // but `self.return_type` is only set on the diagnostic-path, so we // should be okay doing it here. - if !matches!(probe.kind, InherentImplCandidate(..)) { - let InferOk { - value: normalized_xform_ret_ty, - obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); - xform_ret_ty = normalized_xform_ret_ty; - debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); - // Evaluate those obligations to see if they might possibly hold. - for o in normalization_obligations { - let o = self.resolve_vars_if_possible(o); - if !self.predicate_may_hold(&o) { - result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push(( - o.predicate, - None, - Some(o.cause), - )); - } - } + if !matches!(probe.kind, InherentImplCandidate(_)) { + xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty); } debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty); - if let ProbeResult::Match = result - && self - .at(&ObligationCause::dummy(), self.param_env) - .sup(DefineOpaqueTypes::No, return_ty, xform_ret_ty) - .is_err() - { - result = ProbeResult::BadReturnType; + match ocx.sup(cause, self.param_env, return_ty, xform_ret_ty) { + Ok(()) => {} + Err(_) => { + result = ProbeResult::BadReturnType; + } + } + + // Evaluate those obligations to see if they might possibly hold. + for error in ocx.select_where_possible() { + result = ProbeResult::NoMatch; + possibly_unsatisfied_predicates.push(( + error.obligation.predicate, + Some(error.root_obligation.predicate) + .filter(|predicate| *predicate != error.obligation.predicate), + Some(error.root_obligation.cause), + )); } } + if let Err(_) = self.leak_check(outer_universe, Some(snapshot)) { + result = ProbeResult::NoMatch; + } + result }) } @@ -2004,10 +1833,10 @@ impl<'tcx> Candidate<'tcx> { Pick { item: self.item, kind: match self.kind { - InherentImplCandidate(..) => InherentImplPick, - ObjectCandidate => ObjectPick, + InherentImplCandidate(_) => InherentImplPick, + ObjectCandidate(_) => ObjectPick, TraitCandidate(_) => TraitPick, - WhereClauseCandidate(ref trait_ref) => { + WhereClauseCandidate(trait_ref) => { // Only trait derived from where-clauses should // appear here, so they should not contain any // inference variables or other artifacts. This @@ -2018,7 +1847,7 @@ impl<'tcx> Candidate<'tcx> { && !trait_ref.skip_binder().args.has_placeholders() ); - WhereClausePick(*trait_ref) + WhereClausePick(trait_ref) } }, import_ids: self.import_ids.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 9fbec174ce8d2..68c76dcf29734 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -129,6 +129,19 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + pub fn eq_no_opaques>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + expected: T, + actual: T, + ) -> Result<(), TypeError<'tcx>> { + self.infcx + .at(cause, param_env) + .eq(DefineOpaqueTypes::No, expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + /// Checks whether `expected` is a subtype of `actual`: `expected <: actual`. pub fn sub>( &self, diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 9e17189671827..4d637c9728385 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet`, but its tr --> $DIR/issue-91550.rs:8:8 | LL | struct Value(u32); - | ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq` + | ------------ doesn't satisfy `Value: Eq` or `Value: Hash` ... LL | hs.insert(Value(0)); | ^^^^^^ | = note: the following trait bounds were not satisfied: `Value: Eq` - `Value: PartialEq` - which is required by `Value: Eq` `Value: Hash` help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]` | @@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object`, but its --> $DIR/issue-91550.rs:26:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq` + | -------------------- doesn't satisfy `NoDerives: Eq` LL | LL | struct Object(T); | ---------------- method `use_eq` not found for this struct @@ -37,9 +35,6 @@ LL | impl Object { | ^^ --------- | | | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `NoDerives: PartialEq` - which is required by `NoDerives: Eq` help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` | LL + #[derive(Eq, PartialEq)] @@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object`, but it --> $DIR/issue-91550.rs:27:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd` + | -------------------- doesn't satisfy `NoDerives: Ord` LL | LL | struct Object(T); | ---------------- method `use_ord` not found for this struct @@ -65,13 +60,6 @@ LL | impl Object { | ^^^ --------- | | | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `NoDerives: PartialOrd` - which is required by `NoDerives: Ord` - `NoDerives: PartialEq` - which is required by `NoDerives: Ord` - `NoDerives: Eq` - which is required by `NoDerives: Ord` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] @@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object $DIR/issue-91550.rs:28:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd` + | -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd` LL | LL | struct Object(T); | ---------------- method `use_ord_and_partial_ord` not found for this struct @@ -100,13 +88,6 @@ LL | impl Object { | | | | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `NoDerives: PartialEq` - which is required by `NoDerives: Ord` - `NoDerives: Eq` - which is required by `NoDerives: Ord` - `NoDerives: PartialEq` - which is required by `NoDerives: PartialOrd` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] diff --git a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr index 7813370ae63f8..b31689dbf7365 100644 --- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.stderr @@ -15,20 +15,15 @@ help: consider relaxing the implicit `Sized` restriction LL | type Pointer: Deref + ?Sized; | ++++++++ -error[E0599]: the size for values of type `Node` cannot be known at compilation time +error[E0599]: the variant or associated item `new` exists for enum `Node`, but its trait bounds were not satisfied --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:31:35 | LL | enum Node { - | ------------------------------ variant or associated item `new` not found for this enum because it doesn't satisfy `Node: Sized` + | ------------------------------ variant or associated item `new` not found for this enum ... LL | let mut list = RcNode::::new(); - | ^^^ doesn't have a size known at compile-time + | ^^^ variant or associated item cannot be called on `Node` due to unsatisfied trait bounds | -note: trait bound `Node: Sized` was not satisfied - --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:4:18 - | -LL | type Pointer: Deref; - | ------- ^ unsatisfied trait bound introduced here note: trait bound `(dyn Deref> + 'static): Sized` was not satisfied --> $DIR/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs:23:29 | @@ -37,8 +32,6 @@ LL | impl Node LL | where LL | P::Pointer>: Sized, | ^^^^^ unsatisfied trait bound introduced here -note: the trait `Sized` must be implemented - --> $SRC_DIR/core/src/marker.rs:LL:COL error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr index 699a4ecc42bb9..450893e24f160 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr @@ -2,7 +2,7 @@ error[E0599]: the method `filterx` exists for struct `Map $DIR/issue-30786.rs:120:22 | LL | pub struct Map { - | -------------------- method `filterx` not found for this struct because it doesn't satisfy `_: StreamExt` + | -------------------- method `filterx` not found for this struct ... LL | let filter = map.filterx(|x: &_| true); | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds @@ -10,7 +10,6 @@ LL | let filter = map.filterx(|x: &_| true); 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 {} @@ -26,7 +25,7 @@ error[E0599]: the method `countx` exists for struct `Filter $DIR/issue-30786.rs:132:24 | LL | pub struct Filter { - | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt` + | ----------------------- method `countx` not found for this struct ... LL | let count = filter.countx(); | ^^^^^^ method cannot be called due to unsatisfied trait bounds @@ -34,7 +33,6 @@ LL | let count = filter.countx(); 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 {} diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 9ec581c231b7b..f6798f55a472c 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -1,30 +1,27 @@ -error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied - --> $DIR/issue-62742.rs:4:5 +error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied + --> $DIR/issue-62742.rs:4:16 | LL | WrongImpl::foo(0i32); - | ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | ^^^ function or associated item cannot be called on `SafeImpl<_, RawImpl<_>>` due to unsatisfied trait bounds +... +LL | pub struct RawImpl(PhantomData); + | --------------------- doesn't satisfy `RawImpl<_>: Raw<_>` +... +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ----------------------------------------- function or associated item `foo` not found for this struct | - = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` -note: required by a bound in `SafeImpl::::foo` +note: trait bound `RawImpl<_>: Raw<_>` was not satisfied --> $DIR/issue-62742.rs:29:20 | LL | impl> SafeImpl { - | ^^^^^^ required by this bound in `SafeImpl::::foo` -LL | pub fn foo(value: A::Value) {} - | --- required by a bound in this associated function - -error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied - --> $DIR/issue-62742.rs:4:5 - | -LL | WrongImpl::foo(0i32); - | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` - | - = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` -note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:27:35 + | ^^^^^^ -------------- + | | + | unsatisfied trait bound introduced here +note: the trait `Raw` must be implemented + --> $DIR/issue-62742.rs:13:1 | -LL | pub struct SafeImpl>(PhantomData<(A, T)>); - | ^^^^^^ required by this bound in `SafeImpl` +LL | pub trait Raw { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied --> $DIR/issue-62742.rs:7:22 @@ -51,6 +48,19 @@ note: the trait `Raw` must be implemented LL | pub trait Raw { | ^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied + --> $DIR/issue-62742.rs:4:5 + | +LL | WrongImpl::foo(0i32); + | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | + = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` +note: required by a bound in `SafeImpl` + --> $DIR/issue-62742.rs:27:35 + | +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ^^^^^^ required by this bound in `SafeImpl` + error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied --> $DIR/issue-62742.rs:7:5 | diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index ab119a8a4f456..eeb23b130819d 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -1,9 +1,29 @@ -error[E0275]: overflow assigning `_` to `Option<_>` - --> $DIR/issue-84073.rs:32:22 +error[E0599]: the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied + --> $DIR/issue-84073.rs:32:27 | +LL | pub struct Never(PhantomData); + | ------------------- doesn't satisfy `Never<_>: StatefulFuture>` +... +LL | pub struct RaceBuilder { + | ---------------------------- method `when` not found for this struct +... LL | Race::new(|race| race.when()); - | ^^^^ + | ^^^^ method cannot be called on `RaceBuilder<_, Never<_>>` due to unsatisfied trait bounds + | +note: trait bound `Never<_>: StatefulFuture>` was not satisfied + --> $DIR/issue-84073.rs:14:8 + | +LL | impl RaceBuilder + | ----------------- +LL | where +LL | F: StatefulFuture>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: the trait `StatefulFuture` must be implemented + --> $DIR/issue-84073.rs:3:1 + | +LL | pub trait StatefulFuture {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 84247a4270484..0468e0522d1e7 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -6,6 +6,7 @@ LL | let _result = &Some(42).as_deref(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index bf05ab5665cba..cf4e866901cd9 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -6,6 +6,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index ac744a6d3b672..0e3e7999044fc 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -6,6 +6,7 @@ LL | let _result = &Ok(42).as_deref(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 688d2cf3486e8..43143db0da742 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -6,6 +6,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-57362-2.stderr b/tests/ui/issues/issue-57362-2.stderr index 57477f5341ede..a78c96dbd0d59 100644 --- a/tests/ui/issues/issue-57362-2.stderr +++ b/tests/ui/issues/issue-57362-2.stderr @@ -1,11 +1,9 @@ -error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied +error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope --> $DIR/issue-57362-2.rs:22:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds + | ^^^^^^ function or associated item not found in `fn(&())` | - = note: the following trait bounds were not satisfied: - `for<'a> fn(&'a ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57362-2.rs:8:1 diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr index 6d23319ca7e64..fdf75898ae25d 100644 --- a/tests/ui/mismatched_types/issue-36053-2.stderr +++ b/tests/ui/mismatched_types/issue-36053-2.stderr @@ -21,14 +21,16 @@ error[E0599]: the method `count` exists for struct `Filter>, {cl LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | --------- ^^^^^ method cannot be called due to unsatisfied trait bounds | | - | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>` + | doesn't satisfy `_: FnMut<(&&str,)>` or `_: FnOnce<(&&str,)>` | = note: the following trait bounds were not satisfied: - `<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool` - which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>` which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` - `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>` + which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>` + which is required by `&mut Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>` which is required by `&mut Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` error: aborting due to 2 previous errors diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index f73bff51e7ad1..3bfdd4da6dac8 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -6,8 +6,6 @@ LL | this.is_subset(other) | = note: the following trait bounds were not satisfied: `T: Eq` - `T: PartialEq` - which is required by `T: Eq` `T: Hash` help: consider restricting the type parameters to satisfy the trait bounds | diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr index d1e94bc702cae..679bab63e8531 100644 --- a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr +++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr @@ -1,11 +1,9 @@ -error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied +error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope --> $DIR/issue-57642-higher-ranked-subtype.rs:31:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds + | ^^^^^^ function or associated item not found in `fn(&())` | - = note: the following trait bounds were not satisfied: - `for<'a> fn(&'a ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57642-higher-ranked-subtype.rs:4:1 diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr index 9d6d29ec74eec..ae3a0391eea24 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.stderr +++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr @@ -74,22 +74,30 @@ LL | struct Struct { error[E0599]: the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied --> $DIR/derive-trait-for-method-call.rs:40:15 | +LL | enum Enum { + | --------- doesn't satisfy `Enum: Clone` +... LL | struct Foo (X, Y); | ---------------- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied: - `Instant: Default` - `Vec: Clone` - --> $DIR/derive-trait-for-method-call.rs:20:9 +note: trait bound `Instant: Default` was not satisfied + --> $DIR/derive-trait-for-method-call.rs:20:40 | LL | impl Foo { - | ^^^^^ ^^^^^^^ --------- - | | | - | | unsatisfied trait bound introduced here - | unsatisfied trait bound introduced here + | ^^^^^^^ --------- + | | + | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `Enum: Clone` + which is required by `Vec: Clone` +help: consider annotating `Enum` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | enum Enum { + | error: aborting due to 3 previous errors diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr index 74526b4dbc182..49a4db7491ed8 100644 --- a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr +++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr @@ -12,13 +12,6 @@ note: trait bound `(): Iterator` was not satisfied | LL | trait IteratorAlias = Iterator; | ------------- ^^^^^^^^ unsatisfied trait bound introduced here -note: trait bound `(): IteratorAlias` was not satisfied - --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9 - | -LL | impl Foo { - | ^^^^^^^^^^^^^ ------ - | | - | unsatisfied trait bound introduced here error: aborting due to 1 previous error diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr index 0d8bd8ee964e7..7203d820ba0b2 100644 --- a/tests/ui/traits/method-on-unbounded-type-param.stderr +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -70,7 +70,7 @@ LL | x.cmp(&x); which is required by `Box: Iterator` `dyn T: Ord` which is required by `Box: Ord` - `Box: Iterator` + `dyn T: Iterator` which is required by `&mut Box: Iterator` `dyn T: Iterator` which is required by `&mut dyn T: Iterator` diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr index 822fc91e43fea..141f565077a5b 100644 --- a/tests/ui/traits/track-obligations.stderr +++ b/tests/ui/traits/track-obligations.stderr @@ -2,7 +2,10 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b --> $DIR/track-obligations.rs:83:16 | LL | struct ALayer(C); - | ---------------- doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>` + | ---------------- doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` +... +LL | struct AService; + | --------------- doesn't satisfy `>::Response = Res` ... LL | struct Client(C); | ---------------- method `check` not found for this struct @@ -10,27 +13,14 @@ LL | struct Client(C); LL | Client(()).check(); | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds | -note: trait bound ` as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` was not satisfied - --> $DIR/track-obligations.rs:35:14 - | -LL | pub trait ParticularServiceLayer: - | ---------------------- -LL | Layer>::Service> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here -note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied - --> $DIR/track-obligations.rs:71:16 +note: trait bound `>::Response = Res` was not satisfied + --> $DIR/track-obligations.rs:24:21 | -LL | impl Client - | --------- +LL | impl ParticularService for T + | ----------------- - LL | where -LL | ALayer: ParticularServiceLayer, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here -note: the trait `ParticularServiceLayer` must be implemented - --> $DIR/track-obligations.rs:34:1 - | -LL | / pub trait ParticularServiceLayer: -LL | | Layer>::Service> - | |____________________________________________________________________^ +LL | T: Service, + | ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here error[E0271]: type mismatch resolving `>::Response == Res` --> $DIR/track-obligations.rs:87:11 diff --git a/tests/ui/typeck/derive-sugg-arg-arity.stderr b/tests/ui/typeck/derive-sugg-arg-arity.stderr index 382b324c4cc50..477cec5bc1f3a 100644 --- a/tests/ui/typeck/derive-sugg-arg-arity.stderr +++ b/tests/ui/typeck/derive-sugg-arg-arity.stderr @@ -9,9 +9,9 @@ LL | _ => match A::partial_cmp() {}, | = note: the following trait bounds were not satisfied: `A: PartialOrd<_>` - which is required by `&A: PartialOrd<&_>` + which is required by `&A: PartialOrd<_>` `A: PartialOrd<_>` - which is required by `&mut A: PartialOrd<&mut _>` + which is required by `&mut A: PartialOrd<_>` `A: Iterator` which is required by `&mut A: Iterator` note: the trait `Iterator` must be implemented diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr index 0983147a5f0c5..5fee16b5e89f7 100644 --- a/tests/ui/typeck/issue-31173.stderr +++ b/tests/ui/typeck/issue-31173.stderr @@ -39,7 +39,7 @@ LL | | .collect(); = note: the following trait bounds were not satisfied: `, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` which is required by `Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` - `Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` + `, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` which is required by `&mut Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` error: aborting due to 2 previous errors