From 7309babf1773cde3ee6d9e5ef2b177b44278a809 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 4 Dec 2016 00:58:13 +0200 Subject: [PATCH] coherence: code cleanup --- src/librustc_typeck/coherence/builtin.rs | 601 +++++++++++------------ src/librustc_typeck/coherence/mod.rs | 46 +- 2 files changed, 314 insertions(+), 333 deletions(-) diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 6fde18dbf82..8a12eba7d5d 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -22,336 +22,329 @@ use rustc::ty::subst::Subst; use rustc::ty::util::CopyImplementationError; use rustc::infer; +use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use rustc::hir::{self, ItemImpl}; pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - populate_destructors(tcx); - check_implementations_of_copy(tcx); - check_implementations_of_coerce_unsized(tcx); -} + if let Some(drop_trait) = tcx.lang_items.drop_trait() { + tcx.lookup_trait_def(drop_trait).for_each_impl(tcx, |impl_did| { + visit_implementation_of_drop(tcx, impl_did) + }); + } -fn populate_destructors<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let drop_trait = match tcx.lang_items.drop_trait() { - Some(id) => id, - None => return, - }; - tcx.populate_implementations_for_trait_if_necessary(drop_trait); - let drop_trait = tcx.lookup_trait_def(drop_trait); + if let Some(copy_trait) = tcx.lang_items.copy_trait() { + tcx.lookup_trait_def(copy_trait).for_each_impl(tcx, |impl_did| { + visit_implementation_of_copy(tcx, impl_did) + }); + } - drop_trait.for_each_impl(tcx, |impl_did| { - let items = tcx.associated_item_def_ids(impl_did); - if items.is_empty() { - // We'll error out later. For now, just don't ICE. - return; - } - let method_def_id = items[0]; - - let self_type = tcx.item_type(impl_did); - match self_type.sty { - ty::TyAdt(type_def, _) => { - type_def.set_destructor(method_def_id); + if let Some(coerce_unsized_trait) = tcx.lang_items.coerce_unsized_trait() { + let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) { + Ok(id) => id, + Err(err) => { + tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); } - _ => { - // Destructors only work on nominal types. - if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) { - match tcx.map.find(impl_node_id) { - Some(hir_map::NodeItem(item)) => { - let span = match item.node { - ItemImpl(.., ref ty, _) => ty.span, - _ => item.span, - }; - struct_span_err!(tcx.sess, - span, - E0120, - "the Drop trait may only be implemented on \ - structures") - .span_label(span, - &format!("implementing Drop requires a struct")) - .emit(); - } - _ => { - bug!("didn't find impl in ast map"); - } - } - } else { - bug!("found external impl of Drop trait on \ - something other than a struct"); - } - } - } - }); -} - -fn check_implementations_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let copy_trait = match tcx.lang_items.copy_trait() { - Some(id) => id, - None => return, - }; - tcx.populate_implementations_for_trait_if_necessary(copy_trait); - let copy_trait = tcx.lookup_trait_def(copy_trait); - - copy_trait.for_each_impl(tcx, |impl_did| { - debug!("check_implementations_of_copy: impl_did={:?}", impl_did); - - let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) { - n - } else { - debug!("check_implementations_of_copy(): impl not in this \ - crate"); - return; }; - let self_type = tcx.item_type(impl_did); - debug!("check_implementations_of_copy: self_type={:?} (bound)", - self_type); - - let span = tcx.map.span(impl_node_id); - let param_env = ParameterEnvironment::for_item(tcx, impl_node_id); - let self_type = self_type.subst(tcx, ¶m_env.free_substs); - assert!(!self_type.has_escaping_regions()); - - debug!("check_implementations_of_copy: self_type={:?} (free)", - self_type); - - match param_env.can_type_implement_copy(tcx, self_type, span) { - Ok(()) => {} - Err(CopyImplementationError::InfrigingField(name)) => { - struct_span_err!(tcx.sess, - span, - E0204, - "the trait `Copy` may not be implemented for this type") - .span_label(span, &format!("field `{}` does not implement `Copy`", name)) - .emit() - } - Err(CopyImplementationError::InfrigingVariant(name)) => { - let item = tcx.map.expect_item(impl_node_id); - let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node { - tr.path.span - } else { - span - }; - - struct_span_err!(tcx.sess, - span, - E0205, - "the trait `Copy` may not be implemented for this type") - .span_label(span, - &format!("variant `{}` does not implement `Copy`", name)) - .emit() - } - Err(CopyImplementationError::NotAnAdt) => { - let item = tcx.map.expect_item(impl_node_id); - let span = if let ItemImpl(.., ref ty, _) = item.node { - ty.span - } else { - span - }; - - struct_span_err!(tcx.sess, - span, - E0206, - "the trait `Copy` may not be implemented for this type") - .span_label(span, &format!("type is not a structure or enumeration")) - .emit(); - } - Err(CopyImplementationError::HasDestructor) => { - struct_span_err!(tcx.sess, - span, - E0184, - "the trait `Copy` may not be implemented for this type; the \ - type has a destructor") - .span_label(span, &format!("Copy not allowed on types with destructors")) - .emit(); - } - } - }); + tcx.lookup_trait_def(coerce_unsized_trait).for_each_impl(tcx, |impl_did| { + visit_implementation_of_coerce_unsized(tcx, impl_did, + unsize_trait, coerce_unsized_trait) + }); + } } -fn check_implementations_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let coerce_unsized_trait = match tcx.lang_items.coerce_unsized_trait() { - Some(id) => id, - None => return, - }; - let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) { - Ok(id) => id, - Err(err) => { - tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); +fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { + let items = tcx.associated_item_def_ids(impl_did); + if items.is_empty() { + // We'll error out later. For now, just don't ICE. + return; + } + let method_def_id = items[0]; + + let self_type = tcx.item_type(impl_did); + match self_type.sty { + ty::TyAdt(type_def, _) => { + type_def.set_destructor(method_def_id); } - }; - - let trait_def = tcx.lookup_trait_def(coerce_unsized_trait); - - trait_def.for_each_impl(tcx, |impl_did| { - debug!("check_implementations_of_coerce_unsized: impl_did={:?}", - impl_did); - - let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) { - n - } else { - debug!("check_implementations_of_coerce_unsized(): impl not \ - in this crate"); - return; - }; - - let source = tcx.item_type(impl_did); - let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); - let target = trait_ref.substs.type_at(1); - debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", - source, - target); - - let span = tcx.map.span(impl_node_id); - let param_env = ParameterEnvironment::for_item(tcx, impl_node_id); - let source = source.subst(tcx, ¶m_env.free_substs); - let target = target.subst(tcx, ¶m_env.free_substs); - assert!(!source.has_escaping_regions()); - - debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)", - source, - target); - - tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| { - let cause = ObligationCause::misc(span, impl_node_id); - let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, - mt_b: ty::TypeAndMut<'tcx>, - mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| { - if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { - infcx.report_mismatched_types(&cause, - mk_ptr(mt_b.ty), - target, - ty::error::TypeError::Mutability) - .emit(); - } - (mt_a.ty, mt_b.ty, unsize_trait, None) - }; - let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) { - (&ty::TyBox(a), &ty::TyBox(b)) => (a, b, unsize_trait, None), - - (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => { - infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); - check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty)) - } - - (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) | - (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => { - check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)) - } - - (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) - if def_a.is_struct() && def_b.is_struct() => { - if def_a != def_b { - let source_path = tcx.item_path_str(def_a.did); - let target_path = tcx.item_path_str(def_b.did); - span_err!(tcx.sess, - span, - E0377, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with the same \ - definition; expected {}, found {}", - source_path, - target_path); - return; - } - - let fields = &def_a.struct_variant().fields; - let diff_fields = fields.iter() - .enumerate() - .filter_map(|(i, f)| { - let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); - - if tcx.item_type(f.did).is_phantom_data() { - // Ignore PhantomData fields - return None; - } - - // Ignore fields that aren't significantly changed - if let Ok(ok) = infcx.sub_types(false, &cause, b, a) { - if ok.obligations.is_empty() { - return None; - } - } - - // Collect up all fields that were significantly changed - // i.e. those that contain T in coerce_unsized T -> U - Some((i, a, b)) - }) - .collect::>(); - - if diff_fields.is_empty() { - span_err!(tcx.sess, - span, - E0374, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with one field \ - being coerced, none found"); - return; - } else if diff_fields.len() > 1 { - let item = tcx.map.expect_item(impl_node_id); - let span = if let ItemImpl(.., Some(ref t), _, _) = item.node { - t.path.span - } else { - tcx.map.span(impl_node_id) + _ => { + // Destructors only work on nominal types. + if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) { + match tcx.map.find(impl_node_id) { + Some(hir_map::NodeItem(item)) => { + let span = match item.node { + ItemImpl(.., ref ty, _) => ty.span, + _ => item.span, }; - - let mut err = struct_span_err!(tcx.sess, - span, - E0375, - "implementing the trait \ - `CoerceUnsized` requires multiple \ - coercions"); - err.note("`CoerceUnsized` may only be implemented for \ - a coercion between structures with one field being coerced"); - err.note(&format!("currently, {} fields need coercions: {}", - diff_fields.len(), - diff_fields.iter() - .map(|&(i, a, b)| { - format!("{} ({} to {})", fields[i].name, a, b) - }) - .collect::>() - .join(", "))); - err.span_label(span, &format!("requires multiple coercions")); - err.emit(); - return; + struct_span_err!(tcx.sess, + span, + E0120, + "the Drop trait may only be implemented on \ + structures") + .span_label(span, + &format!("implementing Drop requires a struct")) + .emit(); + } + _ => { + bug!("didn't find impl in ast map"); } - - let (i, a, b) = diff_fields[0]; - let kind = ty::adjustment::CustomCoerceUnsized::Struct(i); - (a, b, coerce_unsized_trait, Some(kind)) } + } else { + bug!("found external impl of Drop trait on \ + something other than a struct"); + } + } + } +} - _ => { +fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) { + debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); + + let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) { + n + } else { + debug!("visit_implementation_of_copy(): impl not in this \ + crate"); + return; + }; + + let self_type = tcx.item_type(impl_did); + debug!("visit_implementation_of_copy: self_type={:?} (bound)", + self_type); + + let span = tcx.map.span(impl_node_id); + let param_env = ParameterEnvironment::for_item(tcx, impl_node_id); + let self_type = self_type.subst(tcx, ¶m_env.free_substs); + assert!(!self_type.has_escaping_regions()); + + debug!("visit_implementation_of_copy: self_type={:?} (free)", + self_type); + + match param_env.can_type_implement_copy(tcx, self_type, span) { + Ok(()) => {} + Err(CopyImplementationError::InfrigingField(name)) => { + struct_span_err!(tcx.sess, + span, + E0204, + "the trait `Copy` may not be implemented for this type") + .span_label(span, &format!("field `{}` does not implement `Copy`", name)) + .emit() + } + Err(CopyImplementationError::InfrigingVariant(name)) => { + let item = tcx.map.expect_item(impl_node_id); + let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node { + tr.path.span + } else { + span + }; + + struct_span_err!(tcx.sess, + span, + E0205, + "the trait `Copy` may not be implemented for this type") + .span_label(span, + &format!("variant `{}` does not implement `Copy`", name)) + .emit() + } + Err(CopyImplementationError::NotAnAdt) => { + let item = tcx.map.expect_item(impl_node_id); + let span = if let ItemImpl(.., ref ty, _) = item.node { + ty.span + } else { + span + }; + + struct_span_err!(tcx.sess, + span, + E0206, + "the trait `Copy` may not be implemented for this type") + .span_label(span, &format!("type is not a structure or enumeration")) + .emit(); + } + Err(CopyImplementationError::HasDestructor) => { + struct_span_err!(tcx.sess, + span, + E0184, + "the trait `Copy` may not be implemented for this type; the \ + type has a destructor") + .span_label(span, &format!("Copy not allowed on types with destructors")) + .emit(); + } + } +} + +fn visit_implementation_of_coerce_unsized<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId, + unsize_trait: DefId, coerce_unsized_trait: DefId) +{ + debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", + impl_did); + + let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) { + n + } else { + debug!("visit_implementation_of_coerce_unsized(): impl not \ + in this crate"); + return; + }; + + let source = tcx.item_type(impl_did); + let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); + let target = trait_ref.substs.type_at(1); + debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", + source, + target); + + let span = tcx.map.span(impl_node_id); + let param_env = ParameterEnvironment::for_item(tcx, impl_node_id); + let source = source.subst(tcx, ¶m_env.free_substs); + let target = target.subst(tcx, ¶m_env.free_substs); + assert!(!source.has_escaping_regions()); + + debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", + source, + target); + + tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| { + let cause = ObligationCause::misc(span, impl_node_id); + let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, + mt_b: ty::TypeAndMut<'tcx>, + mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| { + if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { + infcx.report_mismatched_types(&cause, + mk_ptr(mt_b.ty), + target, + ty::error::TypeError::Mutability) + .emit(); + } + (mt_a.ty, mt_b.ty, unsize_trait, None) + }; + let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) { + (&ty::TyBox(a), &ty::TyBox(b)) => (a, b, unsize_trait, None), + + (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => { + infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); + check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty)) + } + + (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) | + (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => { + check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)) + } + + (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) + if def_a.is_struct() && def_b.is_struct() => { + if def_a != def_b { + let source_path = tcx.item_path_str(def_a.did); + let target_path = tcx.item_path_str(def_b.did); span_err!(tcx.sess, span, - E0376, + E0377, "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures"); + for a coercion between structures with the same \ + definition; expected {}, found {}", + source_path, + target_path); return; } - }; - let mut fulfill_cx = traits::FulfillmentContext::new(); + let fields = &def_a.struct_variant().fields; + let diff_fields = fields.iter() + .enumerate() + .filter_map(|(i, f)| { + let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); - // Register an obligation for `A: Trait`. - let cause = traits::ObligationCause::misc(span, impl_node_id); - let predicate = - tcx.predicate_for_trait_def(cause, trait_def_id, 0, source, &[target]); - fulfill_cx.register_predicate_obligation(&infcx, predicate); + if tcx.item_type(f.did).is_phantom_data() { + // Ignore PhantomData fields + return None; + } - // Check that all transitive obligations are satisfied. - if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors); + // Ignore fields that aren't significantly changed + if let Ok(ok) = infcx.sub_types(false, &cause, b, a) { + if ok.obligations.is_empty() { + return None; + } + } + + // Collect up all fields that were significantly changed + // i.e. those that contain T in coerce_unsized T -> U + Some((i, a, b)) + }) + .collect::>(); + + if diff_fields.is_empty() { + span_err!(tcx.sess, + span, + E0374, + "the trait `CoerceUnsized` may only be implemented \ + for a coercion between structures with one field \ + being coerced, none found"); + return; + } else if diff_fields.len() > 1 { + let item = tcx.map.expect_item(impl_node_id); + let span = if let ItemImpl(.., Some(ref t), _, _) = item.node { + t.path.span + } else { + tcx.map.span(impl_node_id) + }; + + let mut err = struct_span_err!(tcx.sess, + span, + E0375, + "implementing the trait \ + `CoerceUnsized` requires multiple \ + coercions"); + err.note("`CoerceUnsized` may only be implemented for \ + a coercion between structures with one field being coerced"); + err.note(&format!("currently, {} fields need coercions: {}", + diff_fields.len(), + diff_fields.iter() + .map(|&(i, a, b)| { + format!("{} ({} to {})", fields[i].name, a, b) + }) + .collect::>() + .join(", "))); + err.span_label(span, &format!("requires multiple coercions")); + err.emit(); + return; + } + + let (i, a, b) = diff_fields[0]; + let kind = ty::adjustment::CustomCoerceUnsized::Struct(i); + (a, b, coerce_unsized_trait, Some(kind)) } - // Finally, resolve all regions. - let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment - .caller_bounds); - infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id); - - if let Some(kind) = kind { - tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind); + _ => { + span_err!(tcx.sess, + span, + E0376, + "the trait `CoerceUnsized` may only be implemented \ + for a coercion between structures"); + return; } - }); + }; + + let mut fulfill_cx = traits::FulfillmentContext::new(); + + // Register an obligation for `A: Trait`. + let cause = traits::ObligationCause::misc(span, impl_node_id); + let predicate = + tcx.predicate_for_trait_def(cause, trait_def_id, 0, source, &[target]); + fulfill_cx.register_predicate_obligation(&infcx, predicate); + + // Check that all transitive obligations are satisfied. + if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(&errors); + } + + // Finally, resolve all regions. + let mut free_regions = FreeRegionMap::new(); + free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment + .caller_bounds); + infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id); + + if let Some(kind) = kind { + tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind); + } }); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 3293818348a..316e6555b41 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -16,7 +16,6 @@ // mappings. That mapping code resides here. use hir::def_id::DefId; -use rustc::traits::Reveal; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{TyParam, TyRawPtr}; @@ -25,7 +24,6 @@ use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr}; use rustc::ty::{TyProjection, TyAnon}; use CrateCtxt; -use rustc::infer::{InferCtxt}; use syntax_pos::Span; use rustc::dep_graph::DepNode; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -37,16 +35,15 @@ mod orphan; mod overlap; mod unsafety; -struct CoherenceChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - crate_context: &'a CrateCtxt<'a, 'gcx>, - inference_context: InferCtxt<'a, 'gcx, 'tcx>, +struct CoherenceChecker<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, } -struct CoherenceCheckVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - cc: &'a CoherenceChecker<'a, 'gcx, 'tcx>, +struct CoherenceCheckVisitor<'a, 'tcx: 'a> { + cc: &'a CoherenceChecker<'a, 'tcx>, } -impl<'a, 'gcx, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'gcx, 'tcx> { +impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { if let ItemImpl(..) = item.node { self.cc.check_implementation(item) @@ -60,7 +57,7 @@ impl<'a, 'gcx, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'gcx, } } -impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Returns the def ID of the base type, if there is one. fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { match ty.sty { @@ -68,7 +65,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()), - TyBox(_) => self.inference_context.tcx.lang_items.owned_box(), + TyBox(_) => self.tcx.lang_items.owned_box(), TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) | TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError | @@ -88,21 +85,21 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. - self.crate_context.tcx.visit_all_item_likes_in_krate( + self.tcx.visit_all_item_likes_in_krate( DepNode::CoherenceCheckImpl, &mut CoherenceCheckVisitor { cc: self }); - builtin::check(self.crate_context.tcx); + builtin::check(self.tcx); } fn check_implementation(&self, item: &Item) { - let tcx = self.crate_context.tcx; + let tcx = self.tcx; let impl_did = tcx.map.local_def_id(item.id); let self_type = tcx.item_type(impl_did); // If there are no traits, then this implementation must have a // base type. - if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(impl_did) { + if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { debug!("(checking implementation) adding impl for trait '{:?}', item '{}'", trait_ref, item.name); @@ -113,9 +110,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { return; } - enforce_trait_manually_implementable(self.crate_context.tcx, - item.span, - trait_ref.def_id); + enforce_trait_manually_implementable(self.tcx, item.span, trait_ref.def_id); self.add_trait_impl(trait_ref, impl_did); } else { // Skip inherent impls where the self type is an error @@ -134,16 +129,15 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) { - let tcx = self.crate_context.tcx; - tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id); + self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id); } - fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'gcx>, impl_def_id: DefId) { + fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) { debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}", impl_trait_ref, impl_def_id); - let trait_def = self.crate_context.tcx.lookup_trait_def(impl_trait_ref.def_id); - trait_def.record_local_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref); + let trait_def = self.tcx.lookup_trait_def(impl_trait_ref.def_id); + trait_def.record_local_impl(self.tcx, impl_def_id, impl_trait_ref); } } @@ -176,13 +170,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def pub fn check_coherence(ccx: &CrateCtxt) { let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); - ccx.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { - CoherenceChecker { - crate_context: ccx, - inference_context: infcx, - } - .check(); - }); + CoherenceChecker { tcx: ccx.tcx }.check(); unsafety::check(ccx.tcx); orphan::check(ccx.tcx); overlap::check(ccx.tcx);