Skip to content

Commit 48cb487

Browse files
committed
Do not look in ParamEnv for opaque type bounds that could be satisfied
1 parent d79bd79 commit 48cb487

File tree

3 files changed

+50
-30
lines changed

3 files changed

+50
-30
lines changed

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,42 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
4040
predicate: self.infcx.resolve_vars_if_possible(obligation.predicate),
4141
};
4242

43-
if obligation.predicate.skip_binder().self_ty().is_ty_var() {
44-
debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type");
45-
// Self is a type variable (e.g., `_: AsRef<str>`).
46-
//
47-
// This is somewhat problematic, as the current scheme can't really
48-
// handle it turning to be a projection. This does end up as truly
49-
// ambiguous in most cases anyway.
50-
//
51-
// Take the fast path out - this also improves
52-
// performance by preventing assemble_candidates_from_impls from
53-
// matching every impl for this trait.
54-
return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
55-
}
56-
5743
let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
44+
let def_id = obligation.predicate.def_id();
45+
let tcx = self.tcx();
46+
47+
match obligation.predicate.skip_binder().self_ty().kind() {
48+
// Opaque types in their defining scope are just like inference vars...
49+
ty::Alias(ty::Opaque, alias) if self.infcx.can_define_opaque_ty(alias.def_id) => {
50+
if tcx.is_lang_item(def_id, LangItem::Unsize) {
51+
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
52+
}
53+
self.assemble_candidates_from_impls(obligation, &mut candidates);
54+
// .. unless we are looking for candidates just on the opaque signature, ...
55+
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
56+
// .. or for auto traits, which look at the hidden type.
57+
// Auto traits must be collected after projected tys, because opaque types
58+
// do not emit auto trait candidates if a projection for the same auto trait
59+
// already exists (e.g. due to the bounds on the opaque).
60+
self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
61+
return Ok(candidates);
62+
}
63+
ty::Infer(ty::TyVar(vid)) => {
64+
debug!(?vid, "ambiguous inference var");
65+
// Self is a type variable (e.g., `_: AsRef<str>`).
66+
//
67+
// This is somewhat problematic, as the current scheme can't really
68+
// handle it turning to be a projection. This does end up as truly
69+
// ambiguous in most cases anyway.
70+
//
71+
// Take the fast path out - this also improves
72+
// performance by preventing assemble_candidates_from_impls from
73+
// matching every impl for this trait.
74+
candidates.ambiguous = true;
75+
return Ok(candidates);
76+
}
77+
_ => {}
78+
}
5879

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

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

7291
if tcx.is_lang_item(def_id, LangItem::Copy) {
7392
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());

tests/ui/type-alias-impl-trait/in-where-clause.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
#![feature(type_alias_impl_trait)]
55
type Bar = impl Sized;
66
//~^ ERROR: cycle
7-
//~| ERROR: cycle
87

98
fn foo() -> Bar
109
where
1110
Bar: Send,
1211
{
1312
[0; 1 + 2]
13+
//~^ ERROR: cannot check whether the hidden type
1414
}
1515

1616
fn main() {}

tests/ui/type-alias-impl-trait/in-where-clause.stderr

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ note: ...which requires computing type of opaque `Bar::{opaque#0}`...
1010
LL | type Bar = impl Sized;
1111
| ^^^^^^^^^^
1212
note: ...which requires type-checking `foo`...
13-
--> $DIR/in-where-clause.rs:9:1
13+
--> $DIR/in-where-clause.rs:8:1
1414
|
1515
LL | / fn foo() -> Bar
1616
LL | | where
@@ -25,25 +25,26 @@ LL | type Bar = impl Sized;
2525
| ^^^^^^^^^^
2626
= 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
2727

28-
error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
29-
--> $DIR/in-where-clause.rs:5:12
30-
|
31-
LL | type Bar = impl Sized;
32-
| ^^^^^^^^^^
33-
|
34-
note: ...which requires type-checking `foo`...
35-
--> $DIR/in-where-clause.rs:13:9
28+
error: cannot check whether the hidden type of `in_where_clause[cb1b]::Bar::{opaque#0}` satisfies auto traits
29+
--> $DIR/in-where-clause.rs:12:9
3630
|
3731
LL | [0; 1 + 2]
3832
| ^^^^^
39-
= note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`...
40-
= note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle
41-
note: cycle used when computing type of `Bar::{opaque#0}`
33+
|
34+
= 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
35+
note: opaque type is declared here
4236
--> $DIR/in-where-clause.rs:5:12
4337
|
4438
LL | type Bar = impl Sized;
4539
| ^^^^^^^^^^
46-
= 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
40+
note: required by a bound in `foo`
41+
--> $DIR/in-where-clause.rs:10:10
42+
|
43+
LL | fn foo() -> Bar
44+
| --- required by a bound in this function
45+
LL | where
46+
LL | Bar: Send,
47+
| ^^^^ required by this bound in `foo`
4748

4849
error: aborting due to 2 previous errors
4950

0 commit comments

Comments
 (0)