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.
This commit is contained in:
parent
ed6c958ee4
commit
25876b3541
@ -1,6 +1,7 @@
|
||||
//! The entry point of the NLL borrow checker.
|
||||
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
|
||||
@ -8,7 +9,7 @@ use rustc_middle::mir::{
|
||||
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
||||
Promoted,
|
||||
};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid};
|
||||
use rustc_span::symbol::sym;
|
||||
use std::env;
|
||||
use std::fmt::Debug;
|
||||
@ -43,7 +44,7 @@ pub type PoloniusOutput = Output<RustcFacts>;
|
||||
/// closure requirements to propagate, and any generated errors.
|
||||
crate struct NllOutput<'tcx> {
|
||||
pub regioncx: RegionInferenceContext<'tcx>,
|
||||
pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
pub opaque_type_values: VecMap<DefId, OpaqueHiddenType<'tcx>>,
|
||||
pub polonius_input: Option<Box<AllFacts>>,
|
||||
pub polonius_output: Option<Rc<PoloniusOutput>>,
|
||||
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
|
||||
@ -372,7 +373,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
|
||||
opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
opaque_type_values: &VecMap<DefId, OpaqueHiddenType<'tcx>>,
|
||||
errors: &mut crate::error::BorrowckErrors<'tcx>,
|
||||
) {
|
||||
let tcx = infcx.tcx;
|
||||
|
@ -1,5 +1,6 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
@ -54,8 +55,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
|
||||
) -> VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> {
|
||||
let mut result: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> = VecMap::new();
|
||||
) -> VecMap<DefId, OpaqueHiddenType<'tcx>> {
|
||||
let mut result: VecMap<DefId, OpaqueHiddenType<'tcx>> = VecMap::new();
|
||||
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
|
||||
let substs = opaque_type_key.substs;
|
||||
debug!(?concrete_type, ?substs);
|
||||
@ -124,21 +125,31 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
|
||||
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
|
||||
// once we convert the generic parameters to those of the opaque type.
|
||||
if let Some(prev) = result.get_mut(&opaque_type_key) {
|
||||
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
|
||||
if prev.ty != ty {
|
||||
let mut err = infcx.tcx.sess.struct_span_err(
|
||||
concrete_type.span,
|
||||
&format!("hidden type `{}` differed from previous `{}`", ty, prev.ty),
|
||||
);
|
||||
err.span_note(prev.span, "previous hidden type bound here");
|
||||
err.emit();
|
||||
if !ty.references_error() {
|
||||
let mut err = infcx.tcx.sess.struct_span_err(
|
||||
concrete_type.span,
|
||||
"concrete type differs from previous defining opaque type use",
|
||||
);
|
||||
err.span_label(prev.span, format!("expected `{}`, got `{}`", prev.ty, ty));
|
||||
if prev.span == concrete_type.span {
|
||||
err.span_label(prev.span, "this expression supplies two conflicting concrete types for the same opaque type");
|
||||
} else {
|
||||
err.span_note(prev.span, "previous use here");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
prev.ty = infcx.tcx.ty_error();
|
||||
}
|
||||
// Pick a better span if there is one.
|
||||
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
||||
prev.span = prev.span.substitute_dummy(concrete_type.span);
|
||||
} else {
|
||||
result.insert(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span });
|
||||
result.insert(
|
||||
opaque_type_key.def_id,
|
||||
OpaqueHiddenType { ty, span: concrete_type.span },
|
||||
);
|
||||
}
|
||||
}
|
||||
result
|
||||
|
@ -9,7 +9,6 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_index::bit_set::BitMatrix;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::ty::OpaqueTypeKey;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use smallvec::SmallVec;
|
||||
@ -242,7 +241,7 @@ pub struct BorrowCheckResult<'tcx> {
|
||||
/// All the opaque types that are restricted to concrete types
|
||||
/// by this function. Unlike the value in `TypeckResults`, this has
|
||||
/// unerased regions.
|
||||
pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
pub concrete_opaque_types: VecMap<DefId, OpaqueHiddenType<'tcx>>,
|
||||
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
|
||||
pub used_mut_upvars: SmallVec<[Field; 8]>,
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
|
@ -356,7 +356,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
let concrete_ty = tcx
|
||||
.mir_borrowck(owner)
|
||||
.concrete_opaque_types
|
||||
.get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
|
||||
.get(&def_id.to_def_id())
|
||||
.copied()
|
||||
.map(|concrete| concrete.ty)
|
||||
.unwrap_or_else(|| {
|
||||
@ -591,13 +591,13 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||
// Use borrowck to get the type with unerased regions.
|
||||
let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
|
||||
debug!(?concrete_opaque_types);
|
||||
for &(opaque_type_key, concrete_type) in concrete_opaque_types {
|
||||
if opaque_type_key.def_id != self.def_id {
|
||||
for &(def_id, concrete_type) in concrete_opaque_types {
|
||||
if def_id != self.def_id {
|
||||
// Ignore constraints for other opaque types.
|
||||
continue;
|
||||
}
|
||||
|
||||
debug!(?concrete_type, ?opaque_type_key.substs, "found constraint");
|
||||
debug!(?concrete_type, "found constraint");
|
||||
|
||||
if let Some(prev) = self.found {
|
||||
if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user