Skip to content

Commit 90a9718

Browse files
authored
Rollup merge of rust-lang#122027 - compiler-errors:rpitit-cycle, r=spastorino
Uplift some feeding out of `associated_type_for_impl_trait_in_impl` and into queries This PR moves the `type_of` and `generics_of` query feeding out of `associated_type_for_impl_trait_in_impl`, since eagerly feeding results in query cycles due to a subtle interaction with `resolve_bound_vars`. Fixes rust-lang#122019 r? spastorino
2 parents e5503b6 + ebc45c8 commit 90a9718

File tree

5 files changed

+85
-60
lines changed

5 files changed

+85
-60
lines changed

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+37
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,43 @@ use rustc_span::Span;
1414
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
1515
use rustc_hir::*;
1616

17+
// For an RPITIT, synthesize generics which are equal to the opaque's generics
18+
// and parent fn's generics compressed into one list.
19+
if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
20+
tcx.opt_rpitit_info(def_id.to_def_id())
21+
{
22+
let trait_def_id = tcx.parent(fn_def_id);
23+
let opaque_ty_generics = tcx.generics_of(opaque_def_id);
24+
let opaque_ty_parent_count = opaque_ty_generics.parent_count;
25+
let mut params = opaque_ty_generics.params.clone();
26+
27+
let parent_generics = tcx.generics_of(trait_def_id);
28+
let parent_count = parent_generics.parent_count + parent_generics.params.len();
29+
30+
let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
31+
32+
for param in &mut params {
33+
param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
34+
- opaque_ty_parent_count as u32;
35+
}
36+
37+
trait_fn_params.extend(params);
38+
params = trait_fn_params;
39+
40+
let param_def_id_to_index =
41+
params.iter().map(|param| (param.def_id, param.index)).collect();
42+
43+
return ty::Generics {
44+
parent: Some(trait_def_id),
45+
parent_count,
46+
params,
47+
param_def_id_to_index,
48+
has_self: opaque_ty_generics.has_self,
49+
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
50+
host_effect_index: parent_generics.host_effect_index,
51+
};
52+
}
53+
1754
let hir_id = tcx.local_def_id_to_hir_id(def_id);
1855

1956
let node = tcx.hir_node(hir_id);

compiler/rustc_hir_analysis/src/collect/type_of.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hir::HirId;
55
use rustc_middle::query::plumbing::CyclePlaceholder;
66
use rustc_middle::ty::print::with_forced_trimmed_paths;
77
use rustc_middle::ty::util::IntTypeExt;
8-
use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
8+
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
99
use rustc_span::symbol::Ident;
1010
use rustc_span::{Span, DUMMY_SP};
1111

@@ -350,22 +350,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
350350
// If we are computing `type_of` the synthesized associated type for an RPITIT in the impl
351351
// side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
352352
// associated type in the impl.
353-
if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) =
354-
tcx.opt_rpitit_info(def_id.to_def_id())
355-
{
356-
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
357-
Ok(map) => {
358-
let assoc_item = tcx.associated_item(def_id);
359-
return map[&assoc_item.trait_item_def_id.unwrap()];
360-
}
361-
Err(_) => {
362-
return ty::EarlyBinder::bind(Ty::new_error_with_message(
363-
tcx,
364-
DUMMY_SP,
365-
"Could not collect return position impl trait in trait tys",
366-
));
353+
match tcx.opt_rpitit_info(def_id.to_def_id()) {
354+
Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => {
355+
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
356+
Ok(map) => {
357+
let assoc_item = tcx.associated_item(def_id);
358+
return map[&assoc_item.trait_item_def_id.unwrap()];
359+
}
360+
Err(_) => {
361+
return ty::EarlyBinder::bind(Ty::new_error_with_message(
362+
tcx,
363+
DUMMY_SP,
364+
"Could not collect return position impl trait in trait tys",
365+
));
366+
}
367367
}
368368
}
369+
// For an RPITIT in a trait, just return the corresponding opaque.
370+
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
371+
return ty::EarlyBinder::bind(Ty::new_opaque(
372+
tcx,
373+
opaque_def_id,
374+
ty::GenericArgs::identity_for_item(tcx, opaque_def_id),
375+
));
376+
}
377+
None => {}
369378
}
370379

371380
let hir_id = tcx.local_def_id_to_hir_id(def_id);

compiler/rustc_middle/src/query/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -826,15 +826,15 @@ rustc_queries! {
826826
/// creates and returns the associated items that correspond to each impl trait in return position
827827
/// of the implemented trait.
828828
query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] {
829-
desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
829+
desc { |tcx| "creating associated items for opaque types returned by `{}`", tcx.def_path_str(fn_def_id) }
830830
cache_on_disk_if { fn_def_id.is_local() }
831831
separate_provide_extern
832832
}
833833

834834
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
835835
/// associated item.
836836
query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
837-
desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
837+
desc { |tcx| "creating the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
838838
cache_on_disk_if { true }
839839
}
840840

compiler/rustc_ty_utils/src/assoc.rs

+4-43
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_hir::def::DefKind;
44
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
55
use rustc_hir::intravisit::{self, Visitor};
66
use rustc_middle::query::Providers;
7-
use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
7+
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
88
use rustc_span::symbol::kw;
99

1010
pub(crate) fn provide(providers: &mut Providers) {
@@ -284,48 +284,8 @@ fn associated_type_for_impl_trait_in_trait(
284284
// Copy defaultness of the containing function.
285285
trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
286286

287-
// Copy type_of of the opaque.
288-
trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque(
289-
tcx,
290-
opaque_ty_def_id.to_def_id(),
291-
GenericArgs::identity_for_item(tcx, opaque_ty_def_id),
292-
)));
293-
294287
trait_assoc_ty.is_type_alias_impl_trait(false);
295288

296-
// Copy generics_of of the opaque type item but the trait is the parent.
297-
trait_assoc_ty.generics_of({
298-
let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
299-
let opaque_ty_parent_count = opaque_ty_generics.parent_count;
300-
let mut params = opaque_ty_generics.params.clone();
301-
302-
let parent_generics = tcx.generics_of(trait_def_id);
303-
let parent_count = parent_generics.parent_count + parent_generics.params.len();
304-
305-
let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
306-
307-
for param in &mut params {
308-
param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
309-
- opaque_ty_parent_count as u32;
310-
}
311-
312-
trait_fn_params.extend(params);
313-
params = trait_fn_params;
314-
315-
let param_def_id_to_index =
316-
params.iter().map(|param| (param.def_id, param.index)).collect();
317-
318-
ty::Generics {
319-
parent: Some(trait_def_id.to_def_id()),
320-
parent_count,
321-
params,
322-
param_def_id_to_index,
323-
has_self: opaque_ty_generics.has_self,
324-
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
325-
host_effect_index: parent_generics.host_effect_index,
326-
}
327-
});
328-
329289
// There are no inferred outlives for the synthesized associated type.
330290
trait_assoc_ty.inferred_outlives_of(&[]);
331291

@@ -382,8 +342,9 @@ fn associated_type_for_impl_trait_in_impl(
382342
impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id));
383343

384344
// Copy generics_of the trait's associated item but the impl as the parent.
385-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl
386-
// generics.
345+
// FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars
346+
// here to paramswhose parent are items in the trait. We could synthesize new params
347+
// here, but it seems overkill.
387348
impl_assoc_ty.generics_of({
388349
let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
389350
let trait_assoc_parent_count = trait_assoc_generics.parent_count;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ check-pass
2+
3+
// Check that we don't hit a query cycle when:
4+
// 1. Computing generics_of, which requires...
5+
// 2. Calling resolve_bound_vars, which requires...
6+
// 3. Calling associated_items, which requires...
7+
// 4. Calling associated_type_for_impl_trait_in_trait, which requires...
8+
// 5. Computing generics_of, which cycles.
9+
10+
pub trait Foo<'a> {
11+
type Assoc;
12+
13+
fn demo<T>(other: T) -> impl Foo<'a, Assoc = Self::Assoc>
14+
where
15+
T: Foo<'a, Assoc = ()>;
16+
}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)