Skip to content

Commit ccf99bd

Browse files
authored
Rollup merge of #111980 - compiler-errors:unmapped-substs, r=lcnr
Preserve substs in opaques recorded in typeck results This means that we now prepopulate MIR with opaques with the right substs. The first commit is a hack that I think we discussed, having to do with `DefiningAnchor::Bubble` basically being equivalent to `DefiningAnchor::Error` in the new solver, so having to use `DefiningAnchor::Bind` instead, lol. r? `@lcnr`
2 parents 453fc03 + df1c1af commit ccf99bd

File tree

14 files changed

+127
-187
lines changed

14 files changed

+127
-187
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,18 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
279279
// HACK This bubble is required for this tests to pass:
280280
// nested-return-type2-tait2.rs
281281
// nested-return-type2-tait3.rs
282-
let infcx =
283-
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
282+
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
283+
// and prepopulate this `InferCtxt` with known opaque values, rather than
284+
// using the `Bind` anchor here. For now it's fine.
285+
let infcx = self
286+
.tcx
287+
.infer_ctxt()
288+
.with_opaque_type_inference(if self.tcx.trait_solver_next() {
289+
DefiningAnchor::Bind(def_id)
290+
} else {
291+
DefiningAnchor::Bubble
292+
})
293+
.build();
284294
let ocx = ObligationCtxt::new(&infcx);
285295
// Require the hidden type to be well-formed with only the generics of the opaque type.
286296
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the

compiler/rustc_borrowck/src/type_check/mod.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
188188

189189
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
190190
// predefined opaques in the typeck root.
191-
// FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
192-
// the HIR typeck map defining usages back to their definition params,
193-
// they won't actually match up with the usages in this body...
194191
if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
195192
checker.register_predefined_opaques_in_new_solver();
196193
}
@@ -1042,10 +1039,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10421039
.typeck(self.body.source.def_id().expect_local())
10431040
.concrete_opaque_types
10441041
.iter()
1045-
.map(|(&def_id, &hidden_ty)| {
1046-
let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
1047-
(ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
1048-
})
1042+
.map(|(k, v)| (*k, *v))
10491043
.collect();
10501044

10511045
let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {

compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs

+78-33
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_errors::StashKey;
12
use rustc_hir::def_id::LocalDefId;
23
use rustc_hir::intravisit::{self, Visitor};
34
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
@@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
5960
}
6061
}
6162

62-
let Some(hidden) = locator.found else {
63+
if let Some(hidden) = locator.found {
64+
// Only check against typeck if we didn't already error
65+
if !hidden.ty.references_error() {
66+
for concrete_type in locator.typeck_types {
67+
if concrete_type.ty != tcx.erase_regions(hidden.ty)
68+
&& !(concrete_type, hidden).references_error()
69+
{
70+
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
71+
}
72+
}
73+
}
74+
75+
hidden.ty
76+
} else {
6377
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
6478
span: tcx.def_span(def_id),
6579
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
7084
_ => "item",
7185
},
7286
});
73-
return tcx.ty_error(reported);
74-
};
75-
76-
// Only check against typeck if we didn't already error
77-
if !hidden.ty.references_error() {
78-
for concrete_type in locator.typeck_types {
79-
if concrete_type.ty != tcx.erase_regions(hidden.ty)
80-
&& !(concrete_type, hidden).references_error()
81-
{
82-
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
83-
}
84-
}
87+
tcx.ty_error(reported)
8588
}
86-
87-
hidden.ty
8889
}
8990

9091
struct TaitConstraintLocator<'tcx> {
@@ -130,13 +131,28 @@ impl TaitConstraintLocator<'_> {
130131
self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
131132
return;
132133
}
133-
let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
134+
135+
let mut constrained = false;
136+
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
137+
if opaque_type_key.def_id != self.def_id {
138+
continue;
139+
}
140+
constrained = true;
141+
let concrete_type =
142+
self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
143+
opaque_type_key,
144+
self.tcx,
145+
true,
146+
));
147+
if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
148+
self.typeck_types.push(concrete_type);
149+
}
150+
}
151+
152+
if !constrained {
134153
debug!("no constraints in typeck results");
135154
return;
136155
};
137-
if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
138-
self.typeck_types.push(typeck_hidden_ty);
139-
}
140156

141157
// Use borrowck to get the type with unerased regions.
142158
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@@ -190,45 +206,74 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
190206
}
191207
}
192208

193-
pub(super) fn find_opaque_ty_constraints_for_rpit(
194-
tcx: TyCtxt<'_>,
209+
pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
210+
tcx: TyCtxt<'tcx>,
195211
def_id: LocalDefId,
196212
owner_def_id: LocalDefId,
197213
) -> Ty<'_> {
198-
let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
214+
let tables = tcx.typeck(owner_def_id);
215+
216+
// Check that all of the opaques we inferred during HIR are compatible.
217+
// FIXME: We explicitly don't check that the types inferred during HIR
218+
// typeck are compatible with the one that we infer during borrowck,
219+
// because that one actually sometimes has consts evaluated eagerly so
220+
// using strict type equality will fail.
221+
let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
222+
if tables.tainted_by_errors.is_none() {
223+
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
224+
if opaque_type_key.def_id != def_id {
225+
continue;
226+
}
227+
let concrete_type = tcx.erase_regions(
228+
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
229+
);
230+
if let Some(prev) = &mut hir_opaque_ty {
231+
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
232+
prev.report_mismatch(&concrete_type, def_id, tcx).stash(
233+
tcx.def_span(opaque_type_key.def_id),
234+
StashKey::OpaqueHiddenTypeMismatch,
235+
);
236+
}
237+
} else {
238+
hir_opaque_ty = Some(concrete_type);
239+
}
240+
}
241+
}
199242

200-
if let Some(concrete) = concrete {
243+
let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
244+
if let Some(mir_opaque_ty) = mir_opaque_ty {
201245
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
202246
debug!(?scope);
203-
let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
247+
let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
204248

205249
match tcx.hir().get(scope) {
206250
Node::Item(it) => intravisit::walk_item(&mut locator, it),
207251
Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
208252
Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
209253
other => bug!("{:?} is not a valid scope for an opaque type item", other),
210254
}
211-
}
212255

213-
concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
214-
let table = tcx.typeck(owner_def_id);
215-
if let Some(guar) = table.tainted_by_errors {
216-
// Some error in the
217-
// owner fn prevented us from populating
256+
mir_opaque_ty.ty
257+
} else {
258+
if let Some(guar) = tables.tainted_by_errors {
259+
// Some error in the owner fn prevented us from populating
218260
// the `concrete_opaque_types` table.
219261
tcx.ty_error(guar)
220262
} else {
221-
table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
263+
// Fall back to the RPIT we inferred during HIR typeck
264+
if let Some(hir_opaque_ty) = hir_opaque_ty {
265+
hir_opaque_ty.ty
266+
} else {
222267
// We failed to resolve the opaque type or it
223268
// resolves to itself. We interpret this as the
224269
// no values of the hidden type ever being constructed,
225270
// so we can just make the hidden type be `!`.
226271
// For backwards compatibility reasons, we fall back to
227272
// `()` until we the diverging default is changed.
228273
tcx.mk_diverging_default()
229-
})
274+
}
230275
}
231-
})
276+
}
232277
}
233278

234279
struct RpitConstraintChecker<'tcx> {

compiler/rustc_hir_typeck/src/writeback.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -583,19 +583,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
583583
continue;
584584
}
585585

586-
let hidden_type =
587-
self.tcx().erase_regions(hidden_type.remap_generic_params_to_declaration_params(
588-
opaque_type_key,
589-
self.tcx(),
590-
true,
591-
));
592-
586+
// Here we only detect impl trait definition conflicts when they
587+
// are equal modulo regions.
593588
if let Some(last_opaque_ty) = self
594589
.typeck_results
595590
.concrete_opaque_types
596-
.insert(opaque_type_key.def_id, hidden_type)
591+
.insert(opaque_type_key, hidden_type)
597592
&& last_opaque_ty.ty != hidden_type.ty
598593
{
594+
assert!(!self.tcx().trait_solver_next());
599595
hidden_type
600596
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
601597
.stash(

compiler/rustc_middle/src/ty/typeck_results.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,7 @@ pub struct TypeckResults<'tcx> {
155155
/// We also store the type here, so that the compiler can use it as a hint
156156
/// for figuring out hidden types, even if they are only set in dead code
157157
/// (which doesn't show up in MIR).
158-
///
159-
/// These types are mapped back to the opaque's identity substitutions
160-
/// (with erased regions), which is why we don't associated substs with any
161-
/// of these usages.
162-
pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
158+
pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
163159

164160
/// Tracks the minimum captures required for a closure;
165161
/// see `MinCaptureInformationMap` for more details.

tests/ui/chalkify/bugs/async.stderr

+3-10
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,9 @@ error: internal compiler error: projection clauses should be implied from elsewh
1313
LL | async fn foo(x: u32) -> u32 {
1414
| ^^^query stack during panic:
1515
#0 [typeck] type-checking `foo`
16-
#1 [thir_body] building THIR for `foo`
17-
#2 [check_match] match-checking `foo`
18-
#3 [mir_built] building MIR for `foo`
19-
#4 [unsafety_check_result] unsafety-checking `foo`
20-
#5 [mir_const] preparing `foo` for borrow checking
21-
#6 [mir_promoted] promoting constants in MIR for `foo`
22-
#7 [mir_borrowck] borrow-checking `foo`
23-
#8 [type_of] computing type of `foo::{opaque#0}`
24-
#9 [check_mod_item_types] checking item types in top-level module
25-
#10 [analysis] running analysis passes on this crate
16+
#1 [type_of] computing type of `foo::{opaque#0}`
17+
#2 [check_mod_item_types] checking item types in top-level module
18+
#3 [analysis] running analysis passes on this crate
2619
end of query stack
2720
error: aborting due to 2 previous errors
2821

tests/ui/dyn-star/param-env-infer.next.stderr

-35
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,6 @@ error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}`
1313
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515
|
16-
note: ...which requires borrow-checking `make_dyn_star`...
17-
--> $DIR/param-env-infer.rs:11:1
18-
|
19-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21-
note: ...which requires promoting constants in MIR for `make_dyn_star`...
22-
--> $DIR/param-env-infer.rs:11:1
23-
|
24-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26-
note: ...which requires preparing `make_dyn_star` for borrow checking...
27-
--> $DIR/param-env-infer.rs:11:1
28-
|
29-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
30-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31-
note: ...which requires unsafety-checking `make_dyn_star`...
32-
--> $DIR/param-env-infer.rs:11:1
33-
|
34-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
35-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36-
note: ...which requires building MIR for `make_dyn_star`...
37-
--> $DIR/param-env-infer.rs:11:1
38-
|
39-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
40-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41-
note: ...which requires match-checking `make_dyn_star`...
42-
--> $DIR/param-env-infer.rs:11:1
43-
|
44-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
45-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46-
note: ...which requires building THIR for `make_dyn_star`...
47-
--> $DIR/param-env-infer.rs:11:1
48-
|
49-
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
50-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5116
note: ...which requires type-checking `make_dyn_star`...
5217
--> $DIR/param-env-infer.rs:11:1
5318
|

tests/ui/impl-trait/auto-trait-leak.stderr

-70
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,6 @@ error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
44
LL | fn cycle1() -> impl Clone {
55
| ^^^^^^^^^^
66
|
7-
note: ...which requires borrow-checking `cycle1`...
8-
--> $DIR/auto-trait-leak.rs:12:1
9-
|
10-
LL | fn cycle1() -> impl Clone {
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12-
note: ...which requires promoting constants in MIR for `cycle1`...
13-
--> $DIR/auto-trait-leak.rs:12:1
14-
|
15-
LL | fn cycle1() -> impl Clone {
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
17-
note: ...which requires preparing `cycle1` for borrow checking...
18-
--> $DIR/auto-trait-leak.rs:12:1
19-
|
20-
LL | fn cycle1() -> impl Clone {
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
22-
note: ...which requires unsafety-checking `cycle1`...
23-
--> $DIR/auto-trait-leak.rs:12:1
24-
|
25-
LL | fn cycle1() -> impl Clone {
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
27-
note: ...which requires building MIR for `cycle1`...
28-
--> $DIR/auto-trait-leak.rs:12:1
29-
|
30-
LL | fn cycle1() -> impl Clone {
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
32-
note: ...which requires match-checking `cycle1`...
33-
--> $DIR/auto-trait-leak.rs:12:1
34-
|
35-
LL | fn cycle1() -> impl Clone {
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
37-
note: ...which requires building THIR for `cycle1`...
38-
--> $DIR/auto-trait-leak.rs:12:1
39-
|
40-
LL | fn cycle1() -> impl Clone {
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
427
note: ...which requires type-checking `cycle1`...
438
--> $DIR/auto-trait-leak.rs:14:5
449
|
@@ -50,41 +15,6 @@ note: ...which requires computing type of `cycle2::{opaque#0}`...
5015
|
5116
LL | fn cycle2() -> impl Clone {
5217
| ^^^^^^^^^^
53-
note: ...which requires borrow-checking `cycle2`...
54-
--> $DIR/auto-trait-leak.rs:19:1
55-
|
56-
LL | fn cycle2() -> impl Clone {
57-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
58-
note: ...which requires promoting constants in MIR for `cycle2`...
59-
--> $DIR/auto-trait-leak.rs:19:1
60-
|
61-
LL | fn cycle2() -> impl Clone {
62-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
63-
note: ...which requires preparing `cycle2` for borrow checking...
64-
--> $DIR/auto-trait-leak.rs:19:1
65-
|
66-
LL | fn cycle2() -> impl Clone {
67-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
68-
note: ...which requires unsafety-checking `cycle2`...
69-
--> $DIR/auto-trait-leak.rs:19:1
70-
|
71-
LL | fn cycle2() -> impl Clone {
72-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
73-
note: ...which requires building MIR for `cycle2`...
74-
--> $DIR/auto-trait-leak.rs:19:1
75-
|
76-
LL | fn cycle2() -> impl Clone {
77-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
78-
note: ...which requires match-checking `cycle2`...
79-
--> $DIR/auto-trait-leak.rs:19:1
80-
|
81-
LL | fn cycle2() -> impl Clone {
82-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
83-
note: ...which requires building THIR for `cycle2`...
84-
--> $DIR/auto-trait-leak.rs:19:1
85-
|
86-
LL | fn cycle2() -> impl Clone {
87-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
8818
note: ...which requires type-checking `cycle2`...
8919
--> $DIR/auto-trait-leak.rs:20:5
9020
|

0 commit comments

Comments
 (0)