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

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

+1-1
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

+17-7
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

+22-14
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

+8-4
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

+5-9
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

+7-6
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

+4-4
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

+2-6
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

+1-1
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

+1
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>

compiler/rustc_middle/src/ty/mod.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -2552,12 +2552,18 @@ impl<'tcx> TyCtxt<'tcx> {
25522552
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
25532553
}
25542554

2555-
pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId {
2556-
while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
2557-
debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
2558-
def_id = self.parent(def_id);
2555+
pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId {
2556+
match self.opt_rpitit_info(def_id) {
2557+
Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
2558+
| Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
2559+
None => {
2560+
while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
2561+
debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
2562+
def_id = self.parent(def_id);
2563+
}
2564+
def_id
2565+
}
25592566
}
2560-
def_id
25612567
}
25622568

25632569
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
@@ -2572,6 +2578,10 @@ impl<'tcx> TyCtxt<'tcx> {
25722578

25732579
let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
25742580

2581+
if self.lower_impl_trait_in_trait_to_assoc_ty() {
2582+
return !self.associated_items_for_impl_trait_in_trait(trait_item_def_id).is_empty();
2583+
}
2584+
25752585
// FIXME(RPITIT): This does a somewhat manual walk through the signature
25762586
// of the trait fn to look for any RPITITs, but that's kinda doing a lot
25772587
// of work. We can probably remove this when we refactor RPITITs to be

compiler/rustc_middle/src/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ pub trait PrettyPrinter<'tcx>:
728728
}
729729
ty::Alias(ty::Projection, ref data) => {
730730
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
731-
&& self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
731+
&& self.tcx().is_impl_trait_in_trait(data.def_id)
732732
{
733733
return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
734734
} else {

compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1288,7 +1288,7 @@ impl<'tcx> AliasTy<'tcx> {
12881288
match tcx.def_kind(self.def_id) {
12891289
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
12901290
DefKind::ImplTraitPlaceholder => {
1291-
tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
1291+
tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
12921292
}
12931293
kind => bug!("expected a projection AliasTy; found {kind:?}"),
12941294
}

compiler/rustc_privacy/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ where
132132
projection.trait_ref_and_own_substs(tcx)
133133
} else {
134134
// HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
135-
let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
135+
let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id);
136136
let trait_generics = tcx.generics_of(def_id);
137137
(
138138
tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),

compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
144144
trait_ref: ty::PolyTraitRef<'tcx>,
145145
obligation: &PredicateObligation<'tcx>,
146146
) -> OnUnimplementedNote {
147-
if self.tcx.opt_rpitit_info(obligation.cause.body_id.to_def_id()).is_some() {
148-
return OnUnimplementedNote::default();
149-
}
150-
151147
let (def_id, substs) = self
152148
.impl_similar_to(trait_ref, obligation)
153149
.unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
154150
let trait_ref = trait_ref.skip_binder();
155151

156-
let body_hir = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
157-
let mut flags =
158-
vec![(sym::ItemContext, self.describe_enclosure(body_hir).map(|s| s.to_owned()))];
152+
let mut flags = vec![];
153+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
154+
// but I guess we could synthesize one here. We don't see any errors that rely on
155+
// that yet, though.
156+
let enclosure =
157+
if let Some(body_hir) = self.tcx.opt_local_def_id_to_hir_id(obligation.cause.body_id) {
158+
self.describe_enclosure(body_hir).map(|s| s.to_owned())
159+
} else {
160+
None
161+
};
162+
flags.push((sym::ItemContext, enclosure));
159163

160164
match obligation.cause.code() {
161165
ObligationCauseCode::BuiltinDerivedObligation(..)

compiler/rustc_trait_selection/src/traits/project.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
12981298
) {
12991299
let tcx = selcx.tcx();
13001300
if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
1301-
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
1301+
let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
13021302

13031303
let trait_def_id = tcx.parent(trait_fn_def_id);
13041304
let trait_substs =
@@ -2200,7 +2200,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
22002200
let tcx = selcx.tcx();
22012201
let mut obligations = data.nested;
22022202

2203-
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
2203+
let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
22042204
let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
22052205
Ok(assoc_ty) => assoc_ty,
22062206
Err(guar) => return Progress::error(tcx, guar),

0 commit comments

Comments
 (0)