convert AdtDef::destructor to on-demand
This removes the Cell from AdtDef. Also, moving destructor validity checking to on-demand (forced during item-type checking) ensures that invalid destructors can't cause ICEs. Fixes #38868. Fixes #40132.
This commit is contained in:
parent
e1cb9ba221
commit
e294fd5ecb
11 changed files with 133 additions and 129 deletions
|
|
@ -17,6 +17,7 @@ use middle::region;
|
|||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
|
||||
use rustc::traits::{self, ObligationCause, Reveal};
|
||||
use util::common::ErrorReported;
|
||||
use util::nodemap::FxHashSet;
|
||||
|
||||
use syntax::ast;
|
||||
|
|
@ -40,7 +41,8 @@ use syntax_pos::Span;
|
|||
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
|
||||
///
|
||||
pub fn check_drop_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
drop_impl_did: DefId) -> Result<(), ()> {
|
||||
drop_impl_did: DefId)
|
||||
-> Result<(), ErrorReported> {
|
||||
let dtor_self_type = tcx.item_type(drop_impl_did);
|
||||
let dtor_predicates = tcx.item_predicates(drop_impl_did);
|
||||
match dtor_self_type.sty {
|
||||
|
|
@ -72,7 +74,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
|||
drop_impl_did: DefId,
|
||||
drop_impl_ty: Ty<'tcx>,
|
||||
self_type_did: DefId)
|
||||
-> Result<(), ()>
|
||||
-> Result<(), ErrorReported>
|
||||
{
|
||||
let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap();
|
||||
let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap();
|
||||
|
|
@ -106,14 +108,14 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
|||
"Use same sequence of generic type and region \
|
||||
parameters that is on the struct/enum definition")
|
||||
.emit();
|
||||
return Err(());
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
|
||||
// this could be reached when we get lazy normalization
|
||||
infcx.report_fulfillment_errors(errors);
|
||||
return Err(());
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
let free_regions = FreeRegionMap::new();
|
||||
|
|
@ -130,8 +132,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
|
|||
dtor_predicates: &ty::GenericPredicates<'tcx>,
|
||||
self_type_did: DefId,
|
||||
self_to_impl_substs: &Substs<'tcx>)
|
||||
-> Result<(), ()>
|
||||
-> Result<(), ErrorReported>
|
||||
{
|
||||
let mut result = Ok(());
|
||||
|
||||
// Here is an example, analogous to that from
|
||||
// `compare_impl_method`.
|
||||
|
|
@ -207,13 +210,11 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
|
|||
"The same requirement must be part of \
|
||||
the struct/enum definition")
|
||||
.emit();
|
||||
result = Err(ErrorReported);
|
||||
}
|
||||
}
|
||||
|
||||
if tcx.sess.has_errors() {
|
||||
return Err(());
|
||||
}
|
||||
Ok(())
|
||||
result
|
||||
}
|
||||
|
||||
/// check_safety_of_destructor_if_necessary confirms that the type
|
||||
|
|
@ -556,7 +557,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
// attributes attached to the impl's generics.
|
||||
let dtor_method = adt_def.destructor(tcx)
|
||||
.expect("dtorck type without destructor impossible");
|
||||
let method = tcx.associated_item(dtor_method);
|
||||
let method = tcx.associated_item(dtor_method.did);
|
||||
let impl_def_id = method.container.id();
|
||||
let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs);
|
||||
return DropckKind::RevisedSelf(revised_ty);
|
||||
|
|
|
|||
|
|
@ -609,31 +609,12 @@ pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult
|
|||
})
|
||||
}
|
||||
|
||||
pub fn check_drop_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
|
||||
tcx.sess.track_errors(|| {
|
||||
let _task = tcx.dep_graph.in_task(DepNode::Dropck);
|
||||
let drop_trait = match tcx.lang_items.drop_trait() {
|
||||
Some(id) => tcx.lookup_trait_def(id), None => { return }
|
||||
};
|
||||
drop_trait.for_each_impl(tcx, |drop_impl_did| {
|
||||
let _task = tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did));
|
||||
if drop_impl_did.is_local() {
|
||||
match dropck::check_drop_impl(tcx, drop_impl_did) {
|
||||
Ok(()) => {}
|
||||
Err(()) => {
|
||||
assert!(tcx.sess.has_errors());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
typeck_tables,
|
||||
closure_type,
|
||||
closure_kind,
|
||||
adt_destructor,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
@ -652,6 +633,12 @@ fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
tcx.item_tables(def_id).closure_kinds[&node_id]
|
||||
}
|
||||
|
||||
fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> Option<ty::Destructor> {
|
||||
tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
fn typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> &'tcx ty::TypeckTables<'tcx> {
|
||||
|
|
@ -901,9 +888,11 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
id: ast::NodeId,
|
||||
span: Span) {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
let def = tcx.lookup_adt_def(def_id);
|
||||
def.destructor(tcx); // force the destructor to be evaluated
|
||||
check_representable(tcx, span, def_id);
|
||||
|
||||
if tcx.lookup_adt_def(def_id).repr.simd {
|
||||
if def.repr.simd {
|
||||
check_simd(tcx, span, def_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -911,7 +900,10 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
id: ast::NodeId,
|
||||
span: Span) {
|
||||
check_representable(tcx, span, tcx.hir.local_def_id(id));
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
let def = tcx.lookup_adt_def(def_id);
|
||||
def.destructor(tcx); // force the destructor to be evaluated
|
||||
check_representable(tcx, span, def_id);
|
||||
}
|
||||
|
||||
pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) {
|
||||
|
|
@ -926,10 +918,10 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
|
|||
tcx.item_tables(tcx.hir.local_def_id(it.id));
|
||||
}
|
||||
hir::ItemEnum(ref enum_definition, _) => {
|
||||
check_enum_variants(tcx,
|
||||
it.span,
|
||||
&enum_definition.variants,
|
||||
it.id);
|
||||
check_enum(tcx,
|
||||
it.span,
|
||||
&enum_definition.variants,
|
||||
it.id);
|
||||
}
|
||||
hir::ItemFn(..) => {} // entirely within check_item_body
|
||||
hir::ItemImpl(.., ref impl_item_refs) => {
|
||||
|
|
@ -1322,12 +1314,13 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
|
|||
}
|
||||
|
||||
#[allow(trivial_numeric_casts)]
|
||||
pub fn check_enum_variants<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
sp: Span,
|
||||
vs: &'tcx [hir::Variant],
|
||||
id: ast::NodeId) {
|
||||
pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
sp: Span,
|
||||
vs: &'tcx [hir::Variant],
|
||||
id: ast::NodeId) {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
let def = tcx.lookup_adt_def(def_id);
|
||||
def.destructor(tcx); // force the destructor to be evaluated
|
||||
|
||||
if vs.is_empty() && tcx.has_attr(def_id, "repr") {
|
||||
struct_span_err!(
|
||||
|
|
|
|||
|
|
@ -322,8 +322,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
|||
|
||||
time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
|
||||
|
||||
time(time_passes, "drop-impl checking", || check::check_drop_impls(tcx))?;
|
||||
|
||||
check_unused::check_crate(tcx);
|
||||
check_for_entry_fn(tcx);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue