Skip to content

Commit

Permalink
Do not look in ParamEnv for opaque type bounds that could be satisfied
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jun 26, 2024
1 parent d79bd79 commit 48cb487
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,42 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
predicate: self.infcx.resolve_vars_if_possible(obligation.predicate),
};

if obligation.predicate.skip_binder().self_ty().is_ty_var() {
debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type");
// Self is a type variable (e.g., `_: AsRef<str>`).
//
// This is somewhat problematic, as the current scheme can't really
// handle it turning to be a projection. This does end up as truly
// ambiguous in most cases anyway.
//
// Take the fast path out - this also improves
// performance by preventing assemble_candidates_from_impls from
// matching every impl for this trait.
return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
}

let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
let def_id = obligation.predicate.def_id();
let tcx = self.tcx();

match obligation.predicate.skip_binder().self_ty().kind() {
// Opaque types in their defining scope are just like inference vars...
ty::Alias(ty::Opaque, alias) if self.infcx.can_define_opaque_ty(alias.def_id) => {
if tcx.is_lang_item(def_id, LangItem::Unsize) {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
}
self.assemble_candidates_from_impls(obligation, &mut candidates);
// .. unless we are looking for candidates just on the opaque signature, ...
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
// .. or for auto traits, which look at the hidden type.
// Auto traits must be collected after projected tys, because opaque types
// do not emit auto trait candidates if a projection for the same auto trait
// already exists (e.g. due to the bounds on the opaque).
self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
return Ok(candidates);
}
ty::Infer(ty::TyVar(vid)) => {
debug!(?vid, "ambiguous inference var");
// Self is a type variable (e.g., `_: AsRef<str>`).
//
// This is somewhat problematic, as the current scheme can't really
// handle it turning to be a projection. This does end up as truly
// ambiguous in most cases anyway.
//
// Take the fast path out - this also improves
// performance by preventing assemble_candidates_from_impls from
// matching every impl for this trait.
candidates.ambiguous = true;
return Ok(candidates);
}
_ => {}
}

// Negative trait predicates have different rules than positive trait predicates.
if obligation.polarity() == ty::PredicatePolarity::Negative {
Expand All @@ -66,8 +87,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

// Other bounds. Consider both in-scope bounds from fn decl
// and applicable impls. There is a certain set of precedence rules here.
let def_id = obligation.predicate.def_id();
let tcx = self.tcx();

if tcx.is_lang_item(def_id, LangItem::Copy) {
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/in-where-clause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
#![feature(type_alias_impl_trait)]
type Bar = impl Sized;
//~^ ERROR: cycle
//~| ERROR: cycle

fn foo() -> Bar
where
Bar: Send,
{
[0; 1 + 2]
//~^ ERROR: cannot check whether the hidden type
}

fn main() {}
27 changes: 14 additions & 13 deletions tests/ui/type-alias-impl-trait/in-where-clause.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ note: ...which requires computing type of opaque `Bar::{opaque#0}`...
LL | type Bar = impl Sized;
| ^^^^^^^^^^
note: ...which requires type-checking `foo`...
--> $DIR/in-where-clause.rs:9:1
--> $DIR/in-where-clause.rs:8:1
|
LL | / fn foo() -> Bar
LL | | where
Expand All @@ -25,25 +25,26 @@ LL | type Bar = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information

error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires type-checking `foo`...
--> $DIR/in-where-clause.rs:13:9
error: cannot check whether the hidden type of `in_where_clause[cb1b]::Bar::{opaque#0}` satisfies auto traits
--> $DIR/in-where-clause.rs:12:9
|
LL | [0; 1 + 2]
| ^^^^^
= note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`...
= note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle
note: cycle used when computing type of `Bar::{opaque#0}`
|
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
note: opaque type is declared here
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
note: required by a bound in `foo`
--> $DIR/in-where-clause.rs:10:10
|
LL | fn foo() -> Bar
| --- required by a bound in this function
LL | where
LL | Bar: Send,
| ^^^^ required by this bound in `foo`

error: aborting due to 2 previous errors

Expand Down

0 comments on commit 48cb487

Please sign in to comment.