Skip to content

Commit

Permalink
Provide a better diagnostic on failure to meet send bound on futures …
Browse files Browse the repository at this point in the history
…in a foreign crate

Adding diagnostic data on generators to the crate metadata and using it to provide
a better diagnostic on failure to meet send bound on futures originated from a foreign crate
  • Loading branch information
oribenshir committed Apr 16, 2022
1 parent 07bb916 commit ebe3c56
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 53 deletions.
19 changes: 19 additions & 0 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::thir;
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
use rustc_serialize::{opaque, Decodable, Decoder};
use rustc_session::cstore::{
Expand Down Expand Up @@ -1732,6 +1733,24 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.collect()
})
}

fn get_generator_diagnostic_data(
self,
tcx: TyCtxt<'tcx>,
id: DefIndex,
) -> Option<GeneratorDiagnosticData<'tcx>> {
self.root
.tables
.generator_diagnostic_data
.get(self, id)
.map(|param| param.decode((self, tcx)))
.map(|generator_data| GeneratorDiagnosticData {
generator_interior_types: generator_data.generator_interior_types,
hir_owner: generator_data.hir_owner,
nodes_types: generator_data.nodes_types,
adjustments: generator_data.adjustments,
})
}
}

impl CrateMetadata {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,

crate_extern_paths => { cdata.source().paths().cloned().collect() }
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) }
}

pub(in crate::rmeta) fn provide(providers: &mut Providers) {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1550,16 +1550,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_info_for_closure(&mut self, hir_id: hir::HirId) {
let def_id = self.tcx.hir().local_def_id(hir_id);
debug!("EncodeContext::encode_info_for_closure({:?})", def_id);

// NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
// including on the signature, which is inferred in `typeck.
let ty = self.tcx.typeck(def_id).node_type(hir_id);

let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
let ty = typeck_result.node_type(hir_id);
match ty.kind() {
ty::Generator(..) => {
let data = self.tcx.generator_kind(def_id).unwrap();
let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data();
record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Generator);
record!(self.tables.generator_kind[def_id.to_def_id()] <- data);
record!(self.tables.generator_diagnostic_data[def_id.to_def_id()] <- generator_diagnostic_data);
}

ty::Closure(..) => {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_middle::mir;
use rustc_middle::thir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion;
Expand Down Expand Up @@ -358,6 +359,7 @@ define_tables! {
def_keys: Table<DefIndex, Lazy<DefKey>>,
def_path_hashes: Table<DefIndex, DefPathHash>,
proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>,
}

#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1962,4 +1962,10 @@ rustc_queries! {
eval_always
desc { "computing the backend features for CLI flags" }
}

query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> {
storage(ArenaCacheSelector<'tcx>)
desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
}
32 changes: 32 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,16 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
pub expr: Option<hir::HirId>,
}

// This type holds diagnostic information on generators and async functions across crate boundaries
// and is used to provide better error messages
#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
pub struct GeneratorDiagnosticData<'tcx> {
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
pub hir_owner: DefId,
pub nodes_types: ItemLocalMap<Ty<'tcx>>,
pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
}

#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
pub struct TypeckResults<'tcx> {
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
Expand Down Expand Up @@ -623,6 +633,28 @@ impl<'tcx> TypeckResults<'tcx> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
}

pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
vec.iter()
.map(|item| {
GeneratorInteriorTypeCause {
ty: item.ty,
span: item.span,
scope_span: item.scope_span,
yield_span: item.yield_span,
expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
}
})
.collect::<Vec<_>>()
});
GeneratorDiagnosticData {
generator_interior_types: generator_interior_type,
hir_owner: self.hir_owner.to_def_id(),
nodes_types: self.node_types.clone(),
adjustments: self.adjustments.clone(),
}
}

pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
self.node_type_opt(id).unwrap_or_else(|| {
bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ pub use self::consts::{
};
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
UserTypeAnnotationIndex,
};
pub use self::instance::{Instance, InstanceDef};
pub use self::list::List;
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_middle/src/ty/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ use crate::traits::{self, ImplSource};
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::GeneratorDiagnosticData;
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
Expand All @@ -49,13 +52,10 @@ use rustc_session::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
use rustc_session::utils::NativeLibKind;
use rustc_session::Limits;
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;

use rustc_ast as ast;
use rustc_attr as attr;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
Expand Down
Loading

0 comments on commit ebe3c56

Please sign in to comment.