Skip to content

Commit 3d09b99

Browse files
Wait until type_of to remap HIR opaques back to their defn params
1 parent a810b58 commit 3d09b99

File tree

7 files changed

+92
-55
lines changed

7 files changed

+92
-55
lines changed

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

+66-28
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
5959
}
6060
}
6161

62-
let Some(hidden) = locator.found else {
62+
if let Some(hidden) = locator.found {
63+
// Only check against typeck if we didn't already error
64+
if !hidden.ty.references_error() {
65+
for concrete_type in locator.typeck_types {
66+
if concrete_type.ty != tcx.erase_regions(hidden.ty)
67+
&& !(concrete_type, hidden).references_error()
68+
{
69+
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
70+
}
71+
}
72+
}
73+
74+
hidden.ty
75+
} else {
6376
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
6477
span: tcx.def_span(def_id),
6578
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@@ -70,21 +83,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
7083
_ => "item",
7184
},
7285
});
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-
}
86+
tcx.ty_error(reported)
8587
}
86-
87-
hidden.ty
8888
}
8989

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

141156
// Use borrowck to get the type with unerased regions.
142157
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@@ -190,8 +205,8 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
190205
}
191206
}
192207

193-
pub(super) fn find_opaque_ty_constraints_for_rpit(
194-
tcx: TyCtxt<'_>,
208+
pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
209+
tcx: TyCtxt<'tcx>,
195210
def_id: LocalDefId,
196211
owner_def_id: LocalDefId,
197212
) -> Ty<'_> {
@@ -208,27 +223,50 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
208223
Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
209224
other => bug!("{:?} is not a valid scope for an opaque type item", other),
210225
}
211-
}
212226

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 {
227+
concrete.ty
228+
} else {
229+
let tables = tcx.typeck(owner_def_id);
230+
if let Some(guar) = tables.tainted_by_errors {
216231
// Some error in the
217232
// owner fn prevented us from populating
218233
// the `concrete_opaque_types` table.
219234
tcx.ty_error(guar)
220235
} else {
221-
table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
236+
// Fall back to the RPIT we inferred during HIR typeck
237+
let mut opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
238+
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
239+
if opaque_type_key.def_id != def_id {
240+
continue;
241+
}
242+
let concrete_type =
243+
tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
244+
opaque_type_key,
245+
tcx,
246+
true,
247+
));
248+
if let Some(prev) = &mut opaque_ty {
249+
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
250+
prev.report_mismatch(&concrete_type, def_id, tcx).emit();
251+
}
252+
} else {
253+
opaque_ty = Some(concrete_type);
254+
}
255+
}
256+
257+
if let Some(opaque_ty) = opaque_ty {
258+
opaque_ty.ty
259+
} else {
222260
// We failed to resolve the opaque type or it
223261
// resolves to itself. We interpret this as the
224262
// no values of the hidden type ever being constructed,
225263
// so we can just make the hidden type be `!`.
226264
// For backwards compatibility reasons, we fall back to
227265
// `()` until we the diverging default is changed.
228266
tcx.mk_diverging_default()
229-
})
267+
}
230268
}
231-
})
269+
}
232270
}
233271

234272
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-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pub struct TypeckResults<'tcx> {
159159
/// These types are mapped back to the opaque's identity substitutions
160160
/// (with erased regions), which is why we don't associated substs with any
161161
/// of these usages.
162-
pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
162+
pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
163163

164164
/// Tracks the minimum captures required for a closure;
165165
/// see `MinCaptureInformationMap` for more details.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
4+
// Makes sure we don't prepopulate the MIR typeck of `define`
5+
// with `Foo<T, U> = T`, but instead, `Foo<B, A> = B`, so that
6+
// the param-env predicates actually apply.
7+
8+
#![feature(type_alias_impl_trait)]
9+
10+
type Foo<T: Send, U> = impl NeedsSend<T>;
11+
12+
trait NeedsSend<T> {}
13+
impl<T: Send> NeedsSend<T> for T {}
14+
15+
fn define<A, B: Send>(a: A, b: B) {
16+
let y: Option<Foo<B, A>> = Some(b);
17+
}
18+
19+
fn main() {}

tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ type X<A, B> = impl Into<&'static A>;
88

99
fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
1010
//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
11-
//~| ERROR concrete type differs from previous defining opaque type use
1211
(a, a)
1312
}
1413

tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr

+1-10
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,6 @@ help: consider introducing a `where` clause, but there might be an alternative b
1010
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
1111
| ++++++++++++++++++++++++++
1212

13-
error: concrete type differs from previous defining opaque type use
14-
--> $DIR/multiple-def-uses-in-one-fn.rs:9:45
15-
|
16-
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
17-
| ^^^^^^^^^^^^^^^^^^
18-
| |
19-
| expected `&B`, got `&A`
20-
| this expression supplies two conflicting concrete types for the same opaque type
21-
22-
error: aborting due to 2 previous errors
13+
error: aborting due to previous error
2314

2415
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)