rustc_typeck: lift CrateCtxt to TyCtxt.

This commit is contained in:
Eduard Burtescu 2016-10-04 02:19:40 +03:00 committed by Eduard-Mihai Burtescu
parent 374ea14412
commit 4649f7387e
24 changed files with 653 additions and 759 deletions

View file

@ -525,6 +525,20 @@ pub struct GlobalCtxt<'tcx> {
stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>, stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
layout_interner: RefCell<FxHashSet<&'tcx Layout>>, layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
/// A vector of every trait accessible in the whole crate
/// (i.e. including those from subcrates). This is used only for
/// error reporting, and so is lazily initialised and generally
/// shouldn't taint the common path (hence the RefCell).
pub all_traits: RefCell<Option<Vec<DefId>>>,
/// Obligations which will have to be checked at the end of
/// type-checking, after all functions have been inferred.
/// The key is the NodeId of the item the obligations were from.
pub deferred_obligations: RefCell<NodeMap<Vec<traits::DeferredObligation<'tcx>>>>,
/// HIR Ty -> Ty lowering cache.
pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
} }
impl<'tcx> GlobalCtxt<'tcx> { impl<'tcx> GlobalCtxt<'tcx> {
@ -720,6 +734,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
layout_depth: Cell::new(0), layout_depth: Cell::new(0),
derive_macros: RefCell::new(NodeMap()), derive_macros: RefCell::new(NodeMap()),
stability_interner: RefCell::new(FxHashSet()), stability_interner: RefCell::new(FxHashSet()),
all_traits: RefCell::new(None),
deferred_obligations: RefCell::new(NodeMap()),
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
}, f) }, f)
} }
} }

View file

@ -37,6 +37,7 @@ macro_rules! define_maps {
pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => { pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
pub struct Maps<$tcx> { pub struct Maps<$tcx> {
providers: IndexVec<CrateNum, Providers<$tcx>>, providers: IndexVec<CrateNum, Providers<$tcx>>,
pub query_stack: RefCell<Vec<Query>>,
$($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),* $($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
} }
@ -46,11 +47,18 @@ macro_rules! define_maps {
-> Self { -> Self {
Maps { Maps {
providers, providers,
query_stack: RefCell::new(vec![]),
$($name: RefCell::new(DepTrackingMap::new(dep_graph.clone()))),* $($name: RefCell::new(DepTrackingMap::new(dep_graph.clone()))),*
} }
} }
} }
#[allow(bad_style)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Query {
$($(#[$attr])* $name($K)),*
}
pub mod queries { pub mod queries {
use std::marker::PhantomData; use std::marker::PhantomData;
@ -119,6 +127,11 @@ define_maps! { <'tcx>
/// additional acyclicity requirements). /// additional acyclicity requirements).
pub super_predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, pub super_predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>,
/// To avoid cycles within the predicates of a single item we compute
/// per-type-parameter predicates for resolving `T::AssocTy`.
pub type_param_predicates: ItemSignature(DefId)
-> ty::GenericPredicates<'tcx>,
pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef, pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
pub adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef, pub adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef,
pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>, pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>,

View file

@ -31,7 +31,7 @@ use ty::subst::{Subst, Substs};
use ty::util::IntTypeExt; use ty::util::IntTypeExt;
use ty::walk::TypeWalker; use ty::walk::TypeWalker;
use util::common::MemoizationMap; use util::common::MemoizationMap;
use util::nodemap::{NodeSet, NodeMap, FxHashMap}; use util::nodemap::{NodeSet, FxHashMap};
use serialize::{self, Encodable, Encoder}; use serialize::{self, Encodable, Encoder};
use std::borrow::Cow; use std::borrow::Cow;
@ -104,13 +104,12 @@ mod sty;
/// The complete set of all analyses described in this module. This is /// The complete set of all analyses described in this module. This is
/// produced by the driver and fed to trans and later passes. /// produced by the driver and fed to trans and later passes.
#[derive(Clone)] #[derive(Clone)]
pub struct CrateAnalysis<'tcx> { pub struct CrateAnalysis {
pub export_map: ExportMap, pub export_map: ExportMap,
pub access_levels: middle::privacy::AccessLevels, pub access_levels: middle::privacy::AccessLevels,
pub reachable: NodeSet, pub reachable: NodeSet,
pub name: String, pub name: String,
pub glob_map: Option<hir::GlobMap>, pub glob_map: Option<hir::GlobMap>,
pub hir_ty_to_ty: NodeMap<Ty<'tcx>>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -1383,7 +1382,7 @@ pub struct ReprOptions {
} }
impl ReprOptions { impl ReprOptions {
pub fn new<'a, 'gcx, 'tcx>(tcx: &TyCtxt<'a, 'gcx, 'tcx>, did: DefId) -> ReprOptions { pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
let mut ret = ReprOptions::default(); let mut ret = ReprOptions::default();
let attrs = tcx.lookup_repr_hints(did); let attrs = tcx.lookup_repr_hints(did);
for r in attrs.iter() { for r in attrs.iter() {
@ -1400,7 +1399,7 @@ impl ReprOptions {
} }
impl<'a, 'gcx, 'tcx> AdtDef { impl<'a, 'gcx, 'tcx> AdtDef {
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fn new(tcx: TyCtxt,
did: DefId, did: DefId,
kind: AdtKind, kind: AdtKind,
variants: Vec<VariantDef>, variants: Vec<VariantDef>,

View file

@ -21,7 +21,7 @@ use rustc::middle::{self, dependency_format, stability, reachable};
use rustc::middle::privacy::AccessLevels; use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
use rustc::util::common::time; use rustc::util::common::time;
use rustc::util::nodemap::{NodeSet, NodeMap}; use rustc::util::nodemap::NodeSet;
use rustc::util::fs::rename_or_copy_remove; use rustc::util::fs::rename_or_copy_remove;
use rustc_borrowck as borrowck; use rustc_borrowck as borrowck;
use rustc_incremental::{self, IncrementalHashesMap}; use rustc_incremental::{self, IncrementalHashesMap};
@ -343,7 +343,7 @@ pub struct CompileState<'a, 'tcx: 'a> {
pub hir_crate: Option<&'a hir::Crate>, pub hir_crate: Option<&'a hir::Crate>,
pub hir_map: Option<&'a hir_map::Map<'tcx>>, pub hir_map: Option<&'a hir_map::Map<'tcx>>,
pub resolutions: Option<&'a Resolutions>, pub resolutions: Option<&'a Resolutions>,
pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>, pub analysis: Option<&'a ty::CrateAnalysis>,
pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>, pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
pub trans: Option<&'a trans::CrateTranslation>, pub trans: Option<&'a trans::CrateTranslation>,
} }
@ -417,7 +417,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
arenas: &'tcx GlobalArenas<'tcx>, arenas: &'tcx GlobalArenas<'tcx>,
cstore: &'a CStore, cstore: &'a CStore,
hir_map: &'a hir_map::Map<'tcx>, hir_map: &'a hir_map::Map<'tcx>,
analysis: &'a ty::CrateAnalysis<'static>, analysis: &'a ty::CrateAnalysis,
resolutions: &'a Resolutions, resolutions: &'a Resolutions,
krate: &'a ast::Crate, krate: &'a ast::Crate,
hir_crate: &'a hir::Crate, hir_crate: &'a hir::Crate,
@ -444,7 +444,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
out_file: &'a Option<PathBuf>, out_file: &'a Option<PathBuf>,
krate: Option<&'a ast::Crate>, krate: Option<&'a ast::Crate>,
hir_crate: &'a hir::Crate, hir_crate: &'a hir::Crate,
analysis: &'a ty::CrateAnalysis<'tcx>, analysis: &'a ty::CrateAnalysis,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
crate_name: &'a str) crate_name: &'a str)
-> Self { -> Self {
@ -534,7 +534,7 @@ fn count_nodes(krate: &ast::Crate) -> usize {
pub struct ExpansionResult { pub struct ExpansionResult {
pub expanded_crate: ast::Crate, pub expanded_crate: ast::Crate,
pub defs: hir_map::Definitions, pub defs: hir_map::Definitions,
pub analysis: ty::CrateAnalysis<'static>, pub analysis: ty::CrateAnalysis,
pub resolutions: Resolutions, pub resolutions: Resolutions,
pub hir_forest: hir_map::Forest, pub hir_forest: hir_map::Forest,
} }
@ -797,7 +797,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
reachable: NodeSet(), reachable: NodeSet(),
name: crate_name.to_string(), name: crate_name.to_string(),
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
hir_ty_to_ty: NodeMap(),
}, },
resolutions: Resolutions { resolutions: Resolutions {
freevars: resolver.freevars, freevars: resolver.freevars,
@ -813,7 +812,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
/// structures carrying the results of the analysis. /// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
hir_map: hir_map::Map<'tcx>, hir_map: hir_map::Map<'tcx>,
mut analysis: ty::CrateAnalysis<'tcx>, mut analysis: ty::CrateAnalysis,
resolutions: Resolutions, resolutions: Resolutions,
arena: &'tcx DroplessArena, arena: &'tcx DroplessArena,
arenas: &'tcx GlobalArenas<'tcx>, arenas: &'tcx GlobalArenas<'tcx>,
@ -821,7 +820,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
f: F) f: F)
-> Result<R, usize> -> Result<R, usize>
where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
ty::CrateAnalysis<'tcx>, ty::CrateAnalysis,
IncrementalHashesMap, IncrementalHashesMap,
CompileResult) -> R CompileResult) -> R
{ {
@ -908,8 +907,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|| stability::check_unstable_api_usage(tcx)); || stability::check_unstable_api_usage(tcx));
// passes are timed inside typeck // passes are timed inside typeck
analysis.hir_ty_to_ty = try_with_f!(typeck::check_crate(tcx), (tcx, analysis, incremental_hashes_map));
try_with_f!(typeck::check_crate(tcx), (tcx, analysis, incremental_hashes_map));
time(time_passes, time(time_passes,
"const checking", "const checking",

View file

@ -201,7 +201,7 @@ impl PpSourceMode {
fn call_with_pp_support_hir<'tcx, A, B, F>(&self, fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
sess: &'tcx Session, sess: &'tcx Session,
hir_map: &hir_map::Map<'tcx>, hir_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis<'tcx>, analysis: &ty::CrateAnalysis,
resolutions: &Resolutions, resolutions: &Resolutions,
arena: &'tcx DroplessArena, arena: &'tcx DroplessArena,
arenas: &'tcx GlobalArenas<'tcx>, arenas: &'tcx GlobalArenas<'tcx>,
@ -838,7 +838,7 @@ pub fn print_after_parsing(sess: &Session,
pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
hir_map: &hir_map::Map<'tcx>, hir_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis<'tcx>, analysis: &ty::CrateAnalysis,
resolutions: &Resolutions, resolutions: &Resolutions,
input: &Input, input: &Input,
krate: &ast::Crate, krate: &ast::Crate,
@ -958,7 +958,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
// Instead, we call that function ourselves. // Instead, we call that function ourselves.
fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
hir_map: &hir_map::Map<'tcx>, hir_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis<'tcx>, analysis: &ty::CrateAnalysis,
resolutions: &Resolutions, resolutions: &Resolutions,
crate_name: &str, crate_name: &str,
arena: &'tcx DroplessArena, arena: &'tcx DroplessArena,

View file

@ -85,7 +85,7 @@ pub mod recorder {
pub struct SaveContext<'l, 'tcx: 'l> { pub struct SaveContext<'l, 'tcx: 'l> {
tcx: TyCtxt<'l, 'tcx, 'tcx>, tcx: TyCtxt<'l, 'tcx, 'tcx>,
tables: &'l ty::TypeckTables<'tcx>, tables: &'l ty::TypeckTables<'tcx>,
analysis: &'l ty::CrateAnalysis<'tcx>, analysis: &'l ty::CrateAnalysis,
span_utils: SpanUtils<'tcx>, span_utils: SpanUtils<'tcx>,
} }
@ -550,7 +550,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
match *qpath { match *qpath {
hir::QPath::Resolved(_, ref path) => path.def, hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => { hir::QPath::TypeRelative(..) => {
if let Some(ty) = self.analysis.hir_ty_to_ty.get(&id) { if let Some(ty) = self.tcx.ast_ty_to_ty_cache.borrow().get(&id) {
if let ty::TyProjection(proj) = ty.sty { if let ty::TyProjection(proj) = ty.sty {
for item in self.tcx.associated_items(proj.trait_ref.def_id) { for item in self.tcx.associated_items(proj.trait_ref.def_id) {
if item.kind == ty::AssociatedKind::Type { if item.kind == ty::AssociatedKind::Type {
@ -854,7 +854,7 @@ impl Format {
pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>, pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
krate: &ast::Crate, krate: &ast::Crate,
analysis: &'l ty::CrateAnalysis<'tcx>, analysis: &'l ty::CrateAnalysis,
cratename: &str, cratename: &str,
odir: Option<&Path>, odir: Option<&Path>,
format: Format) { format: Format) {

View file

@ -897,7 +897,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// FIXME: Self type is not always computed when we are here because type parameter // FIXME: Self type is not always computed when we are here because type parameter
// bounds may affect Self type and have to be converted before it. // bounds may affect Self type and have to be converted before it.
let trait_ref = if impl_def_id.is_local() { let trait_ref = if impl_def_id.is_local() {
tcx.impl_trait_refs.borrow().get(&impl_def_id).cloned().and_then(|x| x) tcx.maps.impl_trait_ref.borrow().get(&impl_def_id)
.cloned().and_then(|x| x)
} else { } else {
tcx.impl_trait_ref(impl_def_id) tcx.impl_trait_ref(impl_def_id)
}; };

View file

@ -10,11 +10,10 @@
use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag}; use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag};
use CrateCtxt;
use hir::def::Def; use hir::def::Def;
use hir::def_id::{DefId, LOCAL_CRATE}; use hir::def_id::{DefId, LOCAL_CRATE};
use rustc::{infer, traits}; use rustc::{infer, traits};
use rustc::ty::{self, LvaluePreference, Ty}; use rustc::ty::{self, TyCtxt, LvaluePreference, Ty};
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax_pos::Span; use syntax_pos::Span;
@ -23,12 +22,9 @@ use rustc::hir;
/// Check that it is legal to call methods of the trait corresponding /// Check that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific /// to `trait_id` (this only cares about the trait, not the specific
/// method that is called) /// method that is called)
pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) { pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) {
if ccx.tcx.lang_items.drop_trait() == Some(trait_id) { if tcx.lang_items.drop_trait() == Some(trait_id) {
struct_span_err!(ccx.tcx.sess, struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
span,
E0040,
"explicit use of destructor method")
.span_label(span, &format!("explicit destructor calls not allowed")) .span_label(span, &format!("explicit destructor calls not allowed"))
.emit(); .emit();
} }

View file

@ -11,7 +11,7 @@
use rustc::hir::{self, ImplItemKind, TraitItemKind}; use rustc::hir::{self, ImplItemKind, TraitItemKind};
use rustc::infer::{self, InferOk}; use rustc::infer::{self, InferOk};
use rustc::middle::free_region::FreeRegionMap; use rustc::middle::free_region::FreeRegionMap;
use rustc::ty; use rustc::ty::{self, TyCtxt};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::error::{ExpectedFound, TypeError};
use rustc::ty::subst::{Subst, Substs}; use rustc::ty::subst::{Subst, Substs};
@ -20,7 +20,6 @@ use rustc::util::common::ErrorReported;
use syntax::ast; use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
use CrateCtxt;
use super::assoc; use super::assoc;
use super::{Inherited, FnCtxt}; use super::{Inherited, FnCtxt};
use astconv::ExplicitSelf; use astconv::ExplicitSelf;
@ -36,7 +35,7 @@ use astconv::ExplicitSelf;
/// - trait_m: the method in the trait /// - trait_m: the method in the trait
/// - impl_trait_ref: the TraitRef corresponding to the trait implementation /// - impl_trait_ref: the TraitRef corresponding to the trait implementation
pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
impl_m_span: Span, impl_m_span: Span,
impl_m_body_id: ast::NodeId, impl_m_body_id: ast::NodeId,
@ -47,7 +46,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
debug!("compare_impl_method(impl_trait_ref={:?})", debug!("compare_impl_method(impl_trait_ref={:?})",
impl_trait_ref); impl_trait_ref);
if let Err(ErrorReported) = compare_self_type(ccx, if let Err(ErrorReported) = compare_self_type(tcx,
impl_m, impl_m,
impl_m_span, impl_m_span,
trait_m, trait_m,
@ -55,7 +54,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
return; return;
} }
if let Err(ErrorReported) = compare_number_of_generics(ccx, if let Err(ErrorReported) = compare_number_of_generics(tcx,
impl_m, impl_m,
impl_m_span, impl_m_span,
trait_m, trait_m,
@ -63,7 +62,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
return; return;
} }
if let Err(ErrorReported) = compare_number_of_method_arguments(ccx, if let Err(ErrorReported) = compare_number_of_method_arguments(tcx,
impl_m, impl_m,
impl_m_span, impl_m_span,
trait_m, trait_m,
@ -71,7 +70,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
return; return;
} }
if let Err(ErrorReported) = compare_predicate_entailment(ccx, if let Err(ErrorReported) = compare_predicate_entailment(tcx,
impl_m, impl_m,
impl_m_span, impl_m_span,
impl_m_body_id, impl_m_body_id,
@ -82,7 +81,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} }
} }
fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
impl_m_span: Span, impl_m_span: Span,
impl_m_body_id: ast::NodeId, impl_m_body_id: ast::NodeId,
@ -90,8 +89,6 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
impl_trait_ref: ty::TraitRef<'tcx>, impl_trait_ref: ty::TraitRef<'tcx>,
old_broken_mode: bool) old_broken_mode: bool)
-> Result<(), ErrorReported> { -> Result<(), ErrorReported> {
let tcx = ccx.tcx;
let trait_to_impl_substs = impl_trait_ref.substs; let trait_to_impl_substs = impl_trait_ref.substs;
let cause = ObligationCause { let cause = ObligationCause {
@ -190,7 +187,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let trait_m_predicates = tcx.item_predicates(trait_m.def_id); let trait_m_predicates = tcx.item_predicates(trait_m.def_id);
// Check region bounds. // Check region bounds.
check_region_bounds_on_impl_method(ccx, check_region_bounds_on_impl_method(tcx,
impl_m_span, impl_m_span,
impl_m, impl_m,
&trait_m_generics, &trait_m_generics,
@ -228,7 +225,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
normalize_cause.clone()); normalize_cause.clone());
tcx.infer_ctxt(trait_param_env, Reveal::NotSpecializable).enter(|infcx| { tcx.infer_ctxt(trait_param_env, Reveal::NotSpecializable).enter(|infcx| {
let inh = Inherited::new(ccx, infcx); let inh = Inherited::new(infcx);
let infcx = &inh.infcx; let infcx = &inh.infcx;
let fulfillment_cx = &inh.fulfillment_cx; let fulfillment_cx = &inh.fulfillment_cx;
@ -383,7 +380,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}) })
} }
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span: Span, span: Span,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
trait_generics: &ty::Generics, trait_generics: &ty::Generics,
@ -414,7 +411,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// are zero. Since I don't quite know how to phrase things at // are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message. // the moment, give a kind of vague error message.
if trait_params.len() != impl_params.len() { if trait_params.len() != impl_params.len() {
struct_span_err!(ccx.tcx.sess, struct_span_err!(tcx.sess,
span, span,
E0195, E0195,
"lifetime parameters or bounds on method `{}` do not match the \ "lifetime parameters or bounds on method `{}` do not match the \
@ -510,14 +507,13 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
} }
} }
fn compare_self_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
impl_m_span: Span, impl_m_span: Span,
trait_m: &ty::AssociatedItem, trait_m: &ty::AssociatedItem,
impl_trait_ref: ty::TraitRef<'tcx>) impl_trait_ref: ty::TraitRef<'tcx>)
-> Result<(), ErrorReported> -> Result<(), ErrorReported>
{ {
let tcx = ccx.tcx;
// Try to give more informative error messages about self typing // Try to give more informative error messages about self typing
// mismatches. Note that any mismatch will also be detected // mismatches. Note that any mismatch will also be detected
// below, where we construct a canonical function type that // below, where we construct a canonical function type that
@ -583,13 +579,12 @@ fn compare_self_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
Ok(()) Ok(())
} }
fn compare_number_of_generics<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
impl_m_span: Span, impl_m_span: Span,
trait_m: &ty::AssociatedItem, trait_m: &ty::AssociatedItem,
trait_item_span: Option<Span>) trait_item_span: Option<Span>)
-> Result<(), ErrorReported> { -> Result<(), ErrorReported> {
let tcx = ccx.tcx;
let impl_m_generics = tcx.item_generics(impl_m.def_id); let impl_m_generics = tcx.item_generics(impl_m.def_id);
let trait_m_generics = tcx.item_generics(trait_m.def_id); let trait_m_generics = tcx.item_generics(trait_m.def_id);
let num_impl_m_type_params = impl_m_generics.types.len(); let num_impl_m_type_params = impl_m_generics.types.len();
@ -653,13 +648,12 @@ fn compare_number_of_generics<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
Ok(()) Ok(())
} }
fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem, impl_m: &ty::AssociatedItem,
impl_m_span: Span, impl_m_span: Span,
trait_m: &ty::AssociatedItem, trait_m: &ty::AssociatedItem,
trait_item_span: Option<Span>) trait_item_span: Option<Span>)
-> Result<(), ErrorReported> { -> Result<(), ErrorReported> {
let tcx = ccx.tcx;
let m_fty = |method: &ty::AssociatedItem| { let m_fty = |method: &ty::AssociatedItem| {
match tcx.item_type(method.def_id).sty { match tcx.item_type(method.def_id).sty {
ty::TyFnDef(_, _, f) => f, ty::TyFnDef(_, _, f) => f,
@ -739,14 +733,13 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
Ok(()) Ok(())
} }
pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_c: &ty::AssociatedItem, impl_c: &ty::AssociatedItem,
impl_c_span: Span, impl_c_span: Span,
trait_c: &ty::AssociatedItem, trait_c: &ty::AssociatedItem,
impl_trait_ref: ty::TraitRef<'tcx>) { impl_trait_ref: ty::TraitRef<'tcx>) {
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
let tcx = ccx.tcx;
tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
let mut fulfillment_cx = traits::FulfillmentContext::new(); let mut fulfillment_cx = traits::FulfillmentContext::new();

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use CrateCtxt;
use check::regionck::RegionCtxt; use check::regionck::RegionCtxt;
use hir::def_id::DefId; use hir::def_id::DefId;
@ -40,17 +39,18 @@ use syntax_pos::Span;
/// struct/enum definition for the nominal type itself (i.e. /// struct/enum definition for the nominal type itself (i.e.
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`). /// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
/// ///
pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> { pub fn check_drop_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let dtor_self_type = ccx.tcx.item_type(drop_impl_did); drop_impl_did: DefId) -> Result<(), ()> {
let dtor_predicates = ccx.tcx.item_predicates(drop_impl_did); let dtor_self_type = tcx.item_type(drop_impl_did);
let dtor_predicates = tcx.item_predicates(drop_impl_did);
match dtor_self_type.sty { match dtor_self_type.sty {
ty::TyAdt(adt_def, self_to_impl_substs) => { ty::TyAdt(adt_def, self_to_impl_substs) => {
ensure_drop_params_and_item_params_correspond(ccx, ensure_drop_params_and_item_params_correspond(tcx,
drop_impl_did, drop_impl_did,
dtor_self_type, dtor_self_type,
adt_def.did)?; adt_def.did)?;
ensure_drop_predicates_are_implied_by_item_defn(ccx, ensure_drop_predicates_are_implied_by_item_defn(tcx,
drop_impl_did, drop_impl_did,
&dtor_predicates, &dtor_predicates,
adt_def.did, adt_def.did,
@ -59,7 +59,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()>
_ => { _ => {
// Destructors only work on nominal types. This was // Destructors only work on nominal types. This was
// already checked by coherence, so we can panic here. // already checked by coherence, so we can panic here.
let span = ccx.tcx.def_span(drop_impl_did); let span = tcx.def_span(drop_impl_did);
span_bug!(span, span_bug!(span,
"should have been rejected by coherence check: {}", "should have been rejected by coherence check: {}",
dtor_self_type); dtor_self_type);
@ -68,13 +68,12 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()>
} }
fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
drop_impl_did: DefId, drop_impl_did: DefId,
drop_impl_ty: Ty<'tcx>, drop_impl_ty: Ty<'tcx>,
self_type_did: DefId) self_type_did: DefId)
-> Result<(), ()> -> Result<(), ()>
{ {
let tcx = ccx.tcx;
let drop_impl_node_id = tcx.hir.as_local_node_id(drop_impl_did).unwrap(); 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(); let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap();
@ -126,7 +125,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
/// Confirms that every predicate imposed by dtor_predicates is /// Confirms that every predicate imposed by dtor_predicates is
/// implied by assuming the predicates attached to self_type_did. /// implied by assuming the predicates attached to self_type_did.
fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
drop_impl_did: DefId, drop_impl_did: DefId,
dtor_predicates: &ty::GenericPredicates<'tcx>, dtor_predicates: &ty::GenericPredicates<'tcx>,
self_type_did: DefId, self_type_did: DefId,
@ -169,8 +168,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
// absent. So we report an error that the Drop impl injected a // absent. So we report an error that the Drop impl injected a
// predicate that is not present on the struct definition. // predicate that is not present on the struct definition.
let tcx = ccx.tcx;
let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap(); let self_type_node_id = tcx.hir.as_local_node_id(self_type_did).unwrap();
let drop_impl_span = tcx.def_span(drop_impl_did); let drop_impl_span = tcx.def_span(drop_impl_did);

View file

@ -14,9 +14,9 @@
use intrinsics; use intrinsics;
use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::traits::{ObligationCause, ObligationCauseCode};
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty}; use rustc::ty::{self, TyCtxt, Ty};
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
use {CrateCtxt, require_same_types}; use require_same_types;
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast; use syntax::ast;
@ -27,13 +27,12 @@ use rustc::hir;
use std::iter; use std::iter;
fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
it: &hir::ForeignItem, it: &hir::ForeignItem,
n_tps: usize, n_tps: usize,
abi: Abi, abi: Abi,
inputs: Vec<Ty<'tcx>>, inputs: Vec<Ty<'tcx>>,
output: Ty<'tcx>) { output: Ty<'tcx>) {
let tcx = ccx.tcx;
let def_id = tcx.hir.local_def_id(it.id); let def_id = tcx.hir.local_def_id(it.id);
let substs = Substs::for_item(tcx, def_id, let substs = Substs::for_item(tcx, def_id,
@ -59,7 +58,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
.span_label(span, &format!("expected {} type parameter", n_tps)) .span_label(span, &format!("expected {} type parameter", n_tps))
.emit(); .emit();
} else { } else {
require_same_types(ccx, require_same_types(tcx,
&ObligationCause::new(it.span, &ObligationCause::new(it.span,
it.id, it.id,
ObligationCauseCode::IntrinsicType), ObligationCauseCode::IntrinsicType),
@ -70,13 +69,9 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
/// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs, /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
/// and in libcore/intrinsics.rs /// and in libcore/intrinsics.rs
pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { it: &hir::ForeignItem) {
let name = Symbol::intern(&format!("P{}", n)); let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)));
ccx.tcx.mk_param(n, name)
}
let tcx = ccx.tcx;
let name = it.name.as_str(); let name = it.name.as_str();
let (n_tps, inputs, output) = if name.starts_with("atomic_") { let (n_tps, inputs, output) = if name.starts_with("atomic_") {
let split : Vec<&str> = name.split('_').collect(); let split : Vec<&str> = name.split('_').collect();
@ -84,19 +79,19 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
//We only care about the operation here //We only care about the operation here
let (n_tps, inputs, output) = match split[1] { let (n_tps, inputs, output) = match split[1] {
"cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(0)),
param(ccx, 0), param(0),
param(ccx, 0)], param(0)],
tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), tcx.intern_tup(&[param(0), tcx.types.bool], false)),
"load" => (1, vec![tcx.mk_imm_ptr(param(ccx, 0))], "load" => (1, vec![tcx.mk_imm_ptr(param(0))],
param(ccx, 0)), param(0)),
"store" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)], "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)],
tcx.mk_nil()), tcx.mk_nil()),
"xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
"min" | "umax" | "umin" => { "min" | "umax" | "umin" => {
(1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)], (1, vec![tcx.mk_mut_ptr(param(0)), param(0)],
param(ccx, 0)) param(0))
} }
"fence" | "singlethreadfence" => { "fence" | "singlethreadfence" => {
(0, Vec::new(), tcx.mk_nil()) (0, Vec::new(), tcx.mk_nil())
@ -116,45 +111,45 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
let (n_tps, inputs, output) = match &name[..] { let (n_tps, inputs, output) = match &name[..] {
"breakpoint" => (0, Vec::new(), tcx.mk_nil()), "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
"size_of" | "size_of" |
"pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize), "pref_align_of" | "min_align_of" => (1, Vec::new(), tcx.types.usize),
"size_of_val" | "min_align_of_val" => { "size_of_val" | "min_align_of_val" => {
(1, vec![ (1, vec![
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
ty::BrAnon(0))), ty::BrAnon(0))),
param(ccx, 0)) param(0))
], ccx.tcx.types.usize) ], tcx.types.usize)
} }
"rustc_peek" => (1, vec![param(ccx, 0)], param(ccx, 0)), "rustc_peek" => (1, vec![param(0)], param(0)),
"init" => (1, Vec::new(), param(ccx, 0)), "init" => (1, Vec::new(), param(0)),
"uninit" => (1, Vec::new(), param(ccx, 0)), "uninit" => (1, Vec::new(), param(0)),
"forget" => (1, vec![ param(ccx, 0) ], tcx.mk_nil()), "forget" => (1, vec![ param(0) ], tcx.mk_nil()),
"transmute" => (2, vec![ param(ccx, 0) ], param(ccx, 1)), "transmute" => (2, vec![ param(0) ], param(1)),
"move_val_init" => { "move_val_init" => {
(1, (1,
vec![ vec![
tcx.mk_mut_ptr(param(ccx, 0)), tcx.mk_mut_ptr(param(0)),
param(ccx, 0) param(0)
], ],
tcx.mk_nil()) tcx.mk_nil())
} }
"drop_in_place" => { "drop_in_place" => {
(1, vec![tcx.mk_mut_ptr(param(ccx, 0))], tcx.mk_nil()) (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_nil())
} }
"needs_drop" => (1, Vec::new(), ccx.tcx.types.bool), "needs_drop" => (1, Vec::new(), tcx.types.bool),
"type_name" => (1, Vec::new(), tcx.mk_static_str()), "type_name" => (1, Vec::new(), tcx.mk_static_str()),
"type_id" => (1, Vec::new(), ccx.tcx.types.u64), "type_id" => (1, Vec::new(), tcx.types.u64),
"offset" | "arith_offset" => { "offset" | "arith_offset" => {
(1, (1,
vec![ vec![
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutImmutable mutbl: hir::MutImmutable
}), }),
ccx.tcx.types.isize tcx.types.isize
], ],
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutImmutable mutbl: hir::MutImmutable
})) }))
} }
@ -162,11 +157,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
(1, (1,
vec![ vec![
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutImmutable mutbl: hir::MutImmutable
}), }),
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutMutable mutbl: hir::MutMutable
}), }),
tcx.types.usize, tcx.types.usize,
@ -177,11 +172,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
(1, (1,
vec![ vec![
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutMutable mutbl: hir::MutMutable
}), }),
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutImmutable mutbl: hir::MutImmutable
}), }),
tcx.types.usize, tcx.types.usize,
@ -192,7 +187,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
(1, (1,
vec![ vec![
tcx.mk_ptr(ty::TypeAndMut { tcx.mk_ptr(ty::TypeAndMut {
ty: param(ccx, 0), ty: param(0),
mutbl: hir::MutMutable mutbl: hir::MutMutable
}), }),
tcx.types.u8, tcx.types.u8,
@ -264,23 +259,23 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
"roundf64" => (0, vec![ tcx.types.f64 ], tcx.types.f64), "roundf64" => (0, vec![ tcx.types.f64 ], tcx.types.f64),
"volatile_load" => "volatile_load" =>
(1, vec![ tcx.mk_imm_ptr(param(ccx, 0)) ], param(ccx, 0)), (1, vec![ tcx.mk_imm_ptr(param(0)) ], param(0)),
"volatile_store" => "volatile_store" =>
(1, vec![ tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0) ], tcx.mk_nil()), (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()),
"ctpop" | "ctlz" | "cttz" | "bswap" => (1, vec![param(ccx, 0)], param(ccx, 0)), "ctpop" | "ctlz" | "cttz" | "bswap" => (1, vec![param(0)], param(0)),
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" =>
(1, vec![param(ccx, 0), param(ccx, 0)], (1, vec![param(0), param(0)],
tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), tcx.intern_tup(&[param(0), tcx.types.bool], false)),
"unchecked_div" | "unchecked_rem" => "unchecked_div" | "unchecked_rem" =>
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), (1, vec![param(0), param(0)], param(0)),
"overflowing_add" | "overflowing_sub" | "overflowing_mul" => "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), (1, vec![param(0), param(0)], param(0)),
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" =>
(1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), (1, vec![param(0), param(0)], param(0)),
"assume" => (0, vec![tcx.types.bool], tcx.mk_nil()), "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
"likely" => (0, vec![tcx.types.bool], tcx.types.bool), "likely" => (0, vec![tcx.types.bool], tcx.types.bool),
@ -289,7 +284,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
"discriminant_value" => (1, vec![ "discriminant_value" => (1, vec![
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
ty::BrAnon(0))), ty::BrAnon(0))),
param(ccx, 0))], tcx.types.u64), param(0))], tcx.types.u64),
"try" => { "try" => {
let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
@ -312,18 +307,17 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
}; };
(n_tps, inputs, output) (n_tps, inputs, output)
}; };
equate_intrinsic_type(ccx, it, n_tps, Abi::RustIntrinsic, inputs, output) equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, inputs, output)
} }
/// Type-check `extern "platform-intrinsic" { ... }` functions. /// Type-check `extern "platform-intrinsic" { ... }` functions.
pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
it: &hir::ForeignItem) { it: &hir::ForeignItem) {
let param = |n| { let param = |n| {
let name = Symbol::intern(&format!("P{}", n)); let name = Symbol::intern(&format!("P{}", n));
ccx.tcx.mk_param(n, name) tcx.mk_param(n, name)
}; };
let tcx = ccx.tcx;
let def_id = tcx.hir.local_def_id(it.id); let def_id = tcx.hir.local_def_id(it.id);
let i_n_tps = tcx.item_generics(def_id).types.len(); let i_n_tps = tcx.item_generics(def_id).types.len();
let name = it.name.as_str(); let name = it.name.as_str();
@ -379,10 +373,10 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
} }
let input_pairs = intr.inputs.iter().zip(sig.inputs()); let input_pairs = intr.inputs.iter().zip(sig.inputs());
for (i, (expected_arg, arg)) in input_pairs.enumerate() { for (i, (expected_arg, arg)) in input_pairs.enumerate() {
match_intrinsic_type_to_type(ccx, &format!("argument {}", i + 1), it.span, match_intrinsic_type_to_type(tcx, &format!("argument {}", i + 1), it.span,
&mut structural_to_nomimal, expected_arg, arg); &mut structural_to_nomimal, expected_arg, arg);
} }
match_intrinsic_type_to_type(ccx, "return value", it.span, match_intrinsic_type_to_type(tcx, "return value", it.span,
&mut structural_to_nomimal, &mut structural_to_nomimal,
&intr.output, sig.output()); &intr.output, sig.output());
return return
@ -396,15 +390,15 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
} }
}; };
equate_intrinsic_type(ccx, it, n_tps, Abi::PlatformIntrinsic, equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic,
inputs, output) inputs, output)
} }
// walk the expected type and the actual type in lock step, checking they're // walk the expected type and the actual type in lock step, checking they're
// the same, in a kinda-structural way, i.e. `Vector`s have to be simd structs with // the same, in a kinda-structural way, i.e. `Vector`s have to be simd structs with
// exactly the right element type // exactly the right element type
fn match_intrinsic_type_to_type<'tcx, 'a>( fn match_intrinsic_type_to_type<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
position: &str, position: &str,
span: Span, span: Span,
structural_to_nominal: &mut FxHashMap<&'a intrinsics::Type, ty::Ty<'tcx>>, structural_to_nominal: &mut FxHashMap<&'a intrinsics::Type, ty::Ty<'tcx>>,
@ -413,7 +407,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
use intrinsics::Type::*; use intrinsics::Type::*;
let simple_error = |real: &str, expected: &str| { let simple_error = |real: &str, expected: &str| {
span_err!(ccx.tcx.sess, span, E0442, span_err!(tcx.sess, span, E0442,
"intrinsic {} has wrong type: found {}, expected {}", "intrinsic {} has wrong type: found {}, expected {}",
position, real, expected) position, real, expected)
}; };
@ -453,7 +447,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
simple_error(&format!("`{}`", t), simple_error(&format!("`{}`", t),
if const_ {"const pointer"} else {"mut pointer"}) if const_ {"const pointer"} else {"mut pointer"})
} }
match_intrinsic_type_to_type(ccx, position, span, structural_to_nominal, match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
inner_expected, ty) inner_expected, ty)
} }
_ => simple_error(&format!("`{}`", t), "raw pointer"), _ => simple_error(&format!("`{}`", t), "raw pointer"),
@ -464,19 +458,19 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
simple_error(&format!("non-simd type `{}`", t), "simd type"); simple_error(&format!("non-simd type `{}`", t), "simd type");
return; return;
} }
let t_len = t.simd_size(ccx.tcx); let t_len = t.simd_size(tcx);
if len as usize != t_len { if len as usize != t_len {
simple_error(&format!("vector with length {}", t_len), simple_error(&format!("vector with length {}", t_len),
&format!("length {}", len)); &format!("length {}", len));
return; return;
} }
let t_ty = t.simd_type(ccx.tcx); let t_ty = t.simd_type(tcx);
{ {
// check that a given structural type always has the same an intrinsic definition // check that a given structural type always has the same an intrinsic definition
let previous = structural_to_nominal.entry(expected).or_insert(t); let previous = structural_to_nominal.entry(expected).or_insert(t);
if *previous != t { if *previous != t {
// this gets its own error code because it is non-trivial // this gets its own error code because it is non-trivial
span_err!(ccx.tcx.sess, span, E0443, span_err!(tcx.sess, span, E0443,
"intrinsic {} has wrong type: found `{}`, expected `{}` which \ "intrinsic {} has wrong type: found `{}`, expected `{}` which \
was used for this vector type previously in this signature", was used for this vector type previously in this signature",
position, position,
@ -485,7 +479,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
return; return;
} }
} }
match_intrinsic_type_to_type(ccx, match_intrinsic_type_to_type(tcx,
position, position,
span, span,
structural_to_nominal, structural_to_nominal,
@ -501,7 +495,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
return return
} }
for (e, c) in expected_contents.iter().zip(contents) { for (e, c) in expected_contents.iter().zip(contents) {
match_intrinsic_type_to_type(ccx, position, span, structural_to_nominal, match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
e, c) e, c)
} }
} }

View file

@ -566,7 +566,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// Disallow calls to the method `drop` defined in the `Drop` trait. // Disallow calls to the method `drop` defined in the `Drop` trait.
match pick.item.container { match pick.item.container {
ty::TraitContainer(trait_def_id) => { ty::TraitContainer(trait_def_id) => {
callee::check_legal_trait_for_method_call(self.ccx, self.span, trait_def_id) callee::check_legal_trait_for_method_call(self.tcx, self.span, trait_def_id)
} }
ty::ImplContainer(..) => {} ty::ImplContainer(..) => {}
} }

View file

@ -653,7 +653,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> { fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> {
let mut duplicates = FxHashSet(); let mut duplicates = FxHashSet();
for trait_info in suggest::all_traits(self.ccx) { for trait_info in suggest::all_traits(self.tcx) {
if duplicates.insert(trait_info.def_id) { if duplicates.insert(trait_info.def_id) {
self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?; self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?;
} }

View file

@ -11,11 +11,9 @@
//! Give useful errors and suggestions to users when an item can't be //! Give useful errors and suggestions to users when an item can't be
//! found or is otherwise invalid. //! found or is otherwise invalid.
use CrateCtxt;
use check::FnCtxt; use check::FnCtxt;
use rustc::hir::map as hir_map; use rustc::hir::map as hir_map;
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable}; use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
use hir::def::Def; use hir::def::Def;
use hir::def_id::{CRATE_DEF_INDEX, DefId}; use hir::def_id::{CRATE_DEF_INDEX, DefId};
use middle::lang_items::FnOnceTraitLangItem; use middle::lang_items::FnOnceTraitLangItem;
@ -343,7 +341,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// there's no implemented traits, so lets suggest some traits to // there's no implemented traits, so lets suggest some traits to
// implement, by finding ones that have the item name, and are // implement, by finding ones that have the item name, and are
// legal to implement. // legal to implement.
let mut candidates = all_traits(self.ccx) let mut candidates = all_traits(self.tcx)
.filter(|info| { .filter(|info| {
// we approximate the coherence rules to only suggest // we approximate the coherence rules to only suggest
// traits that are legal to implement by requiring that // traits that are legal to implement by requiring that
@ -423,7 +421,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub type AllTraitsVec = Vec<TraitInfo>; pub type AllTraitsVec = Vec<DefId>;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct TraitInfo { pub struct TraitInfo {
@ -458,8 +456,8 @@ impl Ord for TraitInfo {
} }
/// Retrieve all traits in this crate and any dependent crates. /// Retrieve all traits in this crate and any dependent crates.
pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> {
if ccx.all_traits.borrow().is_none() { if tcx.all_traits.borrow().is_none() {
use rustc::hir::itemlikevisit; use rustc::hir::itemlikevisit;
let mut traits = vec![]; let mut traits = vec![];
@ -476,7 +474,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
match i.node { match i.node {
hir::ItemTrait(..) => { hir::ItemTrait(..) => {
let def_id = self.map.local_def_id(i.id); let def_id = self.map.local_def_id(i.id);
self.traits.push(TraitInfo::new(def_id)); self.traits.push(def_id);
} }
_ => {} _ => {}
} }
@ -488,45 +486,45 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
} }
} }
ccx.tcx.hir.krate().visit_all_item_likes(&mut Visitor { tcx.hir.krate().visit_all_item_likes(&mut Visitor {
map: &ccx.tcx.hir, map: &tcx.hir,
traits: &mut traits, traits: &mut traits,
}); });
// Cross-crate: // Cross-crate:
let mut external_mods = FxHashSet(); let mut external_mods = FxHashSet();
fn handle_external_def(ccx: &CrateCtxt, fn handle_external_def(tcx: TyCtxt,
traits: &mut AllTraitsVec, traits: &mut AllTraitsVec,
external_mods: &mut FxHashSet<DefId>, external_mods: &mut FxHashSet<DefId>,
def: Def) { def: Def) {
let def_id = def.def_id(); let def_id = def.def_id();
match def { match def {
Def::Trait(..) => { Def::Trait(..) => {
traits.push(TraitInfo::new(def_id)); traits.push(def_id);
} }
Def::Mod(..) => { Def::Mod(..) => {
if !external_mods.insert(def_id) { if !external_mods.insert(def_id) {
return; return;
} }
for child in ccx.tcx.sess.cstore.item_children(def_id) { for child in tcx.sess.cstore.item_children(def_id) {
handle_external_def(ccx, traits, external_mods, child.def) handle_external_def(tcx, traits, external_mods, child.def)
} }
} }
_ => {} _ => {}
} }
} }
for cnum in ccx.tcx.sess.cstore.crates() { for cnum in tcx.sess.cstore.crates() {
let def_id = DefId { let def_id = DefId {
krate: cnum, krate: cnum,
index: CRATE_DEF_INDEX, index: CRATE_DEF_INDEX,
}; };
handle_external_def(ccx, &mut traits, &mut external_mods, Def::Mod(def_id)); handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id));
} }
*ccx.all_traits.borrow_mut() = Some(traits); *tcx.all_traits.borrow_mut() = Some(traits);
} }
let borrow = ccx.all_traits.borrow(); let borrow = tcx.all_traits.borrow();
assert!(borrow.is_some()); assert!(borrow.is_some());
AllTraits { AllTraits {
borrow: borrow, borrow: borrow,
@ -547,7 +545,7 @@ impl<'a> Iterator for AllTraits<'a> {
// ugh. // ugh.
borrow.as_ref().unwrap().get(*idx).map(|info| { borrow.as_ref().unwrap().get(*idx).map(|info| {
*idx += 1; *idx += 1;
*info TraitInfo::new(*info)
}) })
} }
} }

View file

@ -56,7 +56,7 @@ stored in `fcx.node_types` and `fcx.item_substs`. These types
may contain unresolved type variables. After type checking is may contain unresolved type variables. After type checking is
complete, the functions in the writeback module are used to take the complete, the functions in the writeback module are used to take the
types from this table, resolve them, and then write them into their types from this table, resolve them, and then write them into their
permanent home in the type context `ccx.tcx`. permanent home in the type context `tcx`.
This means that during inferencing you should use `fcx.write_ty()` This means that during inferencing you should use `fcx.write_ty()`
and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
@ -98,7 +98,6 @@ use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
use rustc::ty::util::{Representability, IntTypeExt}; use rustc::ty::util::{Representability, IntTypeExt};
use require_c_abi_if_variadic; use require_c_abi_if_variadic;
use session::{Session, CompileResult}; use session::{Session, CompileResult};
use CrateCtxt;
use TypeAndSubsts; use TypeAndSubsts;
use lint; use lint;
use util::common::{ErrorReported, indenter}; use util::common::{ErrorReported, indenter};
@ -154,8 +153,8 @@ mod op;
/// `bar()` will each have their own `FnCtxt`, but they will /// `bar()` will each have their own `FnCtxt`, but they will
/// share the inherited fields. /// share the inherited fields.
pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
ccx: &'a CrateCtxt<'a, 'gcx>,
infcx: InferCtxt<'a, 'gcx, 'tcx>, infcx: InferCtxt<'a, 'gcx, 'tcx>,
locals: RefCell<NodeMap<Ty<'tcx>>>, locals: RefCell<NodeMap<Ty<'tcx>>>,
fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>, fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
@ -474,22 +473,20 @@ impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
/// Helper type of a temporary returned by ccx.inherited(...). /// Helper type of a temporary returned by Inherited::build(...).
/// Necessary because we can't write the following bound: /// Necessary because we can't write the following bound:
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>). /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>).
pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
ccx: &'a CrateCtxt<'a, 'gcx>,
infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx> infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>
} }
impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
pub fn inherited(&'a self, id: ast::NodeId) pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId)
-> InheritedBuilder<'a, 'gcx, 'tcx> { -> InheritedBuilder<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty(); let tables = ty::TypeckTables::empty();
let param_env = ParameterEnvironment::for_item(self.tcx, id); let param_env = ParameterEnvironment::for_item(tcx, id);
InheritedBuilder { InheritedBuilder {
ccx: self, infcx: tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable)
infcx: self.tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable)
} }
} }
} }
@ -498,17 +495,13 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
fn enter<F, R>(&'tcx mut self, f: F) -> R fn enter<F, R>(&'tcx mut self, f: F) -> R
where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
{ {
let ccx = self.ccx; self.infcx.enter(|infcx| f(Inherited::new(infcx)))
self.infcx.enter(|infcx| f(Inherited::new(ccx, infcx)))
} }
} }
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
pub fn new(ccx: &'a CrateCtxt<'a, 'gcx>, pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
infcx: InferCtxt<'a, 'gcx, 'tcx>)
-> Self {
Inherited { Inherited {
ccx: ccx,
infcx: infcx, infcx: infcx,
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
locals: RefCell::new(NodeMap()), locals: RefCell::new(NodeMap()),
@ -536,23 +529,23 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
} }
struct CheckItemTypesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::OnlyBodies(&self.ccx.tcx.hir) NestedVisitorMap::OnlyBodies(&self.tcx.hir)
} }
fn visit_item(&mut self, i: &'tcx hir::Item) { fn visit_item(&mut self, i: &'tcx hir::Item) {
check_item_type(self.ccx, i); check_item_type(self.tcx, i);
intravisit::walk_item(self, i); intravisit::walk_item(self, i);
} }
fn visit_ty(&mut self, t: &'tcx hir::Ty) { fn visit_ty(&mut self, t: &'tcx hir::Ty) {
match t.node { match t.node {
hir::TyArray(_, length) => { hir::TyArray(_, length) => {
check_const_with_type(self.ccx, length, self.ccx.tcx.types.usize, length.node_id); check_const_with_type(self.tcx, length, self.tcx.types.usize, length.node_id);
} }
_ => {} _ => {}
} }
@ -563,7 +556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx hir::Expr) { fn visit_expr(&mut self, e: &'tcx hir::Expr) {
match e.node { match e.node {
hir::ExprRepeat(_, count) => { hir::ExprRepeat(_, count) => {
check_const_with_type(self.ccx, count, self.ccx.tcx.types.usize, count.node_id); check_const_with_type(self.tcx, count, self.tcx.types.usize, count.node_id);
} }
_ => {} _ => {}
} }
@ -576,7 +569,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) { fn visit_item(&mut self, item: &'tcx hir::Item) {
match item.node { match item.node {
hir::ItemFn(ref decl, .., body_id) => { hir::ItemFn(ref decl, .., body_id) => {
check_bare_fn(self.ccx, &decl, body_id, item.id, item.span); check_bare_fn(self.tcx, &decl, body_id, item.id, item.span);
} }
_ => { } _ => { }
} }
@ -585,10 +578,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
match trait_item.node { match trait_item.node {
hir::TraitItemKind::Const(_, Some(expr)) => { hir::TraitItemKind::Const(_, Some(expr)) => {
check_const(self.ccx, expr, trait_item.id) check_const(self.tcx, expr, trait_item.id)
} }
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => { hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => {
check_bare_fn(self.ccx, &sig.decl, body_id, trait_item.id, trait_item.span); check_bare_fn(self.tcx, &sig.decl, body_id, trait_item.id, trait_item.span);
} }
hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) |
hir::TraitItemKind::Const(_, None) | hir::TraitItemKind::Const(_, None) |
@ -601,10 +594,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
match impl_item.node { match impl_item.node {
hir::ImplItemKind::Const(_, expr) => { hir::ImplItemKind::Const(_, expr) => {
check_const(self.ccx, expr, impl_item.id) check_const(self.tcx, expr, impl_item.id)
} }
hir::ImplItemKind::Method(ref sig, body_id) => { hir::ImplItemKind::Method(ref sig, body_id) => {
check_bare_fn(self.ccx, &sig.decl, body_id, impl_item.id, impl_item.span); check_bare_fn(self.tcx, &sig.decl, body_id, impl_item.id, impl_item.span);
} }
hir::ImplItemKind::Type(_) => { hir::ImplItemKind::Type(_) => {
// Nothing to do here. // Nothing to do here.
@ -613,35 +606,35 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
} }
} }
pub fn check_wf_new(ccx: &CrateCtxt) -> CompileResult { pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
ccx.tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx); let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
ccx.tcx.visit_all_item_likes_in_krate(DepNode::WfCheck, &mut visit.as_deep_visitor()); tcx.visit_all_item_likes_in_krate(DepNode::WfCheck, &mut visit.as_deep_visitor());
}) })
} }
pub fn check_item_types(ccx: &CrateCtxt) -> CompileResult { pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
ccx.tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
let mut visit = CheckItemTypesVisitor { ccx: ccx }; let mut visit = CheckItemTypesVisitor { tcx: tcx };
ccx.tcx.visit_all_item_likes_in_krate(DepNode::TypeckItemType, tcx.visit_all_item_likes_in_krate(DepNode::TypeckItemType,
&mut visit.as_deep_visitor()); &mut visit.as_deep_visitor());
}) })
} }
pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult { pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
ccx.tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
let mut visit = CheckItemBodiesVisitor { ccx: ccx }; let mut visit = CheckItemBodiesVisitor { tcx: tcx };
ccx.tcx.visit_all_item_likes_in_krate(DepNode::TypeckTables, &mut visit); tcx.visit_all_item_likes_in_krate(DepNode::TypeckTables, &mut visit);
// Process deferred obligations, now that all functions // Process deferred obligations, now that all functions
// bodies have been fully inferred. // bodies have been fully inferred.
for (&item_id, obligations) in ccx.deferred_obligations.borrow().iter() { for (&item_id, obligations) in tcx.deferred_obligations.borrow().iter() {
// Use the same DepNode as for the body of the original function/item. // Use the same DepNode as for the body of the original function/item.
let def_id = ccx.tcx.hir.local_def_id(item_id); let def_id = tcx.hir.local_def_id(item_id);
let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeckTables(def_id)); let _task = tcx.dep_graph.in_task(DepNode::TypeckTables(def_id));
let param_env = ParameterEnvironment::for_item(ccx.tcx, item_id); let param_env = ParameterEnvironment::for_item(tcx, item_id);
ccx.tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| {
let mut fulfillment_cx = traits::FulfillmentContext::new(); let mut fulfillment_cx = traits::FulfillmentContext::new();
for obligation in obligations.iter().map(|o| o.to_obligation()) { for obligation in obligations.iter().map(|o| o.to_obligation()) {
fulfillment_cx.register_predicate_obligation(&infcx, obligation); fulfillment_cx.register_predicate_obligation(&infcx, obligation);
@ -655,19 +648,19 @@ pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult {
}) })
} }
pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult { pub fn check_drop_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
ccx.tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
let _task = ccx.tcx.dep_graph.in_task(DepNode::Dropck); let _task = tcx.dep_graph.in_task(DepNode::Dropck);
let drop_trait = match ccx.tcx.lang_items.drop_trait() { let drop_trait = match tcx.lang_items.drop_trait() {
Some(id) => ccx.tcx.lookup_trait_def(id), None => { return } Some(id) => tcx.lookup_trait_def(id), None => { return }
}; };
drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| { drop_trait.for_each_impl(tcx, |drop_impl_did| {
let _task = ccx.tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did)); let _task = tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did));
if drop_impl_did.is_local() { if drop_impl_did.is_local() {
match dropck::check_drop_impl(ccx, drop_impl_did) { match dropck::check_drop_impl(tcx, drop_impl_did) {
Ok(()) => {} Ok(()) => {}
Err(()) => { Err(()) => {
assert!(ccx.tcx.sess.has_errors()); assert!(tcx.sess.has_errors());
} }
} }
} }
@ -675,22 +668,22 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
}) })
} }
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_bare_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body_id: hir::BodyId, body_id: hir::BodyId,
fn_id: ast::NodeId, fn_id: ast::NodeId,
span: Span) { span: Span) {
let body = ccx.tcx.hir.body(body_id); let body = tcx.hir.body(body_id);
let raw_fty = ccx.tcx.item_type(ccx.tcx.hir.local_def_id(fn_id)); let raw_fty = tcx.item_type(tcx.hir.local_def_id(fn_id));
let fn_ty = match raw_fty.sty { let fn_ty = match raw_fty.sty {
ty::TyFnDef(.., f) => f, ty::TyFnDef(.., f) => f,
_ => span_bug!(body.value.span, "check_bare_fn: function type expected") _ => span_bug!(body.value.span, "check_bare_fn: function type expected")
}; };
check_abi(ccx, span, fn_ty.abi); check_abi(tcx, span, fn_ty.abi);
ccx.inherited(fn_id).enter(|inh| { Inherited::build(tcx, fn_id).enter(|inh| {
// Compute the fty from point of view of inside fn. // Compute the fty from point of view of inside fn.
let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id); let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id);
let fn_sig = let fn_sig =
@ -713,9 +706,9 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}); });
} }
fn check_abi<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, abi: Abi) { fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) {
if !ccx.tcx.sess.target.target.is_abi_supported(abi) { if !tcx.sess.target.target.is_abi_supported(abi) {
struct_span_err!(ccx.tcx.sess, span, E0570, struct_span_err!(tcx.sess, span, E0570,
"The ABI `{}` is not supported for the current target", abi).emit() "The ABI `{}` is not supported for the current target", abi).emit()
} }
} }
@ -837,30 +830,34 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fcx fcx
} }
fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let def_id = ccx.tcx.hir.local_def_id(id); id: ast::NodeId,
check_representable(ccx.tcx, span, def_id); span: Span) {
let def_id = tcx.hir.local_def_id(id);
check_representable(tcx, span, def_id);
if ccx.tcx.lookup_simd(def_id) { if tcx.lookup_simd(def_id) {
check_simd(ccx.tcx, span, def_id); check_simd(tcx, span, def_id);
} }
} }
fn check_union(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
check_representable(ccx.tcx, span, ccx.tcx.hir.local_def_id(id)); id: ast::NodeId,
span: Span) {
check_representable(tcx, span, tcx.hir.local_def_id(id));
} }
pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) {
debug!("check_item_type(it.id={}, it.name={})", debug!("check_item_type(it.id={}, it.name={})",
it.id, it.id,
ccx.tcx.item_path_str(ccx.tcx.hir.local_def_id(it.id))); tcx.item_path_str(tcx.hir.local_def_id(it.id)));
let _indenter = indenter(); let _indenter = indenter();
match it.node { match it.node {
// Consts can play a role in type-checking, so they are included here. // Consts can play a role in type-checking, so they are included here.
hir::ItemStatic(.., e) | hir::ItemStatic(.., e) |
hir::ItemConst(_, e) => check_const(ccx, e, it.id), hir::ItemConst(_, e) => check_const(tcx, e, it.id),
hir::ItemEnum(ref enum_definition, _) => { hir::ItemEnum(ref enum_definition, _) => {
check_enum_variants(ccx, check_enum_variants(tcx,
it.span, it.span,
&enum_definition.variants, &enum_definition.variants,
it.id); it.id);
@ -868,48 +865,48 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
hir::ItemFn(..) => {} // entirely within check_item_body hir::ItemFn(..) => {} // entirely within check_item_body
hir::ItemImpl(.., ref impl_item_refs) => { hir::ItemImpl(.., ref impl_item_refs) => {
debug!("ItemImpl {} with id {}", it.name, it.id); debug!("ItemImpl {} with id {}", it.name, it.id);
let impl_def_id = ccx.tcx.hir.local_def_id(it.id); let impl_def_id = tcx.hir.local_def_id(it.id);
if let Some(impl_trait_ref) = ccx.tcx.impl_trait_ref(impl_def_id) { if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
check_impl_items_against_trait(ccx, check_impl_items_against_trait(tcx,
it.span, it.span,
impl_def_id, impl_def_id,
impl_trait_ref, impl_trait_ref,
impl_item_refs); impl_item_refs);
let trait_def_id = impl_trait_ref.def_id; let trait_def_id = impl_trait_ref.def_id;
check_on_unimplemented(ccx, trait_def_id, it); check_on_unimplemented(tcx, trait_def_id, it);
} }
} }
hir::ItemTrait(..) => { hir::ItemTrait(..) => {
let def_id = ccx.tcx.hir.local_def_id(it.id); let def_id = tcx.hir.local_def_id(it.id);
check_on_unimplemented(ccx, def_id, it); check_on_unimplemented(tcx, def_id, it);
} }
hir::ItemStruct(..) => { hir::ItemStruct(..) => {
check_struct(ccx, it.id, it.span); check_struct(tcx, it.id, it.span);
} }
hir::ItemUnion(..) => { hir::ItemUnion(..) => {
check_union(ccx, it.id, it.span); check_union(tcx, it.id, it.span);
} }
hir::ItemTy(_, ref generics) => { hir::ItemTy(_, ref generics) => {
let def_id = ccx.tcx.hir.local_def_id(it.id); let def_id = tcx.hir.local_def_id(it.id);
let pty_ty = ccx.tcx.item_type(def_id); let pty_ty = tcx.item_type(def_id);
check_bounds_are_used(ccx, generics, pty_ty); check_bounds_are_used(tcx, generics, pty_ty);
} }
hir::ItemForeignMod(ref m) => { hir::ItemForeignMod(ref m) => {
check_abi(ccx, it.span, m.abi); check_abi(tcx, it.span, m.abi);
if m.abi == Abi::RustIntrinsic { if m.abi == Abi::RustIntrinsic {
for item in &m.items { for item in &m.items {
intrinsic::check_intrinsic_type(ccx, item); intrinsic::check_intrinsic_type(tcx, item);
} }
} else if m.abi == Abi::PlatformIntrinsic { } else if m.abi == Abi::PlatformIntrinsic {
for item in &m.items { for item in &m.items {
intrinsic::check_platform_intrinsic_type(ccx, item); intrinsic::check_platform_intrinsic_type(tcx, item);
} }
} else { } else {
for item in &m.items { for item in &m.items {
let generics = ccx.tcx.item_generics(ccx.tcx.hir.local_def_id(item.id)); let generics = tcx.item_generics(tcx.hir.local_def_id(item.id));
if !generics.types.is_empty() { if !generics.types.is_empty() {
let mut err = struct_span_err!(ccx.tcx.sess, item.span, E0044, let mut err = struct_span_err!(tcx.sess, item.span, E0044,
"foreign items may not have type parameters"); "foreign items may not have type parameters");
span_help!(&mut err, item.span, span_help!(&mut err, item.span,
"consider using specialization instead of \ "consider using specialization instead of \
@ -918,7 +915,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
} }
if let hir::ForeignItemFn(ref fn_decl, _, _) = item.node { if let hir::ForeignItemFn(ref fn_decl, _, _) = item.node {
require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span); require_c_abi_if_variadic(tcx, fn_decl, m.abi, item.span);
} }
} }
} }
@ -927,10 +924,10 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
} }
} }
fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId, def_id: DefId,
item: &hir::Item) { item: &hir::Item) {
let generics = ccx.tcx.item_generics(def_id); let generics = tcx.item_generics(def_id);
if let Some(ref attr) = item.attrs.iter().find(|a| { if let Some(ref attr) = item.attrs.iter().find(|a| {
a.check_name("rustc_on_unimplemented") a.check_name("rustc_on_unimplemented")
}) { }) {
@ -950,8 +947,8 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}) { }) {
Some(_) => (), Some(_) => (),
None => { None => {
let name = ccx.tcx.item_name(def_id); let name = tcx.item_name(def_id);
span_err!(ccx.tcx.sess, attr.span, E0230, span_err!(tcx.sess, attr.span, E0230,
"there is no type parameter \ "there is no type parameter \
{} on trait {}", {} on trait {}",
s, name); s, name);
@ -959,7 +956,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}, },
// `{:1}` and `{}` are not to be used // `{:1}` and `{}` are not to be used
Position::ArgumentIs(_) => { Position::ArgumentIs(_) => {
span_err!(ccx.tcx.sess, attr.span, E0231, span_err!(tcx.sess, attr.span, E0231,
"only named substitution \ "only named substitution \
parameters are allowed"); parameters are allowed");
} }
@ -968,7 +965,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} }
} else { } else {
struct_span_err!( struct_span_err!(
ccx.tcx.sess, attr.span, E0232, tcx.sess, attr.span, E0232,
"this attribute must have a value") "this attribute must have a value")
.span_label(attr.span, &format!("attribute requires a value")) .span_label(attr.span, &format!("attribute requires a value"))
.note(&format!("eg `#[rustc_on_unimplemented = \"foo\"]`")) .note(&format!("eg `#[rustc_on_unimplemented = \"foo\"]`"))
@ -1026,7 +1023,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_span: Span, impl_span: Span,
impl_id: DefId, impl_id: DefId,
impl_trait_ref: ty::TraitRef<'tcx>, impl_trait_ref: ty::TraitRef<'tcx>,
@ -1037,11 +1034,10 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
if impl_trait_ref.references_error() { return; } if impl_trait_ref.references_error() { return; }
// Locate trait definition and items // Locate trait definition and items
let tcx = ccx.tcx;
let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id); let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id);
let mut overridden_associated_type = None; let mut overridden_associated_type = None;
let impl_items = || impl_item_refs.iter().map(|iiref| ccx.tcx.hir.impl_item(iiref.id)); let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir.impl_item(iiref.id));
// Check existing impl methods to see if they are both present in trait // Check existing impl methods to see if they are both present in trait
// and compatible with trait signature // and compatible with trait signature
@ -1056,7 +1052,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
hir::ImplItemKind::Const(..) => { hir::ImplItemKind::Const(..) => {
// Find associated const definition. // Find associated const definition.
if ty_trait_item.kind == ty::AssociatedKind::Const { if ty_trait_item.kind == ty::AssociatedKind::Const {
compare_const_impl(ccx, compare_const_impl(tcx,
&ty_impl_item, &ty_impl_item,
impl_item.span, impl_item.span,
&ty_trait_item, &ty_trait_item,
@ -1080,7 +1076,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let trait_span = tcx.hir.span_if_local(ty_trait_item.def_id); let trait_span = tcx.hir.span_if_local(ty_trait_item.def_id);
if ty_trait_item.kind == ty::AssociatedKind::Method { if ty_trait_item.kind == ty::AssociatedKind::Method {
let err_count = tcx.sess.err_count(); let err_count = tcx.sess.err_count();
compare_impl_method(ccx, compare_impl_method(tcx,
&ty_impl_item, &ty_impl_item,
impl_item.span, impl_item.span,
body_id.node_id, body_id.node_id,
@ -1090,7 +1086,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
true); // start with old-broken-mode true); // start with old-broken-mode
if err_count == tcx.sess.err_count() { if err_count == tcx.sess.err_count() {
// old broken mode did not report an error. Try with the new mode. // old broken mode did not report an error. Try with the new mode.
compare_impl_method(ccx, compare_impl_method(tcx,
&ty_impl_item, &ty_impl_item,
impl_item.span, impl_item.span,
body_id.node_id, body_id.node_id,
@ -1203,12 +1199,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} }
/// Checks a constant with a given type. /// Checks a constant with a given type.
fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fn check_const_with_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
body: hir::BodyId, body: hir::BodyId,
expected_type: Ty<'tcx>, expected_type: Ty<'tcx>,
id: ast::NodeId) { id: ast::NodeId) {
let body = ccx.tcx.hir.body(body); let body = tcx.hir.body(body);
ccx.inherited(id).enter(|inh| { Inherited::build(tcx, id).enter(|inh| {
let fcx = FnCtxt::new(&inh, None, body.value.id); let fcx = FnCtxt::new(&inh, None, body.value.id);
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
@ -1231,11 +1227,11 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
}); });
} }
fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn check_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
body: hir::BodyId, body: hir::BodyId,
id: ast::NodeId) { id: ast::NodeId) {
let decl_ty = ccx.tcx.item_type(ccx.tcx.hir.local_def_id(id)); let decl_ty = tcx.item_type(tcx.hir.local_def_id(id));
check_const_with_type(ccx, body, decl_ty, id); check_const_with_type(tcx, body, decl_ty, id);
} }
/// Checks whether a type can be represented in memory. In particular, it /// Checks whether a type can be represented in memory. In particular, it
@ -1293,53 +1289,53 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
} }
#[allow(trivial_numeric_casts)] #[allow(trivial_numeric_casts)]
pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, pub fn check_enum_variants<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
sp: Span, sp: Span,
vs: &'tcx [hir::Variant], vs: &'tcx [hir::Variant],
id: ast::NodeId) { id: ast::NodeId) {
let def_id = ccx.tcx.hir.local_def_id(id); let def_id = tcx.hir.local_def_id(id);
let hint = *ccx.tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny); let hint = *tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny);
if hint != attr::ReprAny && vs.is_empty() { if hint != attr::ReprAny && vs.is_empty() {
struct_span_err!( struct_span_err!(
ccx.tcx.sess, sp, E0084, tcx.sess, sp, E0084,
"unsupported representation for zero-variant enum") "unsupported representation for zero-variant enum")
.span_label(sp, &format!("unsupported enum representation")) .span_label(sp, &format!("unsupported enum representation"))
.emit(); .emit();
} }
let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx); let repr_type_ty = tcx.enum_repr_type(Some(&hint)).to_ty(tcx);
if repr_type_ty == ccx.tcx.types.i128 || repr_type_ty == ccx.tcx.types.u128 { if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
if !ccx.tcx.sess.features.borrow().i128_type { if !tcx.sess.features.borrow().i128_type {
emit_feature_err(&ccx.tcx.sess.parse_sess, emit_feature_err(&tcx.sess.parse_sess,
"i128_type", sp, GateIssue::Language, "128-bit type is unstable"); "i128_type", sp, GateIssue::Language, "128-bit type is unstable");
} }
} }
for v in vs { for v in vs {
if let Some(e) = v.node.disr_expr { if let Some(e) = v.node.disr_expr {
check_const_with_type(ccx, e, repr_type_ty, e.node_id); check_const_with_type(tcx, e, repr_type_ty, e.node_id);
} }
} }
let def_id = ccx.tcx.hir.local_def_id(id); let def_id = tcx.hir.local_def_id(id);
let def = ccx.tcx.lookup_adt_def(def_id); let def = tcx.lookup_adt_def(def_id);
let mut disr_vals: Vec<ConstInt> = Vec::new(); let mut disr_vals: Vec<ConstInt> = Vec::new();
for (discr, v) in def.discriminants(ccx.tcx).zip(vs) { for (discr, v) in def.discriminants(tcx).zip(vs) {
// Check for duplicate discriminant values // Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x == discr) { if let Some(i) = disr_vals.iter().position(|&x| x == discr) {
let variant_i_node_id = ccx.tcx.hir.as_local_node_id(def.variants[i].did).unwrap(); let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap();
let variant_i = ccx.tcx.hir.expect_variant(variant_i_node_id); let variant_i = tcx.hir.expect_variant(variant_i_node_id);
let i_span = match variant_i.node.disr_expr { let i_span = match variant_i.node.disr_expr {
Some(expr) => ccx.tcx.hir.span(expr.node_id), Some(expr) => tcx.hir.span(expr.node_id),
None => ccx.tcx.hir.span(variant_i_node_id) None => tcx.hir.span(variant_i_node_id)
}; };
let span = match v.node.disr_expr { let span = match v.node.disr_expr {
Some(expr) => ccx.tcx.hir.span(expr.node_id), Some(expr) => tcx.hir.span(expr.node_id),
None => v.span None => v.span
}; };
struct_span_err!(ccx.tcx.sess, span, E0081, struct_span_err!(tcx.sess, span, E0081,
"discriminant value `{}` already exists", disr_vals[i]) "discriminant value `{}` already exists", disr_vals[i])
.span_label(i_span, &format!("first use of `{}`", disr_vals[i])) .span_label(i_span, &format!("first use of `{}`", disr_vals[i]))
.span_label(span , &format!("enum already has `{}`", disr_vals[i])) .span_label(span , &format!("enum already has `{}`", disr_vals[i]))
@ -1348,7 +1344,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
disr_vals.push(discr); disr_vals.push(discr);
} }
check_representable(ccx.tcx, sp, def_id); check_representable(tcx, sp, def_id);
} }
impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
@ -1504,10 +1500,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
&self.parameter_environment
}
pub fn sess(&self) -> &Session { pub fn sess(&self) -> &Session {
&self.tcx.sess &self.tcx.sess
} }
@ -1754,10 +1746,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.write_ty(node_id, self.tcx.mk_nil()); self.write_ty(node_id, self.tcx.mk_nil());
} }
pub fn write_never(&self, node_id: ast::NodeId) {
self.write_ty(node_id, self.tcx.types.never);
}
pub fn write_error(&self, node_id: ast::NodeId) { pub fn write_error(&self, node_id: ast::NodeId) {
self.write_ty(node_id, self.tcx.types.err); self.write_ty(node_id, self.tcx.types.err);
} }
@ -4303,7 +4291,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let container = self.tcx.associated_item(def_id).container; let container = self.tcx.associated_item(def_id).container;
match container { match container {
ty::TraitContainer(trait_did) => { ty::TraitContainer(trait_did) => {
callee::check_legal_trait_for_method_call(self.ccx, span, trait_did) callee::check_legal_trait_for_method_call(self.tcx, span, trait_did)
} }
ty::ImplContainer(_) => {} ty::ImplContainer(_) => {}
} }
@ -4624,7 +4612,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
generics: &hir::Generics, generics: &hir::Generics,
ty: Ty<'tcx>) { ty: Ty<'tcx>) {
debug!("check_bounds_are_used(n_tps={}, ty={:?})", debug!("check_bounds_are_used(n_tps={}, ty={:?})",
@ -4643,7 +4631,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
for (&used, param) in tps_used.iter().zip(&generics.ty_params) { for (&used, param) in tps_used.iter().zip(&generics.ty_params) {
if !used { if !used {
struct_span_err!(ccx.tcx.sess, param.span, E0091, struct_span_err!(tcx.sess, param.span, E0091,
"type parameter `{}` is unused", "type parameter `{}` is unused",
param.name) param.name)
.span_label(param.span, &format!("unused type parameter")) .span_label(param.span, &format!("unused type parameter"))

View file

@ -102,8 +102,6 @@ use syntax_pos::Span;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, PatKind}; use rustc::hir::{self, PatKind};
use self::SubjectNode::Subject;
// a variation on try that just returns unit // a variation on try that just returns unit
macro_rules! ignore_err { macro_rules! ignore_err {
($e:expr) => (match $e { Ok(e) => e, Err(_) => return () }) ($e:expr) => (match $e { Ok(e) => e, Err(_) => return () })
@ -183,7 +181,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
repeating_scope: ast::NodeId, repeating_scope: ast::NodeId,
// id of AST node being analyzed (the subject of the analysis). // id of AST node being analyzed (the subject of the analysis).
subject: SubjectNode, subject: ast::NodeId,
} }
@ -195,14 +193,13 @@ impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> {
} }
pub struct RepeatingScope(ast::NodeId); pub struct RepeatingScope(ast::NodeId);
pub enum SubjectNode { Subject(ast::NodeId), None } pub struct Subject(ast::NodeId);
impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
pub fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, pub fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
initial_repeating_scope: RepeatingScope, RepeatingScope(initial_repeating_scope): RepeatingScope,
initial_body_id: ast::NodeId, initial_body_id: ast::NodeId,
subject: SubjectNode) -> RegionCtxt<'a, 'gcx, 'tcx> { Subject(subject): Subject) -> RegionCtxt<'a, 'gcx, 'tcx> {
let RepeatingScope(initial_repeating_scope) = initial_repeating_scope;
RegionCtxt { RegionCtxt {
fcx: fcx, fcx: fcx,
repeating_scope: initial_repeating_scope, repeating_scope: initial_repeating_scope,
@ -416,13 +413,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
} }
fn resolve_regions_and_report_errors(&self) { fn resolve_regions_and_report_errors(&self) {
let subject_node_id = match self.subject { let subject_node_id = self.subject;
Subject(s) => s,
SubjectNode::None => {
bug!("cannot resolve_regions_and_report_errors \
without subject node");
}
};
self.fcx.resolve_regions_and_report_errors(&self.free_region_map, self.fcx.resolve_regions_and_report_errors(&self.free_region_map,
subject_node_id); subject_node_id);

View file

@ -9,9 +9,8 @@
// except according to those terms. // except according to those terms.
use astconv::ExplicitSelf; use astconv::ExplicitSelf;
use check::FnCtxt; use check::{Inherited, FnCtxt};
use constrained_type_params::{identify_constrained_type_params, Parameter}; use constrained_type_params::{identify_constrained_type_params, Parameter};
use CrateCtxt;
use hir::def_id::DefId; use hir::def_id::DefId;
use middle::region::{CodeExtent}; use middle::region::{CodeExtent};
@ -27,8 +26,8 @@ use errors::DiagnosticBuilder;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir; use rustc::hir;
pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> { pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
ccx: &'ccx CrateCtxt<'ccx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
code: ObligationCauseCode<'tcx>, code: ObligationCauseCode<'tcx>,
} }
@ -51,9 +50,9 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
let id = self.id; let id = self.id;
let span = self.span; let span = self.span;
self.inherited.enter(|inh| { self.inherited.enter(|inh| {
let fcx = FnCtxt::new(&inh, Some(inh.ccx.tcx.types.never), id); let fcx = FnCtxt::new(&inh, None, id);
let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
ccx: fcx.ccx, tcx: fcx.tcx.global_tcx(),
code: code code: code
}); });
fcx.select_all_obligations_or_error(); fcx.select_all_obligations_or_error();
@ -62,19 +61,15 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
} }
} }
impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'gcx>) pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
-> CheckTypeWellFormedVisitor<'ccx, 'gcx> { -> CheckTypeWellFormedVisitor<'a, 'gcx> {
CheckTypeWellFormedVisitor { CheckTypeWellFormedVisitor {
ccx: ccx, tcx: tcx,
code: ObligationCauseCode::MiscObligation code: ObligationCauseCode::MiscObligation
} }
} }
fn tcx(&self) -> TyCtxt<'ccx, 'gcx, 'gcx> {
self.ccx.tcx
}
/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
/// well-formed, meaning that they do not require any constraints not declared in the struct /// well-formed, meaning that they do not require any constraints not declared in the struct
/// definition itself. For example, this definition would be illegal: /// definition itself. For example, this definition would be illegal:
@ -87,10 +82,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
/// the types first. /// the types first.
fn check_item_well_formed(&mut self, item: &hir::Item) { fn check_item_well_formed(&mut self, item: &hir::Item) {
let ccx = self.ccx; let tcx = self.tcx;
debug!("check_item_well_formed(it.id={}, it.name={})", debug!("check_item_well_formed(it.id={}, it.name={})",
item.id, item.id,
ccx.tcx.item_path_str(ccx.tcx.hir.local_def_id(item.id))); tcx.item_path_str(tcx.hir.local_def_id(item.id)));
match item.node { match item.node {
/// Right now we check that every default trait implementation /// Right now we check that every default trait implementation
@ -117,9 +112,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => { hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => {
// FIXME(#27579) what amount of WF checking do we need for neg impls? // FIXME(#27579) what amount of WF checking do we need for neg impls?
let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.hir.local_def_id(item.id)).unwrap(); let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) { if !tcx.trait_has_default_impl(trait_ref.def_id) {
error_192(ccx, item.span); error_192(tcx, item.span);
} }
} }
hir::ItemFn(.., body_id) => { hir::ItemFn(.., body_id) => {
@ -211,14 +206,14 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
} }
fn for_item<'tcx>(&self, item: &hir::Item) fn for_item<'tcx>(&self, item: &hir::Item)
-> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> { -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
self.for_id(item.id, item.span) self.for_id(item.id, item.span)
} }
fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
-> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> { -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
CheckWfFcxBuilder { CheckWfFcxBuilder {
inherited: self.ccx.inherited(id), inherited: Inherited::build(self.tcx, id),
code: self.code.clone(), code: self.code.clone(),
id: id, id: id,
span: span span: span
@ -270,7 +265,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
// //
// 3) that the trait definition does not have any type parameters // 3) that the trait definition does not have any type parameters
let predicates = self.tcx().item_predicates(trait_def_id); let predicates = self.tcx.item_predicates(trait_def_id);
// We must exclude the Self : Trait predicate contained by all // We must exclude the Self : Trait predicate contained by all
// traits. // traits.
@ -285,7 +280,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
} }
}); });
let has_ty_params = self.tcx().item_generics(trait_def_id).types.len() > 1; let has_ty_params = self.tcx.item_generics(trait_def_id).types.len() > 1;
// We use an if-else here, since the generics will also trigger // We use an if-else here, since the generics will also trigger
// an extraneous error message when we find predicates like // an extraneous error message when we find predicates like
@ -296,14 +291,14 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
// extraneous predicates created by things like // extraneous predicates created by things like
// an associated type inside the trait. // an associated type inside the trait.
let mut err = None; let mut err = None;
if !self.tcx().associated_item_def_ids(trait_def_id).is_empty() { if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() {
error_380(self.ccx, span); error_380(self.tcx, span);
} else if has_ty_params { } else if has_ty_params {
err = Some(struct_span_err!(self.tcx().sess, span, E0567, err = Some(struct_span_err!(self.tcx.sess, span, E0567,
"traits with auto impls (`e.g. impl \ "traits with auto impls (`e.g. impl \
Trait for ..`) can not have type parameters")); Trait for ..`) can not have type parameters"));
} else if has_predicates { } else if has_predicates {
err = Some(struct_span_err!(self.tcx().sess, span, E0568, err = Some(struct_span_err!(self.tcx.sess, span, E0568,
"traits with auto impls (`e.g. impl \ "traits with auto impls (`e.g. impl \
Trait for ..`) cannot have predicates")); Trait for ..`) cannot have predicates"));
} }
@ -321,9 +316,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
} }
fn check_trait(&mut self, item: &hir::Item) { fn check_trait(&mut self, item: &hir::Item) {
let trait_def_id = self.tcx().hir.local_def_id(item.id); let trait_def_id = self.tcx.hir.local_def_id(item.id);
if self.tcx().trait_has_default_impl(trait_def_id) { if self.tcx.trait_has_default_impl(trait_def_id) {
self.check_auto_trait(trait_def_id, item.span); self.check_auto_trait(trait_def_id, item.span);
} }
@ -514,15 +509,15 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
item: &hir::Item, item: &hir::Item,
ast_generics: &hir::Generics) ast_generics: &hir::Generics)
{ {
let item_def_id = self.tcx().hir.local_def_id(item.id); let item_def_id = self.tcx.hir.local_def_id(item.id);
let ty = self.tcx().item_type(item_def_id); let ty = self.tcx.item_type(item_def_id);
if self.tcx().has_error_field(ty) { if self.tcx.has_error_field(ty) {
return; return;
} }
let ty_predicates = self.tcx().item_predicates(item_def_id); let ty_predicates = self.tcx.item_predicates(item_def_id);
assert_eq!(ty_predicates.parent, None); assert_eq!(ty_predicates.parent, None);
let variances = self.tcx().item_variances(item_def_id); let variances = self.tcx.item_variances(item_def_id);
let mut constrained_parameters: FxHashSet<_> = let mut constrained_parameters: FxHashSet<_> =
variances.iter().enumerate() variances.iter().enumerate()
@ -555,15 +550,15 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
span: Span, span: Span,
param_name: ast::Name) param_name: ast::Name)
{ {
let mut err = error_392(self.ccx, span, param_name); let mut err = error_392(self.tcx, span, param_name);
let suggested_marker_id = self.tcx().lang_items.phantom_data(); let suggested_marker_id = self.tcx.lang_items.phantom_data();
match suggested_marker_id { match suggested_marker_id {
Some(def_id) => { Some(def_id) => {
err.help( err.help(
&format!("consider removing `{}` or using a marker such as `{}`", &format!("consider removing `{}` or using a marker such as `{}`",
param_name, param_name,
self.tcx().item_path_str(def_id))); self.tcx.item_path_str(def_id)));
} }
None => { None => {
// no lang items, no help! // no lang items, no help!
@ -595,7 +590,7 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
} }
} }
impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
NestedVisitorMap::None NestedVisitorMap::None
} }
@ -681,21 +676,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
fn error_192(ccx: &CrateCtxt, span: Span) { fn error_192(tcx: TyCtxt, span: Span) {
span_err!(ccx.tcx.sess, span, E0192, span_err!(tcx.sess, span, E0192,
"negative impls are only allowed for traits with \ "negative impls are only allowed for traits with \
default impls (e.g., `Send` and `Sync`)") default impls (e.g., `Send` and `Sync`)")
} }
fn error_380(ccx: &CrateCtxt, span: Span) { fn error_380(tcx: TyCtxt, span: Span) {
span_err!(ccx.tcx.sess, span, E0380, span_err!(tcx.sess, span, E0380,
"traits with default impls (`e.g. impl \ "traits with default impls (`e.g. impl \
Trait for ..`) must have no methods or associated items") Trait for ..`) must have no methods or associated items")
} }
fn error_392<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, param_name: ast::Name) fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast::Name)
-> DiagnosticBuilder<'tcx> { -> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(ccx.tcx.sess, span, E0392, let mut err = struct_span_err!(tcx.sess, span, E0392,
"parameter `{}` is never used", param_name); "parameter `{}` is never used", param_name);
err.span_label(span, &format!("unused type parameter")); err.span_label(span, &format!("unused type parameter"));
err err

View file

@ -491,7 +491,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}).collect(); }).collect();
if !obligations.is_empty() { if !obligations.is_empty() {
assert!(self.fcx.ccx.deferred_obligations.borrow_mut() assert!(self.fcx.tcx.deferred_obligations.borrow_mut()
.insert(item_id, obligations).is_none()); .insert(item_id, obligations).is_none());
} }
} }
@ -499,7 +499,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
fn visit_type_nodes(&self) { fn visit_type_nodes(&self) {
for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() { for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() {
let ty = self.resolve(ty, ResolvingTyNode(id)); let ty = self.resolve(ty, ResolvingTyNode(id));
self.fcx.ccx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty); self.fcx.tcx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty);
} }
} }

View file

@ -24,7 +24,6 @@ use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use rustc::ty::{TyUint, TyClosure, TyFnDef, TyFnPtr}; use rustc::ty::{TyUint, TyClosure, TyFnDef, TyFnPtr};
use rustc::ty::{TyProjection, TyAnon}; use rustc::ty::{TyProjection, TyAnon};
use CrateCtxt;
use syntax_pos::Span; use syntax_pos::Span;
use rustc::dep_graph::DepNode; use rustc::dep_graph::DepNode;
use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::itemlikevisit::ItemLikeVisitor;
@ -176,12 +175,12 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def
err.emit(); err.emit();
} }
pub fn check_coherence(ccx: &CrateCtxt) { pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
CoherenceCollect::check(ccx.tcx); CoherenceCollect::check(tcx);
let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); let _task = tcx.dep_graph.in_task(DepNode::Coherence);
unsafety::check(ccx.tcx); unsafety::check(tcx);
orphan::check(ccx.tcx); orphan::check(tcx);
overlap::check(ccx.tcx); overlap::check(tcx);
builtin::check(ccx.tcx); builtin::check(tcx);
} }

File diff suppressed because it is too large Load diff

View file

@ -23,14 +23,12 @@ use rustc::dep_graph::DepNode;
use rustc::hir; use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::ty; use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc::util::nodemap::{FxHashMap, FxHashSet};
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax_pos::Span; use syntax_pos::Span;
use CrateCtxt;
/// Checks that all the type/lifetime parameters on an impl also /// Checks that all the type/lifetime parameters on an impl also
/// appear in the trait ref or self-type (or are constrained by a /// appear in the trait ref or self-type (or are constrained by a
/// where-clause). These rules are needed to ensure that, given a /// where-clause). These rules are needed to ensure that, given a
@ -61,27 +59,27 @@ use CrateCtxt;
/// impl<'a> Trait<Foo> for Bar { type X = &'a i32; } /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
/// ^ 'a is unused and appears in assoc type, error /// ^ 'a is unused and appears in assoc type, error
/// ``` /// ```
pub fn impl_wf_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>) { pub fn impl_wf_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
// We will tag this as part of the WF check -- logically, it is, // We will tag this as part of the WF check -- logically, it is,
// but it's one that we must perform earlier than the rest of // but it's one that we must perform earlier than the rest of
// WfCheck. // WfCheck.
ccx.tcx.visit_all_item_likes_in_krate(DepNode::WfCheck, &mut ImplWfCheck { ccx: ccx }); tcx.visit_all_item_likes_in_krate(DepNode::WfCheck, &mut ImplWfCheck { tcx: tcx });
} }
struct ImplWfCheck<'a, 'tcx: 'a> { struct ImplWfCheck<'a, 'tcx: 'a> {
ccx: &'a CrateCtxt<'a, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) { fn visit_item(&mut self, item: &'tcx hir::Item) {
match item.node { match item.node {
hir::ItemImpl(.., ref generics, _, _, ref impl_item_refs) => { hir::ItemImpl(.., ref generics, _, _, ref impl_item_refs) => {
let impl_def_id = self.ccx.tcx.hir.local_def_id(item.id); let impl_def_id = self.tcx.hir.local_def_id(item.id);
enforce_impl_params_are_constrained(self.ccx, enforce_impl_params_are_constrained(self.tcx,
generics, generics,
impl_def_id, impl_def_id,
impl_item_refs); impl_item_refs);
enforce_impl_items_are_distinct(self.ccx, impl_item_refs); enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
} }
_ => { } _ => { }
} }
@ -92,16 +90,16 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { } fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
} }
fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_hir_generics: &hir::Generics, impl_hir_generics: &hir::Generics,
impl_def_id: DefId, impl_def_id: DefId,
impl_item_refs: &[hir::ImplItemRef]) impl_item_refs: &[hir::ImplItemRef])
{ {
// Every lifetime used in an associated type must be constrained. // Every lifetime used in an associated type must be constrained.
let impl_self_ty = ccx.tcx.item_type(impl_def_id); let impl_self_ty = tcx.item_type(impl_def_id);
let impl_generics = ccx.tcx.item_generics(impl_def_id); let impl_generics = tcx.item_generics(impl_def_id);
let impl_predicates = ccx.tcx.item_predicates(impl_def_id); let impl_predicates = tcx.item_predicates(impl_def_id);
let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref); let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref);
ctp::identify_constrained_type_params( ctp::identify_constrained_type_params(
@ -111,19 +109,19 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) { for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) {
let param_ty = ty::ParamTy::for_def(ty_param); let param_ty = ty::ParamTy::for_def(ty_param);
if !input_parameters.contains(&ctp::Parameter::from(param_ty)) { if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
report_unused_parameter(ccx, param.span, "type", &param_ty.to_string()); report_unused_parameter(tcx, param.span, "type", &param_ty.to_string());
} }
} }
// Disallow unconstrained lifetimes, but only if they appear in assoc types. // Disallow unconstrained lifetimes, but only if they appear in assoc types.
let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter() let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter()
.map(|item_ref| ccx.tcx.hir.local_def_id(item_ref.id.node_id)) .map(|item_ref| tcx.hir.local_def_id(item_ref.id.node_id))
.filter(|&def_id| { .filter(|&def_id| {
let item = ccx.tcx.associated_item(def_id); let item = tcx.associated_item(def_id);
item.kind == ty::AssociatedKind::Type && item.defaultness.has_value() item.kind == ty::AssociatedKind::Type && item.defaultness.has_value()
}) })
.flat_map(|def_id| { .flat_map(|def_id| {
ctp::parameters_for(&ccx.tcx.item_type(def_id), true) ctp::parameters_for(&tcx.item_type(def_id), true)
}).collect(); }).collect();
for (ty_lifetime, lifetime) in impl_generics.regions.iter() for (ty_lifetime, lifetime) in impl_generics.regions.iter()
.zip(&impl_hir_generics.lifetimes) .zip(&impl_hir_generics.lifetimes)
@ -134,7 +132,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
lifetimes_in_associated_types.contains(&param) && // (*) lifetimes_in_associated_types.contains(&param) && // (*)
!input_parameters.contains(&param) !input_parameters.contains(&param)
{ {
report_unused_parameter(ccx, lifetime.lifetime.span, report_unused_parameter(tcx, lifetime.lifetime.span,
"lifetime", &lifetime.lifetime.name.to_string()); "lifetime", &lifetime.lifetime.name.to_string());
} }
} }
@ -159,13 +157,13 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// used elsewhere are not projected back out. // used elsewhere are not projected back out.
} }
fn report_unused_parameter(ccx: &CrateCtxt, fn report_unused_parameter(tcx: TyCtxt,
span: Span, span: Span,
kind: &str, kind: &str,
name: &str) name: &str)
{ {
struct_span_err!( struct_span_err!(
ccx.tcx.sess, span, E0207, tcx.sess, span, E0207,
"the {} parameter `{}` is not constrained by the \ "the {} parameter `{}` is not constrained by the \
impl trait, self type, or predicates", impl trait, self type, or predicates",
kind, name) kind, name)
@ -174,10 +172,9 @@ fn report_unused_parameter(ccx: &CrateCtxt,
} }
/// Enforce that we do not have two items in an impl with the same name. /// Enforce that we do not have two items in an impl with the same name.
fn enforce_impl_items_are_distinct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn enforce_impl_items_are_distinct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_item_refs: &[hir::ImplItemRef]) impl_item_refs: &[hir::ImplItemRef])
{ {
let tcx = ccx.tcx;
let mut seen_type_items = FxHashMap(); let mut seen_type_items = FxHashMap();
let mut seen_value_items = FxHashMap(); let mut seen_value_items = FxHashMap();
for impl_item_ref in impl_item_refs { for impl_item_ref in impl_item_refs {

View file

@ -110,7 +110,7 @@ use hir::map as hir_map;
use rustc::infer::InferOk; use rustc::infer::InferOk;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::traits::{ObligationCause, ObligationCauseCode, Reveal};
use session::config; use session::config;
use util::common::time; use util::common::time;
@ -120,9 +120,6 @@ use syntax::symbol::keywords;
use syntax_pos::Span; use syntax_pos::Span;
use std::iter; use std::iter;
use std::cell::RefCell;
use util::nodemap::NodeMap;
// NB: This module needs to be declared first so diagnostics are // NB: This module needs to be declared first so diagnostics are
// registered before they are used. // registered before they are used.
pub mod diagnostics; pub mod diagnostics;
@ -141,27 +138,6 @@ pub struct TypeAndSubsts<'tcx> {
pub ty: Ty<'tcx>, pub ty: Ty<'tcx>,
} }
pub struct CrateCtxt<'a, 'tcx: 'a> {
ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
/// A vector of every trait accessible in the whole crate
/// (i.e. including those from subcrates). This is used only for
/// error reporting, and so is lazily initialised and generally
/// shouldn't taint the common path (hence the RefCell).
pub all_traits: RefCell<Option<check::method::AllTraitsVec>>,
/// This stack is used to identify cycles in the user's source.
/// Note that these cycles can cross multiple items.
pub stack: RefCell<Vec<collect::AstConvRequest>>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
/// Obligations which will have to be checked at the end of
/// type-checking, after all functions have been inferred.
/// The key is the NodeId of the item the obligations were from.
pub deferred_obligations: RefCell<NodeMap<Vec<traits::DeferredObligation<'tcx>>>>,
}
fn require_c_abi_if_variadic(tcx: TyCtxt, fn require_c_abi_if_variadic(tcx: TyCtxt,
decl: &hir::FnDecl, decl: &hir::FnDecl,
abi: Abi, abi: Abi,
@ -174,12 +150,12 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
} }
} }
fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>, expected: Ty<'tcx>,
actual: Ty<'tcx>) actual: Ty<'tcx>)
-> bool { -> bool {
ccx.tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| {
match infcx.eq_types(false, &cause, expected, actual) { match infcx.eq_types(false, &cause, expected, actual) {
Ok(InferOk { obligations, .. }) => { Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations // FIXME(#32730) propagate obligations
@ -218,10 +194,9 @@ fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name {
} }
} }
fn check_main_fn_ty(ccx: &CrateCtxt, fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
main_id: ast::NodeId, main_id: ast::NodeId,
main_span: Span) { main_span: Span) {
let tcx = ccx.tcx;
let main_def_id = tcx.hir.local_def_id(main_id); let main_def_id = tcx.hir.local_def_id(main_id);
let main_t = tcx.item_type(main_def_id); let main_t = tcx.item_type(main_def_id);
match main_t.sty { match main_t.sty {
@ -231,7 +206,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
match it.node { match it.node {
hir::ItemFn(.., ref generics, _) => { hir::ItemFn(.., ref generics, _) => {
if generics.is_parameterized() { if generics.is_parameterized() {
struct_span_err!(ccx.tcx.sess, generics.span, E0131, struct_span_err!(tcx.sess, generics.span, E0131,
"main function is not allowed to have type parameters") "main function is not allowed to have type parameters")
.span_label(generics.span, .span_label(generics.span,
&format!("main cannot have type parameters")) &format!("main cannot have type parameters"))
@ -253,7 +228,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
})); }));
require_same_types( require_same_types(
ccx, tcx,
&ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
se_ty, se_ty,
main_t); main_t);
@ -266,11 +241,10 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
} }
} }
fn check_start_fn_ty(ccx: &CrateCtxt, fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
start_id: ast::NodeId, start_id: ast::NodeId,
start_span: Span) { start_span: Span) {
let tcx = ccx.tcx; let start_def_id = tcx.hir.local_def_id(start_id);
let start_def_id = ccx.tcx.hir.local_def_id(start_id);
let start_t = tcx.item_type(start_def_id); let start_t = tcx.item_type(start_def_id);
match start_t.sty { match start_t.sty {
ty::TyFnDef(..) => { ty::TyFnDef(..) => {
@ -308,7 +282,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
})); }));
require_same_types( require_same_types(
ccx, tcx,
&ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
se_ty, se_ty,
start_t); start_t);
@ -321,13 +295,12 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
} }
} }
fn check_for_entry_fn(ccx: &CrateCtxt) { fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let tcx = ccx.tcx;
let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn); let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn);
if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() { if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
match tcx.sess.entry_type.get() { match tcx.sess.entry_type.get() {
Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp), Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp), Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
Some(config::EntryNone) => {} Some(config::EntryNone) => {}
None => bug!("entry function without a type") None => bug!("entry function without a type")
} }
@ -335,21 +308,14 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
} }
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> Result<NodeMap<Ty<'tcx>>, usize> { -> Result<(), usize> {
let time_passes = tcx.sess.time_passes(); let time_passes = tcx.sess.time_passes();
let ccx = CrateCtxt {
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
all_traits: RefCell::new(None),
stack: RefCell::new(Vec::new()),
tcx: tcx,
deferred_obligations: RefCell::new(NodeMap()),
};
// this ensures that later parts of type checking can assume that items // this ensures that later parts of type checking can assume that items
// have valid types and not error // have valid types and not error
tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
time(time_passes, "type collecting", || time(time_passes, "type collecting", ||
collect::collect_item_types(&ccx)); collect::collect_item_types(tcx));
})?; })?;
@ -358,28 +324,28 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
time(time_passes, "impl wf inference", || time(time_passes, "impl wf inference", ||
impl_wf_check::impl_wf_check(&ccx)); impl_wf_check::impl_wf_check(tcx));
})?; })?;
tcx.sess.track_errors(|| { tcx.sess.track_errors(|| {
time(time_passes, "coherence checking", || time(time_passes, "coherence checking", ||
coherence::check_coherence(&ccx)); coherence::check_coherence(tcx));
})?; })?;
time(time_passes, "wf checking", || check::check_wf_new(&ccx))?; time(time_passes, "wf checking", || check::check_wf_new(tcx))?;
time(time_passes, "item-types checking", || check::check_item_types(&ccx))?; time(time_passes, "item-types checking", || check::check_item_types(tcx))?;
time(time_passes, "item-bodies checking", || check::check_item_bodies(&ccx))?; time(time_passes, "item-bodies checking", || check::check_item_bodies(tcx))?;
time(time_passes, "drop-impl checking", || check::check_drop_impls(&ccx))?; time(time_passes, "drop-impl checking", || check::check_drop_impls(tcx))?;
check_unused::check_crate(tcx); check_unused::check_crate(tcx);
check_for_entry_fn(&ccx); check_for_entry_fn(tcx);
let err_count = tcx.sess.err_count(); let err_count = tcx.sess.err_count();
if err_count == 0 { if err_count == 0 {
Ok(ccx.ast_ty_to_ty_cache.into_inner()) Ok(())
} else { } else {
Err(err_count) Err(err_count)
} }

View file

@ -1772,7 +1772,7 @@ impl Clean<Type> for hir::Ty {
} }
TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => { TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
let mut def = Def::Err; let mut def = Def::Err;
if let Some(ty) = cx.hir_ty_to_ty.get(&self.id) { if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&self.id) {
if let ty::TyProjection(proj) = ty.sty { if let ty::TyProjection(proj) = ty.sty {
def = Def::Trait(proj.trait_ref.def_id); def = Def::Trait(proj.trait_ref.def_id);
} }

View file

@ -15,10 +15,10 @@ use rustc::session::{self, config};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::def::{Def, ExportMap}; use rustc::hir::def::{Def, ExportMap};
use rustc::middle::privacy::AccessLevels; use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, GlobalArenas, Ty}; use rustc::ty::{self, TyCtxt, GlobalArenas};
use rustc::hir::map as hir_map; use rustc::hir::map as hir_map;
use rustc::lint; use rustc::lint;
use rustc::util::nodemap::{FxHashMap, NodeMap}; use rustc::util::nodemap::FxHashMap;
use rustc_trans::back::link; use rustc_trans::back::link;
use rustc_resolve as resolve; use rustc_resolve as resolve;
use rustc_metadata::cstore::CStore; use rustc_metadata::cstore::CStore;
@ -65,9 +65,6 @@ pub struct DocContext<'a, 'tcx: 'a> {
/// Table node id of lifetime parameter definition -> substituted lifetime /// Table node id of lifetime parameter definition -> substituted lifetime
pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>, pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>,
pub export_map: ExportMap, pub export_map: ExportMap,
/// Table from HIR Ty nodes to their resolved Ty.
pub hir_ty_to_ty: NodeMap<Ty<'tcx>>,
} }
impl<'a, 'tcx> DocContext<'a, 'tcx> { impl<'a, 'tcx> DocContext<'a, 'tcx> {
@ -183,7 +180,7 @@ pub fn run_core(search_paths: SearchPaths,
sess.fatal("Compilation failed, aborting rustdoc"); sess.fatal("Compilation failed, aborting rustdoc");
} }
let ty::CrateAnalysis { access_levels, export_map, hir_ty_to_ty, .. } = analysis; let ty::CrateAnalysis { access_levels, export_map, .. } = analysis;
// Convert from a NodeId set to a DefId set since we don't always have easy access // Convert from a NodeId set to a DefId set since we don't always have easy access
// to the map from defid -> nodeid // to the map from defid -> nodeid
@ -202,7 +199,6 @@ pub fn run_core(search_paths: SearchPaths,
ty_substs: Default::default(), ty_substs: Default::default(),
lt_substs: Default::default(), lt_substs: Default::default(),
export_map: export_map, export_map: export_map,
hir_ty_to_ty: hir_ty_to_ty,
}; };
debug!("crate: {:?}", tcx.hir.krate()); debug!("crate: {:?}", tcx.hir.krate());