From 07141681cbcc097718003ad64e0c87bf1d8d56cd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 5 Jun 2024 09:57:50 +0000 Subject: [PATCH] Do not use global cache for selection candidates if opaque types can be constrained --- .../src/traits/select/mod.rs | 13 ++++++++++++ .../occurs-check/opaques.next.stderr | 4 ++-- .../coherence/occurs-check/opaques.old.stderr | 21 +++++++++++++++++++ tests/ui/coherence/occurs-check/opaques.rs | 4 +--- tests/ui/impl-trait/equality.rs | 2 +- tests/ui/impl-trait/equality.stderr | 4 ++-- .../escaping-bound-var.rs | 1 + .../escaping-bound-var.stderr | 10 ++++++++- 8 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 tests/ui/coherence/occurs-check/opaques.old.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2489b8916d181..dcdd337ba76bc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -49,6 +49,7 @@ use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::Symbol; +use rustc_type_ir::InferCtxtLike as _; use std::cell::{Cell, RefCell}; use std::cmp; @@ -1557,6 +1558,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.is_intercrate() { return None; } + + // Opaque types are not part of the global cache key, so we'd be caching and loading + // values, even though we don't have all the information that went into them. + if !self.infcx.defining_opaque_types().is_empty() { + return None; + } + let tcx = self.tcx(); let pred = cache_fresh_trait_pred.skip_binder(); @@ -1595,6 +1603,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.is_intercrate() { return false; } + // Opaque types are not part of the global cache key, so we'd be caching and loading + // values, even though we don't have all the information that went into them. + if !self.infcx.defining_opaque_types().is_empty() { + return false; + } match result { Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(), _ => true, diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 11d1edcca2f91..3de479963bb44 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:30:1 + --> $DIR/opaques.rs:28:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0282]: type annotations needed - --> $DIR/opaques.rs:13:20 + --> $DIR/opaques.rs:11:20 | LL | pub fn cast(x: Container, T>) -> Container { | ^ cannot infer type diff --git a/tests/ui/coherence/occurs-check/opaques.old.stderr b/tests/ui/coherence/occurs-check/opaques.old.stderr new file mode 100644 index 0000000000000..faade2747f281 --- /dev/null +++ b/tests/ui/coherence/occurs-check/opaques.old.stderr @@ -0,0 +1,21 @@ +error[E0284]: type annotations needed + --> $DIR/opaques.rs:11:20 + | +LL | pub fn cast(x: Container, T>) -> Container { + | ^ cannot infer type + | + = note: cannot satisfy ` as Trait>::Assoc == _` +note: required because it appears within the type `Container, T>` + --> $DIR/opaques.rs:17:8 + | +LL | struct Container, U> { + | ^^^^^^^^^ + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | pub fn cast(x: &Container, T>) -> Container { + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index 241a247c84130..eacb61fabc64e 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -3,15 +3,13 @@ // A regression test for #105787 -//@[old] known-bug: #105787 -//@[old] check-pass #![feature(type_alias_impl_trait)] mod defining_scope { use super::*; pub type Alias = impl Sized; pub fn cast(x: Container, T>) -> Container { - //[next]~^ ERROR type annotations needed + //~^ ERROR type annotations needed x } } diff --git a/tests/ui/impl-trait/equality.rs b/tests/ui/impl-trait/equality.rs index 952f81f19784c..e4ce0f7111d1c 100644 --- a/tests/ui/impl-trait/equality.rs +++ b/tests/ui/impl-trait/equality.rs @@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo { 0 } else { n + sum_to(n - 1) - //~^ ERROR cannot satisfy `>::Output == i32` + //~^ ERROR cannot satisfy `>::Output == u32` } } diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr index c9ba1a5ba32d1..9b6706d44478e 100644 --- a/tests/ui/impl-trait/equality.stderr +++ b/tests/ui/impl-trait/equality.stderr @@ -22,11 +22,11 @@ help: change the type of the numeric literal from `u32` to `i32` LL | 0_i32 | ~~~ -error[E0284]: type annotations needed: cannot satisfy `>::Output == i32` +error[E0284]: type annotations needed: cannot satisfy `>::Output == u32` --> $DIR/equality.rs:24:11 | LL | n + sum_to(n - 1) - | ^ cannot satisfy `>::Output == i32` + | ^ cannot satisfy `>::Output == u32` error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs index 1ff200680be5e..2883a428d5435 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs @@ -8,6 +8,7 @@ trait Test<'a> {} pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` +//~| ERROR unconstrained opaque type impl Trait<'_> for () { type Assoc = (); diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr index 09f6fba79cfdf..dd2a9b2ade577 100644 --- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr +++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr @@ -10,6 +10,14 @@ note: lifetime declared here LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; | ^^ -error: aborting due to 1 previous error +error: unconstrained opaque type + --> $DIR/escaping-bound-var.rs:9:47 + | +LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>; + | ^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0657`.