Skip to content

Commit 2622e1a

Browse files
committed
Allow defining opaque types in where clause candidate selection
1 parent 2f4fbf8 commit 2622e1a

File tree

9 files changed

+40
-79
lines changed

9 files changed

+40
-79
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_infer::infer::region_constraints::RegionConstraintData;
1919
use rustc_infer::infer::{
2020
BoundRegion, BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin,
2121
};
22+
use rustc_infer::traits::{Obligation, ObligationCause};
2223
use rustc_middle::mir::tcx::PlaceTy;
2324
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
2425
use rustc_middle::mir::*;
@@ -40,6 +41,7 @@ use rustc_span::symbol::sym;
4041
use rustc_span::Span;
4142
use rustc_span::DUMMY_SP;
4243
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
44+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
4345
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
4446
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
4547
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -1799,7 +1801,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
17991801
// `Sized` bound in no way depends on precise regions, so this
18001802
// shouldn't affect `is_sized`.
18011803
let erased_ty = tcx.erase_regions(ty);
1802-
if !erased_ty.is_sized(tcx, self.param_env) {
1804+
let sized_trait = tcx.require_lang_item(LangItem::Sized, Some(span));
1805+
let trait_ref = ty::TraitRef::new(tcx, sized_trait, [erased_ty]);
1806+
1807+
let is_sized = self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
1808+
tcx,
1809+
ObligationCause::dummy_with_span(span),
1810+
self.param_env,
1811+
trait_ref,
1812+
));
1813+
if !is_sized {
18031814
// in current MIR construction, all non-control-flow rvalue
18041815
// expressions evaluate through `as_temp` or `into` a return
18051816
// slot or local, so to find all unsized rvalues it is enough

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2675,7 +2675,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
26752675
);
26762676
self.infcx
26772677
.at(&obligation.cause, obligation.param_env)
2678-
.eq(DefineOpaqueTypes::No, predicate.trait_ref, trait_ref)
2678+
.eq(DefineOpaqueTypes::Yes, predicate.trait_ref, trait_ref)
26792679
.map(|InferOk { obligations, .. }| obligations)
26802680
.map_err(|_| ())
26812681
}

tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
2-
--> $DIR/norm-before-method-resolution-opaque-type.rs:16:19
2+
--> $DIR/norm-before-method-resolution-opaque-type.rs:15:19
33
|
44
LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
55
| ^ cannot satisfy `Foo == _`
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,11 @@
1-
error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
2-
--> $DIR/norm-before-method-resolution-opaque-type.rs:16:4
1+
error[E0161]: cannot move a value of type `<X as Trait<'_>>::Out<Foo>`
2+
--> $DIR/norm-before-method-resolution-opaque-type.rs:21:9
33
|
4-
LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
5-
| ^^^^^^^^^^^
6-
|
7-
= note: consider moving the opaque type's declaration and defining uses into a separate module
8-
note: this opaque type is in the signature
9-
--> $DIR/norm-before-method-resolution-opaque-type.rs:13:12
10-
|
11-
LL | type Foo = impl Sized;
12-
| ^^^^^^^^^^
13-
14-
error: unconstrained opaque type
15-
--> $DIR/norm-before-method-resolution-opaque-type.rs:13:12
16-
|
17-
LL | type Foo = impl Sized;
18-
| ^^^^^^^^^^
19-
|
20-
= note: `Foo` must be used in combination with a concrete type within the same module
4+
LL | let x = *x;
5+
| ^ the size of `<X as Trait<'_>>::Out<Foo>` cannot be statically determined
216

227
error[E0507]: cannot move out of `*x` which is behind a shared reference
23-
--> $DIR/norm-before-method-resolution-opaque-type.rs:23:13
8+
--> $DIR/norm-before-method-resolution-opaque-type.rs:21:13
249
|
2510
LL | let x = *x;
2611
| ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
@@ -31,6 +16,7 @@ LL - let x = *x;
3116
LL + let x = x;
3217
|
3318

34-
error: aborting due to 3 previous errors
19+
error: aborting due to 2 previous errors
3520

36-
For more information about this error, try `rustc --explain E0507`.
21+
Some errors have detailed explanations: E0161, E0507.
22+
For more information about an error, try `rustc --explain E0161`.

tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,15 @@ impl<'a, T> Trait<'a> for T {
1111
}
1212

1313
type Foo = impl Sized;
14-
//[old]~^ ERROR: unconstrained opaque type
1514

1615
fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
17-
//[old]~^ ERROR: item does not constrain
18-
//[next]~^^ ERROR: cannot satisfy `Foo == _`
16+
//[next]~^ ERROR: cannot satisfy `Foo == _`
1917
where
2018
for<'a> X: Trait<'a>,
2119
for<'a> <X as Trait<'a>>::Out<()>: Copy,
2220
{
2321
let x = *x; //[old]~ ERROR: cannot move out of `*x`
22+
//[old]~^ ERROR: cannot move a value of type `<X as Trait<'_>>::Out<Foo>`
2423
todo!();
2524
}
2625

tests/ui/impl-trait/bind-hidden-type-in-projection-matching.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ impl<'a, T> Trait<'a> for T {
88
}
99

1010
type Foo = impl Sized;
11-
//~^ ERROR: unconstrained opaque type
1211

1312
fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
14-
//~^ ERROR: item does not constrain
1513
where
1614
for<'a> X: Trait<'a>,
1715
for<'a> <X as Trait<'a>>::Out<()>: Copy,
1816
{
1917
let x = *x; //~ ERROR: cannot move out of `*x`
18+
//~^ ERROR: cannot move a value of type `<X as Trait<'_>>::Out<Foo>`
2019
todo!();
2120
}
2221

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,11 @@
1-
error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
2-
--> $DIR/bind-hidden-type-in-projection-matching.rs:13:4
1+
error[E0161]: cannot move a value of type `<X as Trait<'_>>::Out<Foo>`
2+
--> $DIR/bind-hidden-type-in-projection-matching.rs:17:9
33
|
4-
LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
5-
| ^^^^^^^^^^^
6-
|
7-
= note: consider moving the opaque type's declaration and defining uses into a separate module
8-
note: this opaque type is in the signature
9-
--> $DIR/bind-hidden-type-in-projection-matching.rs:10:12
10-
|
11-
LL | type Foo = impl Sized;
12-
| ^^^^^^^^^^
13-
14-
error: unconstrained opaque type
15-
--> $DIR/bind-hidden-type-in-projection-matching.rs:10:12
16-
|
17-
LL | type Foo = impl Sized;
18-
| ^^^^^^^^^^
19-
|
20-
= note: `Foo` must be used in combination with a concrete type within the same module
4+
LL | let x = *x;
5+
| ^ the size of `<X as Trait<'_>>::Out<Foo>` cannot be statically determined
216

227
error[E0507]: cannot move out of `*x` which is behind a shared reference
23-
--> $DIR/bind-hidden-type-in-projection-matching.rs:19:13
8+
--> $DIR/bind-hidden-type-in-projection-matching.rs:17:13
249
|
2510
LL | let x = *x;
2611
| ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
@@ -31,6 +16,7 @@ LL - let x = *x;
3116
LL + let x = x;
3217
|
3318

34-
error: aborting due to 3 previous errors
19+
error: aborting due to 2 previous errors
3520

36-
For more information about this error, try `rustc --explain E0507`.
21+
Some errors have detailed explanations: E0161, E0507.
22+
For more information about an error, try `rustc --explain E0161`.

tests/ui/impl-trait/nested_impl_trait.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
55

66
fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
77
//~^ ERROR nested `impl Trait` is not allowed
8-
//~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
98

109
fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
1110
//~^ ERROR nested `impl Trait` is not allowed
@@ -18,7 +17,6 @@ struct X;
1817
impl X {
1918
fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
2019
//~^ ERROR nested `impl Trait` is not allowed
21-
//~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
2220
}
2321

2422
fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {

tests/ui/impl-trait/nested_impl_trait.stderr

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
88
| outer `impl Trait`
99

1010
error[E0666]: nested `impl Trait` is not allowed
11-
--> $DIR/nested_impl_trait.rs:10:42
11+
--> $DIR/nested_impl_trait.rs:9:42
1212
|
1313
LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
1414
| ----------^^^^^^^^^^-
@@ -17,7 +17,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
1717
| outer `impl Trait`
1818

1919
error[E0666]: nested `impl Trait` is not allowed
20-
--> $DIR/nested_impl_trait.rs:14:37
20+
--> $DIR/nested_impl_trait.rs:13:37
2121
|
2222
LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
2323
| ----------^^^^^^^^^^-
@@ -26,7 +26,7 @@ LL | fn bad_in_arg_position(_: impl Into<impl Debug>) { }
2626
| outer `impl Trait`
2727

2828
error[E0666]: nested `impl Trait` is not allowed
29-
--> $DIR/nested_impl_trait.rs:19:44
29+
--> $DIR/nested_impl_trait.rs:18:44
3030
|
3131
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
3232
| ----------^^^^^^^^^^-
@@ -35,32 +35,14 @@ LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
3535
| outer `impl Trait`
3636

3737
error[E0562]: `impl Trait` is not allowed in `fn` pointer return types
38-
--> $DIR/nested_impl_trait.rs:10:32
38+
--> $DIR/nested_impl_trait.rs:9:32
3939
|
4040
LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
4141
| ^^^^^^^^^^^^^^^^^^^^^
4242
|
4343
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
4444

45-
error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
46-
--> $DIR/nested_impl_trait.rs:6:46
47-
|
48-
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
49-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
50-
|
51-
= help: the trait `Into<U>` is implemented for `T`
52-
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
53-
54-
error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
55-
--> $DIR/nested_impl_trait.rs:19:34
56-
|
57-
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
58-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
59-
|
60-
= help: the trait `Into<U>` is implemented for `T`
61-
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
62-
63-
error: aborting due to 7 previous errors
45+
error: aborting due to 5 previous errors
6446

65-
Some errors have detailed explanations: E0277, E0562, E0666.
66-
For more information about an error, try `rustc --explain E0277`.
47+
Some errors have detailed explanations: E0562, E0666.
48+
For more information about an error, try `rustc --explain E0562`.

0 commit comments

Comments
 (0)