Skip to content

Commit e745b4d

Browse files
committed
Auto merge of #95767 - oli-obk:all_your_generics_belong_to_the_definitions, r=compiler-errors
Report opaque type mismatches directly during borrowck of the function instead of within the `type_of` query. This allows us to only store a single hidden type per opaque type instead of having to store one per set of substitutions. r? `@compiler-errors` This does not affect diagnostics, because the diagnostic messages are exactly the same.
2 parents dd38eea + 7d2cad6 commit e745b4d

File tree

5 files changed

+44
-34
lines changed

5 files changed

+44
-34
lines changed

compiler/rustc_borrowck/src/nll.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
//! The entry point of the NLL borrow checker.
22
33
use rustc_data_structures::vec_map::VecMap;
4+
use rustc_hir::def_id::DefId;
45
use rustc_index::vec::IndexVec;
56
use rustc_infer::infer::InferCtxt;
67
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
78
use rustc_middle::mir::{
89
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
910
Promoted,
1011
};
11-
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid};
12+
use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid};
1213
use rustc_span::symbol::sym;
1314
use std::env;
1415
use std::fmt::Debug;
@@ -43,7 +44,7 @@ pub type PoloniusOutput = Output<RustcFacts>;
4344
/// closure requirements to propagate, and any generated errors.
4445
crate struct NllOutput<'tcx> {
4546
pub regioncx: RegionInferenceContext<'tcx>,
46-
pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
47+
pub opaque_type_values: VecMap<DefId, OpaqueHiddenType<'tcx>>,
4748
pub polonius_input: Option<Box<AllFacts>>,
4849
pub polonius_output: Option<Rc<PoloniusOutput>>,
4950
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
@@ -372,7 +373,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
372373
body: &Body<'tcx>,
373374
regioncx: &RegionInferenceContext<'tcx>,
374375
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
375-
opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
376+
opaque_type_values: &VecMap<DefId, OpaqueHiddenType<'tcx>>,
376377
errors: &mut crate::error::BorrowckErrors<'tcx>,
377378
) {
378379
let tcx = infcx.tcx;

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_data_structures::vec_map::VecMap;
3+
use rustc_hir::def_id::DefId;
34
use rustc_hir::OpaqueTyOrigin;
45
use rustc_infer::infer::InferCtxt;
56
use rustc_middle::ty::subst::GenericArgKind;
@@ -54,8 +55,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5455
&self,
5556
infcx: &InferCtxt<'_, 'tcx>,
5657
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
57-
) -> VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> {
58-
let mut result: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> = VecMap::new();
58+
) -> VecMap<DefId, OpaqueHiddenType<'tcx>> {
59+
let mut result: VecMap<DefId, OpaqueHiddenType<'tcx>> = VecMap::new();
5960
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
6061
let substs = opaque_type_key.substs;
6162
debug!(?concrete_type, ?substs);
@@ -124,21 +125,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
124125
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
125126
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
126127
// once we convert the generic parameters to those of the opaque type.
127-
if let Some(prev) = result.get_mut(&opaque_type_key) {
128+
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
128129
if prev.ty != ty {
129-
let mut err = infcx.tcx.sess.struct_span_err(
130-
concrete_type.span,
131-
&format!("hidden type `{}` differed from previous `{}`", ty, prev.ty),
132-
);
133-
err.span_note(prev.span, "previous hidden type bound here");
134-
err.emit();
130+
if !ty.references_error() {
131+
prev.report_mismatch(
132+
&OpaqueHiddenType { ty, span: concrete_type.span },
133+
infcx.tcx,
134+
);
135+
}
135136
prev.ty = infcx.tcx.ty_error();
136137
}
137138
// Pick a better span if there is one.
138139
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
139140
prev.span = prev.span.substitute_dummy(concrete_type.span);
140141
} else {
141-
result.insert(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span });
142+
result.insert(
143+
opaque_type_key.def_id,
144+
OpaqueHiddenType { ty, span: concrete_type.span },
145+
);
142146
}
143147
}
144148
result

compiler/rustc_middle/src/mir/query.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_hir as hir;
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_index::bit_set::BitMatrix;
1111
use rustc_index::vec::IndexVec;
12-
use rustc_middle::ty::OpaqueTypeKey;
1312
use rustc_span::Span;
1413
use rustc_target::abi::VariantIdx;
1514
use smallvec::SmallVec;
@@ -242,7 +241,7 @@ pub struct BorrowCheckResult<'tcx> {
242241
/// All the opaque types that are restricted to concrete types
243242
/// by this function. Unlike the value in `TypeckResults`, this has
244243
/// unerased regions.
245-
pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
244+
pub concrete_opaque_types: VecMap<DefId, OpaqueHiddenType<'tcx>>,
246245
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
247246
pub used_mut_upvars: SmallVec<[Field; 8]>,
248247
pub tainted_by_errors: Option<ErrorGuaranteed>,

compiler/rustc_middle/src/ty/mod.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,26 @@ pub struct OpaqueHiddenType<'tcx> {
11121112
pub ty: Ty<'tcx>,
11131113
}
11141114

1115+
impl<'tcx> OpaqueHiddenType<'tcx> {
1116+
pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) {
1117+
// Found different concrete types for the opaque type.
1118+
let mut err = tcx.sess.struct_span_err(
1119+
other.span,
1120+
"concrete type differs from previous defining opaque type use",
1121+
);
1122+
err.span_label(other.span, format!("expected `{}`, got `{}`", self.ty, other.ty));
1123+
if self.span == other.span {
1124+
err.span_label(
1125+
self.span,
1126+
"this expression supplies two conflicting concrete types for the same opaque type",
1127+
);
1128+
} else {
1129+
err.span_note(self.span, "previous use here");
1130+
}
1131+
err.emit();
1132+
}
1133+
}
1134+
11151135
rustc_index::newtype_index! {
11161136
/// "Universes" are used during type- and trait-checking in the
11171137
/// presence of `for<..>` binders to control what sets of names are

compiler/rustc_typeck/src/collect/type_of.rs

+5-19
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
356356
let concrete_ty = tcx
357357
.mir_borrowck(owner)
358358
.concrete_opaque_types
359-
.get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
359+
.get(&def_id.to_def_id())
360360
.copied()
361361
.map(|concrete| concrete.ty)
362362
.unwrap_or_else(|| {
@@ -591,31 +591,17 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
591591
// Use borrowck to get the type with unerased regions.
592592
let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
593593
debug!(?concrete_opaque_types);
594-
for &(opaque_type_key, concrete_type) in concrete_opaque_types {
595-
if opaque_type_key.def_id != self.def_id {
594+
for &(def_id, concrete_type) in concrete_opaque_types {
595+
if def_id != self.def_id {
596596
// Ignore constraints for other opaque types.
597597
continue;
598598
}
599599

600-
debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
600+
debug!(?concrete_type, "found constraint");
601601

602602
if let Some(prev) = self.found {
603603
if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() {
604-
// Found different concrete types for the opaque type.
605-
let mut err = self.tcx.sess.struct_span_err(
606-
concrete_type.span,
607-
"concrete type differs from previous defining opaque type use",
608-
);
609-
err.span_label(
610-
concrete_type.span,
611-
format!("expected `{}`, got `{}`", prev.ty, concrete_type.ty),
612-
);
613-
if prev.span == concrete_type.span {
614-
err.span_label(prev.span, "this expression supplies two conflicting concrete types for the same opaque type");
615-
} else {
616-
err.span_note(prev.span, "previous use here");
617-
}
618-
err.emit();
604+
prev.report_mismatch(&concrete_type, self.tcx);
619605
}
620606
} else {
621607
self.found = Some(concrete_type);

0 commit comments

Comments
 (0)