Skip to content

Commit a7dc987

Browse files
compiler-errorsworkingjubilee
authored andcommitted
Add variances to RPITITs
1 parent b7297ac commit a7dc987

21 files changed

+241
-168
lines changed

Diff for: compiler/rustc_hir_analysis/src/variance/mod.rs

+44-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use itertools::Itertools;
77
use rustc_arena::DroplessArena;
8+
use rustc_hir as hir;
89
use rustc_hir::def::DefKind;
910
use rustc_hir::def_id::{DefId, LocalDefId};
1011
use rustc_middle::query::Providers;
@@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
6364
let crate_map = tcx.crate_variances(());
6465
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
6566
}
67+
DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
68+
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
69+
return variance_of_opaque(
70+
tcx,
71+
opaque_def_id.expect_local(),
72+
ForceCaptureTraitArgs::Yes,
73+
);
74+
}
75+
None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
76+
},
6677
DefKind::OpaqueTy => {
67-
return variance_of_opaque(tcx, item_def_id);
78+
let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn {
79+
parent: _,
80+
in_trait_or_impl: Some(hir::RpitContext::Trait),
81+
} =
82+
tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin
83+
{
84+
ForceCaptureTraitArgs::Yes
85+
} else {
86+
ForceCaptureTraitArgs::No
87+
};
88+
89+
return variance_of_opaque(tcx, item_def_id, force_capture_trait_args);
6890
}
6991
_ => {}
7092
}
@@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
7395
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
7496
}
7597

98+
#[derive(Debug, Copy, Clone)]
99+
enum ForceCaptureTraitArgs {
100+
Yes,
101+
No,
102+
}
103+
76104
#[instrument(level = "trace", skip(tcx), ret)]
77-
fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
105+
fn variance_of_opaque(
106+
tcx: TyCtxt<'_>,
107+
item_def_id: LocalDefId,
108+
force_capture_trait_args: ForceCaptureTraitArgs,
109+
) -> &[ty::Variance] {
78110
let generics = tcx.generics_of(item_def_id);
79111

80112
// Opaque types may only use regions that are bound. So for
@@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
115147
#[instrument(level = "trace", skip(self), ret)]
116148
fn visit_ty(&mut self, t: Ty<'tcx>) {
117149
match t.kind() {
118-
ty::Alias(_, ty::AliasTy { def_id, args, .. })
119-
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
120-
{
150+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
121151
self.visit_opaque(*def_id, args);
122152
}
123153
_ => t.super_visit_with(self),
@@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
135165
let mut generics = generics;
136166
while let Some(def_id) = generics.parent {
137167
generics = tcx.generics_of(def_id);
168+
169+
// Don't mark trait params generic if we're in an RPITIT.
170+
if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes)
171+
&& generics.parent.is_none()
172+
{
173+
debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
174+
break;
175+
}
176+
138177
for param in &generics.own_params {
139178
match param.kind {
140179
ty::GenericParamDefKind::Lifetime => {

Diff for: compiler/rustc_metadata/src/rmeta/encoder.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1100,9 +1100,12 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
11001100
| DefKind::Fn
11011101
| DefKind::Ctor(..)
11021102
| DefKind::AssocFn => true,
1103+
DefKind::AssocTy => {
1104+
// Only encode variances for RPITITs (for traits)
1105+
matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. }))
1106+
}
11031107
DefKind::Mod
11041108
| DefKind::Field
1105-
| DefKind::AssocTy
11061109
| DefKind::AssocConst
11071110
| DefKind::TyParam
11081111
| DefKind::ConstParam

Diff for: compiler/rustc_middle/src/ty/context.rs

+4
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
539539
self.trait_def(trait_def_id).implement_via_object
540540
}
541541

542+
fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
543+
self.is_impl_trait_in_trait(def_id)
544+
}
545+
542546
fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed {
543547
self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string())
544548
}

Diff for: compiler/rustc_type_ir/src/interner.rs

+2
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ pub trait Interner:
261261

262262
fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
263263

264+
fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
265+
264266
fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;
265267

266268
fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool;

Diff for: compiler/rustc_type_ir/src/relate.rs

+10
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
254254
b.args,
255255
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
256256
)?,
257+
ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => {
258+
relate_args_with_variances(
259+
relation,
260+
a.def_id,
261+
relation.cx().variances_of(a.def_id),
262+
a.args,
263+
b.args,
264+
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
265+
)?
266+
}
257267
ty::Projection | ty::Weak | ty::Inherent => {
258268
relate_args_invariantly(relation, a.args, b.args)?
259269
}

Diff for: tests/ui/impl-trait/in-trait/variance.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
1-
#![feature(rustc_attrs)]
1+
#![feature(rustc_attrs, precise_capturing_in_traits)]
22
#![allow(internal_features)]
33
#![rustc_variance_of_opaques]
44

5-
trait Captures<'a> {}
6-
impl<T> Captures<'_> for T {}
7-
85
trait Foo<'i> {
96
fn implicit_capture_early<'a: 'a>() -> impl Sized {}
10-
//~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
7+
//~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
8+
9+
fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
10+
//~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
1111

12-
fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {}
13-
//~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
12+
fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
13+
//~^ [Self: o, 'i: o, 'a: *, 'i: o]
1414

1515
fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
16-
//~^ [Self: o, 'i: *, 'a: o, 'i: o]
16+
//~^ [Self: o, 'i: o, 'a: o, 'i: o]
17+
18+
fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
19+
//~^ [Self: o, 'i: o, 'i: o, 'a: o]
1720

18-
fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
19-
//~^ [Self: o, 'i: *, 'a: o, 'i: o]
21+
fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
22+
//~^ [Self: o, 'i: o, 'i: o]
2023
}
2124

2225
fn main() {}

Diff for: tests/ui/impl-trait/in-trait/variance.stderr

+23-11
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
1-
error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
2-
--> $DIR/variance.rs:9:44
1+
error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
2+
--> $DIR/variance.rs:6:44
33
|
44
LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {}
55
| ^^^^^^^^^^
66

7-
error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
8-
--> $DIR/variance.rs:12:44
7+
error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
8+
--> $DIR/variance.rs:9:44
9+
|
10+
LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: [Self: o, 'i: o, 'a: *, 'i: o]
14+
--> $DIR/variance.rs:12:40
915
|
10-
LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {}
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
16+
LL | fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1218

13-
error: [Self: o, 'i: *, 'a: o, 'i: o]
19+
error: [Self: o, 'i: o, 'a: o, 'i: o]
1420
--> $DIR/variance.rs:15:48
1521
|
1622
LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
1723
| ^^^^^^^^^^
1824

19-
error: [Self: o, 'i: *, 'a: o, 'i: o]
25+
error: [Self: o, 'i: o, 'i: o, 'a: o]
2026
--> $DIR/variance.rs:18:48
2127
|
22-
LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
28+
LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: [Self: o, 'i: o, 'i: o]
32+
--> $DIR/variance.rs:21:44
33+
|
34+
LL | fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
2436

25-
error: aborting due to 4 previous errors
37+
error: aborting due to 6 previous errors
2638

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
#![feature(precise_capturing_in_traits)]
2+
13
fn type_param<T>() -> impl Sized + use<> {}
24
//~^ ERROR `impl Trait` must mention all type parameters in scope
35

46
trait Foo {
57
fn bar() -> impl Sized + use<>;
68
//~^ ERROR `impl Trait` must mention the `Self` type of the trait
7-
//~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
89
}
910

1011
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
1-
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
2-
--> $DIR/forgot-to-capture-type.rs:5:30
3-
|
4-
LL | fn bar() -> impl Sized + use<>;
5-
| ^^^^^
6-
|
7-
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
8-
= note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
9-
= help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
10-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
11-
121
error: `impl Trait` must mention all type parameters in scope in `use<...>`
13-
--> $DIR/forgot-to-capture-type.rs:1:23
2+
--> $DIR/forgot-to-capture-type.rs:3:23
143
|
154
LL | fn type_param<T>() -> impl Sized + use<> {}
165
| - ^^^^^^^^^^^^^^^^^^
@@ -20,7 +9,7 @@ LL | fn type_param<T>() -> impl Sized + use<> {}
209
= note: currently, all type parameters are required to be mentioned in the precise captures list
2110

2211
error: `impl Trait` must mention the `Self` type of the trait in `use<...>`
23-
--> $DIR/forgot-to-capture-type.rs:5:17
12+
--> $DIR/forgot-to-capture-type.rs:7:17
2413
|
2514
LL | trait Foo {
2615
| --------- `Self` type parameter is implicitly captured by this `impl Trait`
@@ -29,5 +18,5 @@ LL | fn bar() -> impl Sized + use<>;
2918
|
3019
= note: currently, all type parameters are required to be mentioned in the precise captures list
3120

32-
error: aborting due to 3 previous errors
21+
error: aborting due to 2 previous errors
3322

Diff for: tests/ui/impl-trait/precise-capturing/redundant.normal.stderr

-20
This file was deleted.

Diff for: tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr

-24
This file was deleted.

Diff for: tests/ui/impl-trait/precise-capturing/redundant.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
//@ compile-flags: -Zunstable-options --edition=2024
2-
//@ revisions: normal rpitit
3-
//@[normal] check-pass
2+
//@ check-pass
3+
4+
#![feature(precise_capturing_in_traits)]
45

56
fn hello<'a>() -> impl Sized + use<'a> {}
6-
//[normal]~^ WARN all possible in-scope parameters are already captured
7+
//~^ WARN all possible in-scope parameters are already captured
78

89
struct Inherent;
910
impl Inherent {
1011
fn inherent(&self) -> impl Sized + use<'_> {}
11-
//[normal]~^ WARN all possible in-scope parameters are already captured
12+
//~^ WARN all possible in-scope parameters are already captured
1213
}
1314

14-
#[cfg(rpitit)]
1515
trait Test<'a> {
1616
fn in_trait() -> impl Sized + use<'a, Self>;
17-
//[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
17+
//~^ WARN all possible in-scope parameters are already captured
1818
}
19-
#[cfg(rpitit)]
2019
impl<'a> Test<'a> for () {
2120
fn in_trait() -> impl Sized + use<'a> {}
22-
//[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
21+
//~^ WARN all possible in-scope parameters are already captured
2322
}
2423

2524
fn main() {}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
2+
--> $DIR/redundant.rs:6:19
3+
|
4+
LL | fn hello<'a>() -> impl Sized + use<'a> {}
5+
| ^^^^^^^^^^^^^-------
6+
| |
7+
| help: remove the `use<...>` syntax
8+
|
9+
= note: `#[warn(impl_trait_redundant_captures)]` on by default
10+
11+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
12+
--> $DIR/redundant.rs:11:27
13+
|
14+
LL | fn inherent(&self) -> impl Sized + use<'_> {}
15+
| ^^^^^^^^^^^^^-------
16+
| |
17+
| help: remove the `use<...>` syntax
18+
19+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
20+
--> $DIR/redundant.rs:16:22
21+
|
22+
LL | fn in_trait() -> impl Sized + use<'a, Self>;
23+
| ^^^^^^^^^^^^^-------------
24+
| |
25+
| help: remove the `use<...>` syntax
26+
27+
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
28+
--> $DIR/redundant.rs:20:22
29+
|
30+
LL | fn in_trait() -> impl Sized + use<'a> {}
31+
| ^^^^^^^^^^^^^-------
32+
| |
33+
| help: remove the `use<...>` syntax
34+
35+
warning: 4 warnings emitted
36+

0 commit comments

Comments
 (0)