Skip to content

Commit 246d989

Browse files
authored
Rollup merge of #109198 - compiler-errors:new-rpitit-default-body, r=spastorino
Install projection from RPITIT to default trait method opaque correctly 1. For new lowering strategy `-Zlower-impl-trait-in-trait-to-assoc-ty`, install the correct default trait method projection predicates (RPITIT -> opaque). This makes default trait body tests pass! 2. Fix two WF-checking bugs -- first, we want to make sure that we're always looking for an opaque type in `check_return_position_impl_trait_in_trait_bounds`. That's because the RPITIT projections are normalized to opaques during wfcheck. Second, fix RPITIT's param-envs by not adding the projection predicates that we install on trait methods to make default RPITITs work -- I left a comment why. 3. Also, just a small drive-by for `rustc_on_unimplemented`. Not sure if it affects any tests, but can't hurt. r? ````@spastorino,```` based off of #109140
2 parents edd6b42 + 8d922eb commit 246d989

File tree

50 files changed

+419
-107
lines changed

Some content is hidden

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

50 files changed

+419
-107
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
557557
check_opaque(tcx, id);
558558
}
559559
DefKind::ImplTraitPlaceholder => {
560-
let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
560+
let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
561561
// Only check the validity of this opaque type if the function has a default body
562562
if let hir::Node::TraitItem(hir::TraitItem {
563563
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::autoderef::Autoderef;
22
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
33

4-
use hir::def::DefKind;
54
use rustc_ast as ast;
65
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
76
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -1548,16 +1547,27 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
15481547
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
15491548
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
15501549
{
1550+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
1551+
// strategy, we can't just call `check_associated_item` on the new RPITITs,
1552+
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
1553+
// That's because we need to check that the bounds of the RPITIT hold using
1554+
// the special substs that we create during opaque type lowering, otherwise we're
1555+
// getting a bunch of early bound and free regions mixed up... Haven't looked too
1556+
// deep into this, though.
15511557
for arg in fn_output.walk() {
15521558
if let ty::GenericArgKind::Type(ty) = arg.unpack()
1553-
&& let ty::Alias(ty::Opaque, proj) = ty.kind()
1554-
&& tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
1555-
&& tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
1559+
// RPITITs are always eagerly normalized into opaques, so always look for an
1560+
// opaque here.
1561+
&& let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
1562+
&& let Some(opaque_def_id) = opaque_ty.def_id.as_local()
1563+
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
1564+
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
1565+
&& source == fn_def_id
15561566
{
1557-
let span = tcx.def_span(proj.def_id);
1558-
let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
1567+
let span = tcx.def_span(opaque_ty.def_id);
1568+
let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
15591569
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
1560-
let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
1570+
let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
15611571
let normalized_bound = wfcx.normalize(span, None, bound);
15621572
traits::wf::predicate_obligations(
15631573
wfcx.infcx,

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
33
use rustc_hir as hir;
44
use rustc_infer::traits::util;
55
use rustc_middle::ty::subst::InternalSubsts;
6-
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
6+
use rustc_middle::ty::{self, Ty, TyCtxt};
77
use rustc_span::def_id::DefId;
88
use rustc_span::Span;
99

@@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
7676
tcx: TyCtxt<'_>,
7777
def_id: DefId,
7878
) -> &'_ [(ty::Predicate<'_>, Span)] {
79-
// If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
80-
// generated the synthesized associate type.
81-
let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
82-
tcx.opt_rpitit_info(def_id)
83-
{
84-
Some(opaque_def_id)
85-
} else {
86-
None
87-
};
79+
match tcx.opt_rpitit_info(def_id) {
80+
// RPITIT's bounds are the same as opaque type bounds, but with
81+
// a projection self type.
82+
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
83+
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
84+
let opaque_ty = item.expect_opaque_ty();
85+
return opaque_type_bounds(
86+
tcx,
87+
opaque_def_id,
88+
opaque_ty.bounds,
89+
tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
90+
item.span,
91+
);
92+
}
93+
// These should have been fed!
94+
Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
95+
None => {}
96+
}
8897

89-
let bounds_def_id = rpitit_info.unwrap_or(def_id);
90-
let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
98+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
9199
match tcx.hir().get(hir_id) {
92100
hir::Node::TraitItem(hir::TraitItem {
93101
kind: hir::TraitItemKind::Type(bounds, _),
@@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
100108
..
101109
}) => {
102110
let substs = InternalSubsts::identity_for_item(tcx, def_id);
103-
let item_ty = if *in_trait || rpitit_info.is_some() {
111+
let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
104112
tcx.mk_projection(def_id, substs)
105113
} else {
106114
tcx.mk_opaque(def_id, substs)
107115
};
108-
opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
116+
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
109117
}
110118
_ => bug!("item_bounds called on {:?}", def_id),
111119
}

compiler/rustc_hir_analysis/src/variance/mod.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
112112
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
113113
match t.kind() {
114114
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
115-
if matches!(
116-
self.tcx.def_kind(*def_id),
117-
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
118-
) =>
115+
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
116+
{
117+
self.visit_opaque(*def_id, substs)
118+
}
119+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
120+
// at all for RPITITs.
121+
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
122+
if self.tcx.is_impl_trait_in_trait(*def_id) =>
119123
{
120124
self.visit_opaque(*def_id, substs)
121125
}

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
44

5-
use hir::def::DefKind;
65
use rustc_errors::ErrorGuaranteed;
76
use rustc_hir as hir;
87
use rustc_hir::lang_items::LangItem;
@@ -715,14 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
715714
.subst_iter_copied(self.tcx, substs)
716715
.find_map(|(p, s)| get_future_output(p, s))?,
717716
ty::Error(_) => return None,
718-
ty::Alias(ty::Projection, proj)
719-
if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
720-
{
721-
self.tcx
722-
.bound_explicit_item_bounds(proj.def_id)
723-
.subst_iter_copied(self.tcx, proj.substs)
724-
.find_map(|(p, s)| get_future_output(p, s))?
725-
}
717+
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
718+
.tcx
719+
.bound_explicit_item_bounds(proj.def_id)
720+
.subst_iter_copied(self.tcx, proj.substs)
721+
.find_map(|(p, s)| get_future_output(p, s))?,
726722
_ => span_bug!(
727723
self.tcx.def_span(expr_def_id),
728724
"async fn generator return type not an inference variable: {ret_ty}"

compiler/rustc_infer/src/infer/error_reporting/mod.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,10 +359,12 @@ impl<'tcx> InferCtxt<'tcx> {
359359
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
360360
let (def_id, substs) = match *ty.kind() {
361361
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
362-
if matches!(
363-
self.tcx.def_kind(def_id),
364-
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
365-
) =>
362+
if matches!(self.tcx.def_kind(def_id), DefKind::OpaqueTy) =>
363+
{
364+
(def_id, substs)
365+
}
366+
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
367+
if self.tcx.is_impl_trait_in_trait(def_id) =>
366368
{
367369
(def_id, substs)
368370
}
@@ -1757,8 +1759,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
17571759
)
17581760
}
17591761
(true, ty::Alias(ty::Projection, proj))
1760-
if self.tcx.def_kind(proj.def_id)
1761-
== DefKind::ImplTraitPlaceholder =>
1762+
if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
17621763
{
17631764
let sm = self.tcx.sess.source_map();
17641765
let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::TypeErrCtxt;
22
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
33
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
4-
use rustc_hir::{self as hir, def::DefKind};
4+
use rustc_hir as hir;
55
use rustc_middle::traits::ObligationCauseCode;
66
use rustc_middle::ty::error::ExpectedFound;
77
use rustc_middle::ty::print::Printer;
@@ -75,7 +75,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
7575
diag.note("an associated type was expected, but a different one was found");
7676
}
7777
(ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
78-
if tcx.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
78+
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
7979
{
8080
let p_def_id = tcx
8181
.generics_of(body_owner_def_id)
@@ -222,7 +222,7 @@ impl<T> Trait<T> for X {
222222
diag.span_label(p_span, "this type parameter");
223223
}
224224
}
225-
(ty::Alias(ty::Projection, proj_ty), _) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
225+
(ty::Alias(ty::Projection, proj_ty), _) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
226226
self.expected_projection(
227227
diag,
228228
proj_ty,
@@ -231,7 +231,7 @@ impl<T> Trait<T> for X {
231231
cause.code(),
232232
);
233233
}
234-
(_, ty::Alias(ty::Projection, proj_ty)) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
234+
(_, ty::Alias(ty::Projection, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
235235
let msg = format!(
236236
"consider constraining the associated type `{}` to `{}`",
237237
values.found, values.expected,

compiler/rustc_infer/src/infer/opaque_types.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use super::{DefineOpaqueTypes, InferResult};
33
use crate::errors::OpaqueHiddenTypeDiag;
44
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
55
use crate::traits;
6-
use hir::def::DefKind;
76
use hir::def_id::{DefId, LocalDefId};
87
use hir::OpaqueTyOrigin;
98
use rustc_data_structures::sync::Lrc;
@@ -478,9 +477,7 @@ where
478477
}
479478
}
480479

481-
ty::Alias(ty::Projection, proj)
482-
if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
483-
{
480+
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => {
484481
// Skip lifetime parameters that are not captures.
485482
let variances = self.tcx.variances_of(proj.def_id);
486483

@@ -559,8 +556,7 @@ impl<'tcx> InferCtxt<'tcx> {
559556
// FIXME(RPITIT): Don't replace RPITITs with inference vars.
560557
ty::Alias(ty::Projection, projection_ty)
561558
if !projection_ty.has_escaping_bound_vars()
562-
&& tcx.def_kind(projection_ty.def_id)
563-
!= DefKind::ImplTraitPlaceholder =>
559+
&& !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
564560
{
565561
self.infer_projection(
566562
param_env,

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
10281028
| DefKind::InlineConst => true,
10291029

10301030
DefKind::ImplTraitPlaceholder => {
1031-
let parent_def_id = tcx.impl_trait_in_trait_parent(def_id.to_def_id());
1031+
let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
10321032
let assoc_item = tcx.associated_item(parent_def_id);
10331033
match assoc_item.container {
10341034
// Always encode an RPIT in an impl fn, since it always has a body

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ rustc_queries! {
191191
{
192192
desc { "determine whether the opaque is a type-alias impl trait" }
193193
separate_provide_extern
194+
feedable
194195
}
195196

196197
query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>

0 commit comments

Comments
 (0)