Skip to content

Commit 524d2b3

Browse files
committed
Make RPIT and TAIT work exactly the same
1 parent 493c960 commit 524d2b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+359
-221
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ pub struct OpaqueTypeDecl<'tcx> {
3838
pub origin: hir::OpaqueTyOrigin,
3939
}
4040

41+
pub enum ReplaceOpaqueTypes {
42+
/// Closures can't create hidden types for opaque types of their parent, as they
43+
/// do not have all the outlives information available. Also `type_of` looks for
44+
/// hidden types in the owner (so the closure's parent), so it would not find these
45+
/// definitions.
46+
OnlyForRPIT,
47+
All,
48+
}
49+
4150
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
4251
pub fn replace_opaque_types_with_inference_vars(
4352
&self,
@@ -46,27 +55,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
4655
span: Span,
4756
code: ObligationCauseCode<'tcx>,
4857
param_env: ty::ParamEnv<'tcx>,
58+
replace: ReplaceOpaqueTypes,
4959
) -> InferOk<'tcx, Ty<'tcx>> {
5060
if !ty.has_opaque_types() {
5161
return InferOk { value: ty, obligations: vec![] };
5262
}
5363
let mut obligations = vec![];
64+
let replace_opaque_type = |def_id| match self.opaque_type_origin(def_id, span) {
65+
None => false,
66+
Some(OpaqueTyOrigin::FnReturn(..)) => true,
67+
// Not using `==` or `matches!` here to make sure we exhaustively match variants.
68+
Some(_) => match replace {
69+
ReplaceOpaqueTypes::OnlyForRPIT => false,
70+
ReplaceOpaqueTypes::All => true,
71+
},
72+
};
5473
let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
5574
tcx: self.tcx,
5675
lt_op: |lt| lt,
5776
ct_op: |ct| ct,
5877
ty_op: |ty| match *ty.kind() {
59-
// Closures can't create hidden types for opaque types of their parent, as they
60-
// do not have all the outlives information available. Also `type_of` looks for
61-
// hidden types in the owner (so the closure's parent), so it would not find these
62-
// definitions.
63-
ty::Opaque(def_id, _substs)
64-
if matches!(
65-
self.opaque_type_origin(def_id, span),
66-
Some(OpaqueTyOrigin::FnReturn(..))
67-
) =>
68-
{
69-
let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span };
78+
ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
79+
let def_span = self.tcx.def_span(def_id);
80+
let span = if span.contains(def_span) { def_span } else { span };
7081
let cause = ObligationCause::new(span, body_id, code.clone());
7182
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
7283
// for opaque types, and then use that kind to fix the spans for type errors

compiler/rustc_typeck/src/check/check.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1313
use rustc_hir::intravisit::Visitor;
1414
use rustc_hir::lang_items::LangItem;
1515
use rustc_hir::{ItemKind, Node, PathSegment};
16+
use rustc_infer::infer::opaque_types::ReplaceOpaqueTypes;
1617
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1718
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1819
use rustc_infer::traits::Obligation;
@@ -95,9 +96,10 @@ pub(super) fn check_fn<'a, 'tcx>(
9596
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
9697
declared_ret_ty,
9798
body.value.hir_id,
98-
DUMMY_SP,
99+
decl.output.span(),
99100
traits::ObligationCauseCode::OpaqueReturnType(None),
100101
param_env,
102+
ReplaceOpaqueTypes::All,
101103
));
102104
// If we replaced declared_ret_ty with infer vars, then we must be infering
103105
// an opaque type, so set a flag so we can improve diagnostics.

compiler/rustc_typeck/src/check/closure.rs

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::rustc_middle::ty::subst::Subst;
77
use rustc_hir as hir;
88
use rustc_hir::def_id::DefId;
99
use rustc_hir::lang_items::LangItem;
10+
use rustc_infer::infer::opaque_types::ReplaceOpaqueTypes;
1011
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1112
use rustc_infer::infer::LateBoundRegionConversionTime;
1213
use rustc_infer::infer::{InferOk, InferResult};
@@ -645,13 +646,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
645646
result
646647
}
647648

649+
/// Closures can't create hidden types for opaque types of their parent, as they
650+
/// do not have all the outlives information available. Also `type_of` looks for
651+
/// hidden types in the owner (so the closure's parent), so it would not find these
652+
/// definitions.
648653
fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
649654
let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars(
650655
ty,
651656
body_id,
652657
span,
653658
ObligationCauseCode::MiscObligation,
654659
self.param_env,
660+
ReplaceOpaqueTypes::OnlyForRPIT,
655661
);
656662
self.register_predicates(obligations);
657663
value
@@ -671,39 +677,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
671677

672678
let ret_ty = ret_coercion.borrow().expected_ty();
673679
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
674-
let (def_id, substs) = match *ret_ty.kind() {
675-
ty::Opaque(def_id, substs) => (def_id, substs),
680+
681+
let get_future_output = |predicate: ty::Predicate<'tcx>, span| {
682+
// Search for a pending obligation like
683+
//
684+
// `<R as Future>::Output = T`
685+
//
686+
// where R is the return type we are expecting. This type `T`
687+
// will be our output.
688+
let bound_predicate = predicate.kind();
689+
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
690+
self.deduce_future_output_from_projection(
691+
span,
692+
bound_predicate.rebind(proj_predicate),
693+
)
694+
} else {
695+
None
696+
}
697+
};
698+
699+
let output_ty = match *ret_ty.kind() {
700+
ty::Infer(ty::TyVar(ret_vid)) => {
701+
self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
702+
get_future_output(obligation.predicate, obligation.cause.span)
703+
})
704+
}
705+
ty::Opaque(def_id, substs) => self
706+
.tcx
707+
.bound_explicit_item_bounds(def_id)
708+
.transpose_iter()
709+
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
710+
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0)),
676711
ty::Error(_) => return None,
677712
_ => span_bug!(
678713
self.tcx.def_span(expr_def_id),
679714
"async fn generator return type not an inference variable"
680715
),
681716
};
682717

683-
let item_bounds = self.tcx.bound_explicit_item_bounds(def_id);
684-
685-
// Search for a pending obligation like
686-
//
687-
// `<R as Future>::Output = T`
688-
//
689-
// where R is the return type we are expecting. This type `T`
690-
// will be our output.
691-
let output_ty = item_bounds
692-
.transpose_iter()
693-
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
694-
.find_map(|(predicate, span)| {
695-
let bound_predicate = predicate.subst(self.tcx, substs).kind();
696-
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
697-
{
698-
self.deduce_future_output_from_projection(
699-
span.0,
700-
bound_predicate.rebind(proj_predicate),
701-
)
702-
} else {
703-
None
704-
}
705-
});
706-
707718
debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
708719
output_ty
709720
}

src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl Thing for AssocNoCopy {
3030
type Out = Box<dyn Bar<Assoc: Copy>>;
3131

3232
fn func() -> Self::Out {
33-
Box::new(AssocNoCopy)
3433
//~^ ERROR the trait bound `String: Copy` is not satisfied
34+
Box::new(AssocNoCopy)
3535
}
3636
}

src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
error[E0277]: the trait bound `String: Copy` is not satisfied
2-
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:33:9
2+
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18
33
|
4-
LL | Box::new(AssocNoCopy)
5-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
6-
|
7-
= note: required for the cast from `AssocNoCopy` to the object type `dyn Bar<Assoc = <AssocNoCopy as Thing>::Out::{opaque#0}>`
4+
LL | fn func() -> Self::Out {
5+
| ^^^^^^^^^ the trait `Copy` is not implemented for `String`
86

97
error: aborting due to previous error
108

src/test/ui/async-await/issues/issue-65159.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ async fn copy() -> Result<()>
66
//~^ ERROR this enum takes 2 generic arguments
77
{
88
Ok(())
9+
//~^ ERROR type annotations needed
910
}
1011

1112
fn main() { }

src/test/ui/async-await/issues/issue-65159.stderr

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ help: add missing generic argument
1616
LL | async fn copy() -> Result<(), E>
1717
| +++
1818

19-
error: aborting due to previous error
19+
error[E0282]: type annotations needed
20+
--> $DIR/issue-65159.rs:8:5
21+
|
22+
LL | Ok(())
23+
| ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
24+
|
25+
help: consider specifying the generic arguments
26+
|
27+
LL | Ok::<(), E>(())
28+
| +++++++++
29+
30+
error: aborting due to 2 previous errors
2031

21-
For more information about this error, try `rustc --explain E0107`.
32+
Some errors have detailed explanations: E0107, E0282.
33+
For more information about an error, try `rustc --explain E0107`.

src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
1717
//~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
1818
//~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
1919
LockedMarket(generator.lock().unwrap().buy())
20+
//~^ ERROR cannot return value referencing temporary
2021
}
2122

2223
struct LockedMarket<T>(T);

src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
77
| expected 0 lifetime arguments
88
|
99
note: struct defined here, with 0 lifetime parameters
10-
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
10+
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
1111
|
1212
LL | struct LockedMarket<T>(T);
1313
| ^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
1919
| ^^^^^^^^^^^^ expected 1 generic argument
2020
|
2121
note: struct defined here, with 1 generic parameter: `T`
22-
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
22+
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
2323
|
2424
LL | struct LockedMarket<T>(T);
2525
| ^^^^^^^^^^^^ -
@@ -28,6 +28,16 @@ help: add missing generic argument
2828
LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
2929
| +++
3030

31-
error: aborting due to 2 previous errors
31+
error[E0515]: cannot return value referencing temporary value
32+
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5
33+
|
34+
LL | LockedMarket(generator.lock().unwrap().buy())
35+
| ^^^^^^^^^^^^^-------------------------^^^^^^^
36+
| | |
37+
| | temporary value created here
38+
| returns a value referencing data owned by the current function
39+
40+
error: aborting due to 3 previous errors
3241

33-
For more information about this error, try `rustc --explain E0107`.
42+
Some errors have detailed explanations: E0107, E0515.
43+
For more information about an error, try `rustc --explain E0107`.

src/test/ui/chalkify/bugs/async.stderr

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,10 @@ LL | T: Generator<ResumeTy, Yield = ()>,
2929
| ^^^^^^^^^^ required by this bound in `std::future::from_generator`
3030

3131
error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
32-
--> $DIR/async.rs:7:29
32+
--> $DIR/async.rs:7:25
3333
|
34-
LL | async fn foo(x: u32) -> u32 {
35-
| _____________________________^
36-
LL | | x
37-
LL | | }
38-
| |_^
34+
LL | async fn foo(x: u32) -> u32 {
35+
| ^^^
3936

4037
error: aborting due to 3 previous errors
4138

src/test/ui/generic-associated-types/bugs/issue-89008.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0271]: type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
2-
--> $DIR/issue-89008.rs:40:9
2+
--> $DIR/issue-89008.rs:39:43
33
|
44
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
5-
| ---- this type parameter
6-
LL | async {empty()}
7-
| ^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
5+
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
6+
| |
7+
| this type parameter
88
|
99
note: expected this to be `()`
1010
--> $DIR/issue-89008.rs:18:17

src/test/ui/impl-trait/issue-55872-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ impl<S: Default> Bar for S {
1111

1212
fn foo<T: Default>() -> Self::E {
1313
//~^ ERROR impl has stricter requirements than trait
14-
(S::default(), T::default())
15-
//~^ ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
14+
//~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277]
1615
//~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277]
16+
(S::default(), T::default())
1717
}
1818
}
1919

src/test/ui/impl-trait/issue-55872-1.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | fn foo<T: Default>() -> Self::E {
88
| ^^^^^^^ impl has extra requirement `T: Default`
99

1010
error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
11-
--> $DIR/issue-55872-1.rs:14:9
11+
--> $DIR/issue-55872-1.rs:12:29
1212
|
13-
LL | (S::default(), T::default())
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
13+
LL | fn foo<T: Default>() -> Self::E {
14+
| ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
1515
|
1616
= note: required because it appears within the type `(S, T)`
1717
help: consider further restricting this bound
@@ -20,10 +20,10 @@ LL | impl<S: Default + std::marker::Copy> Bar for S {
2020
| +++++++++++++++++++
2121

2222
error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
23-
--> $DIR/issue-55872-1.rs:14:9
23+
--> $DIR/issue-55872-1.rs:12:29
2424
|
25-
LL | (S::default(), T::default())
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
25+
LL | fn foo<T: Default>() -> Self::E {
26+
| ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
2727
|
2828
= note: required because it appears within the type `(S, T)`
2929
help: consider further restricting this bound

src/test/ui/impl-trait/issue-55872-3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ pub trait Bar {
1212
impl<S> Bar for S {
1313
type E = impl std::marker::Copy;
1414
fn foo<T>() -> Self::E {
15+
//~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied [E0277]
1516
async {}
16-
//~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied [E0277]
1717
}
1818
}
1919

src/test/ui/impl-trait/issue-55872-3.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
2-
--> $DIR/issue-55872-3.rs:15:9
2+
--> $DIR/issue-55872-3.rs:14:20
33
|
4-
LL | async {}
5-
| ^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
4+
LL | fn foo<T>() -> Self::E {
5+
| ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
66

77
error: aborting due to previous error
88

src/test/ui/impl-trait/issues/issue-70877.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ impl Iterator for Bar {
1313
type Item = FooItem;
1414

1515
fn next(&mut self) -> Option<Self::Item> {
16-
Some(Box::new(quux)) //~ ERROR mismatched types
16+
Some(Box::new(quux))
1717
}
1818
}
1919

0 commit comments

Comments
 (0)