Enable drop_tracking_mir by default.
This commit is contained in:
parent
a626caaad9
commit
286502c9ed
29 changed files with 114 additions and 2513 deletions
|
@ -30,10 +30,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTi
|
|||
use rustc_middle::hir::map;
|
||||
use rustc_middle::ty::error::TypeError::{self, Sorts};
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
|
||||
GeneratorDiagnosticData, GeneratorInteriorTypeCause, GenericArgs, InferTy, IsSuggestable,
|
||||
ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt, TypeckResults,
|
||||
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
|
||||
InferTy, IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt, TypeckResults,
|
||||
};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
|
@ -58,15 +57,12 @@ pub enum GeneratorInteriorOrUpvar {
|
|||
// This type provides a uniform interface to retrieve data on generators, whether it originated from
|
||||
// the local crate being compiled or from a foreign crate.
|
||||
#[derive(Debug)]
|
||||
pub enum GeneratorData<'tcx, 'a> {
|
||||
Local(&'a TypeckResults<'tcx>),
|
||||
Foreign(&'tcx GeneratorDiagnosticData<'tcx>),
|
||||
}
|
||||
struct GeneratorData<'tcx, 'a>(&'a TypeckResults<'tcx>);
|
||||
|
||||
impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
|
||||
// Try to get information about variables captured by the generator that matches a type we are
|
||||
// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
|
||||
// meet an obligation
|
||||
/// Try to get information about variables captured by the generator that matches a type we are
|
||||
/// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
|
||||
/// meet an obligation
|
||||
fn try_get_upvar_span<F>(
|
||||
&self,
|
||||
infer_context: &InferCtxt<'tcx>,
|
||||
|
@ -76,27 +72,21 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
|
|||
where
|
||||
F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
|
||||
{
|
||||
match self {
|
||||
GeneratorData::Local(typeck_results) => {
|
||||
infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
|
||||
upvars.iter().find_map(|(upvar_id, upvar)| {
|
||||
let upvar_ty = typeck_results.node_type(*upvar_id);
|
||||
let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
|
||||
ty_matches(ty::Binder::dummy(upvar_ty))
|
||||
.then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
|
||||
})
|
||||
})
|
||||
}
|
||||
GeneratorData::Foreign(_) => None,
|
||||
}
|
||||
infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
|
||||
upvars.iter().find_map(|(upvar_id, upvar)| {
|
||||
let upvar_ty = self.0.node_type(*upvar_id);
|
||||
let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
|
||||
ty_matches(ty::Binder::dummy(upvar_ty))
|
||||
.then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Try to get the span of a type being awaited on that matches the type we are looking with the
|
||||
// `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
|
||||
// obligation
|
||||
/// Try to get the span of a type being awaited on that matches the type we are looking with the
|
||||
/// `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
|
||||
/// obligation
|
||||
fn get_from_await_ty<F>(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
visitor: AwaitsVisitor,
|
||||
hir: map::Map<'tcx>,
|
||||
ty_matches: F,
|
||||
|
@ -104,69 +94,12 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
|
|||
where
|
||||
F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
|
||||
{
|
||||
match self {
|
||||
GeneratorData::Local(typeck_results) => visitor
|
||||
.awaits
|
||||
.into_iter()
|
||||
.map(|id| hir.expect_expr(id))
|
||||
.find(|await_expr| {
|
||||
ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
|
||||
})
|
||||
.map(|expr| expr.span),
|
||||
GeneratorData::Foreign(generator_diagnostic_data) => visitor
|
||||
.awaits
|
||||
.into_iter()
|
||||
.map(|id| hir.expect_expr(id))
|
||||
.find(|await_expr| {
|
||||
ty_matches(ty::Binder::dummy(
|
||||
generator_diagnostic_data
|
||||
.adjustments
|
||||
.get(&await_expr.hir_id.local_id)
|
||||
.map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..])
|
||||
.last()
|
||||
.map_or_else::<Ty<'tcx>, _, _>(
|
||||
|| {
|
||||
generator_diagnostic_data
|
||||
.nodes_types
|
||||
.get(&await_expr.hir_id.local_id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
bug!(
|
||||
"node_type: no type for node {}",
|
||||
tcx.hir().node_to_string(await_expr.hir_id)
|
||||
)
|
||||
})
|
||||
},
|
||||
|adj| adj.target,
|
||||
),
|
||||
))
|
||||
})
|
||||
.map(|expr| expr.span),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the type, expression, span and optional scope span of all types
|
||||
/// that are live across the yield of this generator
|
||||
fn get_generator_interior_types(
|
||||
&self,
|
||||
) -> ty::Binder<'tcx, &[GeneratorInteriorTypeCause<'tcx>]> {
|
||||
match self {
|
||||
GeneratorData::Local(typeck_result) => {
|
||||
typeck_result.generator_interior_types.as_deref()
|
||||
}
|
||||
GeneratorData::Foreign(generator_diagnostic_data) => {
|
||||
generator_diagnostic_data.generator_interior_types.as_deref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used to get the source of the data, note we don't have as much information for generators
|
||||
// originated from foreign crates
|
||||
fn is_foreign(&self) -> bool {
|
||||
match self {
|
||||
GeneratorData::Local(_) => false,
|
||||
GeneratorData::Foreign(_) => true,
|
||||
}
|
||||
visitor
|
||||
.awaits
|
||||
.into_iter()
|
||||
.map(|id| hir.expect_expr(id))
|
||||
.find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(&await_expr))))
|
||||
.map(|expr| expr.span)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +249,7 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||
outer_generator: Option<DefId>,
|
||||
trait_pred: ty::TraitPredicate<'tcx>,
|
||||
target_ty: Ty<'tcx>,
|
||||
typeck_results: Option<&ty::TypeckResults<'tcx>>,
|
||||
typeck_results: &ty::TypeckResults<'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
next_code: Option<&ObligationCauseCode<'tcx>>,
|
||||
);
|
||||
|
@ -2351,12 +2284,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// cycles. If we can't use resolved types because the generator comes from another crate,
|
||||
// we still provide a targeted error but without all the relevant spans.
|
||||
let generator_data = match &self.typeck_results {
|
||||
Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData::Local(&t),
|
||||
Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData(&t),
|
||||
_ if generator_did.is_local() => {
|
||||
GeneratorData::Local(self.tcx.typeck(generator_did.expect_local()))
|
||||
}
|
||||
_ if let Some(generator_diag_data) = self.tcx.generator_diagnostic_data(generator_did) => {
|
||||
GeneratorData::Foreign(generator_diag_data)
|
||||
GeneratorData(self.tcx.typeck(generator_did.expect_local()))
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
|
@ -2368,30 +2298,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
let mut interior_or_upvar_span = None;
|
||||
|
||||
let from_awaited_ty = generator_data.get_from_await_ty(self.tcx, visitor, hir, ty_matches);
|
||||
let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
|
||||
debug!(?from_awaited_ty);
|
||||
|
||||
// The generator interior types share the same binders
|
||||
if let Some(cause) =
|
||||
generator_data.get_generator_interior_types().skip_binder().iter().find(
|
||||
|ty::GeneratorInteriorTypeCause { ty, .. }| {
|
||||
ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
|
||||
},
|
||||
)
|
||||
{
|
||||
let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
|
||||
|
||||
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
|
||||
*span,
|
||||
Some((*scope_span, *yield_span, *expr, from_awaited_ty)),
|
||||
));
|
||||
|
||||
if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
|
||||
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span, None));
|
||||
}
|
||||
} else if self.tcx.sess.opts.unstable_opts.drop_tracking_mir
|
||||
// Avoid disclosing internal information to downstream crates.
|
||||
&& generator_did.is_local()
|
||||
// Avoid disclosing internal information to downstream crates.
|
||||
if generator_did.is_local()
|
||||
// Try to avoid cycles.
|
||||
&& !generator_within_in_progress_typeck
|
||||
&& let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
|
||||
|
@ -2420,17 +2331,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
|
||||
}
|
||||
|
||||
if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
|
||||
if interior_or_upvar_span.is_none() && !generator_did.is_local() {
|
||||
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span, None));
|
||||
}
|
||||
|
||||
debug!(?interior_or_upvar_span);
|
||||
if let Some(interior_or_upvar_span) = interior_or_upvar_span {
|
||||
let is_async = self.tcx.generator_is_async(generator_did);
|
||||
let typeck_results = match generator_data {
|
||||
GeneratorData::Local(typeck_results) => Some(typeck_results),
|
||||
GeneratorData::Foreign(_) => None,
|
||||
};
|
||||
let typeck_results = generator_data.0;
|
||||
self.note_obligation_cause_for_async_await(
|
||||
err,
|
||||
interior_or_upvar_span,
|
||||
|
@ -2459,7 +2367,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
outer_generator: Option<DefId>,
|
||||
trait_pred: ty::TraitPredicate<'tcx>,
|
||||
target_ty: Ty<'tcx>,
|
||||
typeck_results: Option<&ty::TypeckResults<'tcx>>,
|
||||
typeck_results: &ty::TypeckResults<'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
next_code: Option<&ObligationCauseCode<'tcx>>,
|
||||
) {
|
||||
|
@ -2584,11 +2492,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
} else {
|
||||
// Look at the last interior type to get a span for the `.await`.
|
||||
debug!(
|
||||
generator_interior_types = ?format_args!(
|
||||
"{:#?}", typeck_results.as_ref().map(|t| &t.generator_interior_types)
|
||||
),
|
||||
);
|
||||
explain_yield(interior_span, yield_span, scope_span);
|
||||
}
|
||||
|
||||
|
@ -2608,14 +2511,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
// ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
|
||||
// ```
|
||||
//
|
||||
let is_region_borrow = if let Some(typeck_results) = typeck_results {
|
||||
typeck_results
|
||||
.expr_adjustments(expr)
|
||||
.iter()
|
||||
.any(|adj| adj.is_region_borrow())
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let is_region_borrow = typeck_results
|
||||
.expr_adjustments(expr)
|
||||
.iter()
|
||||
.any(|adj| adj.is_region_borrow());
|
||||
|
||||
// ```rust
|
||||
// struct Foo(*const u8);
|
||||
|
@ -2628,16 +2527,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
|
||||
_ => false,
|
||||
};
|
||||
if let Some(typeck_results) = typeck_results {
|
||||
if (typeck_results.is_method_call(e) && is_region_borrow)
|
||||
|| is_raw_borrow_inside_fn_like_call
|
||||
{
|
||||
err.span_help(
|
||||
parent_span,
|
||||
"consider moving this into a `let` \
|
||||
if (typeck_results.is_method_call(e) && is_region_borrow)
|
||||
|| is_raw_borrow_inside_fn_like_call
|
||||
{
|
||||
err.span_help(
|
||||
parent_span,
|
||||
"consider moving this into a `let` \
|
||||
binding to create a shorter lived borrow",
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue