From e8d01ea4c76f6f3cb4f71dbff261355f825d12bb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 25 Jan 2017 22:01:11 +0200 Subject: [PATCH 01/17] rustc: store type parameter defaults outside of ty::Generics. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/infer/mod.rs | 15 +- src/librustc/middle/cstore.rs | 15 +- src/librustc/middle/resolve_lifetime.rs | 4 +- src/librustc/ty/context.rs | 16 +- src/librustc/ty/error.rs | 8 +- src/librustc/ty/maps.rs | 2 +- src/librustc/ty/mod.rs | 31 ++-- src/librustc/ty/structural_impls.rs | 36 +--- src/librustc/ty/subst.rs | 14 +- src/librustc/util/ppaux.rs | 9 +- src/librustc_metadata/cstore_impl.rs | 18 +- src/librustc_metadata/decoder.rs | 25 +-- src/librustc_metadata/encoder.rs | 61 ++++--- src/librustc_metadata/schema.rs | 17 +- src/librustc_privacy/lib.rs | 12 +- src/librustc_resolve/diagnostics.rs | 27 +++ src/librustc_resolve/lib.rs | 78 +++++++-- src/librustc_trans/debuginfo/mod.rs | 6 +- src/librustc_trans/debuginfo/utils.rs | 8 +- src/librustc_typeck/astconv.rs | 58 +++---- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/mod.rs | 18 +- src/librustc_typeck/collect.rs | 157 +++++++++--------- src/librustc_typeck/diagnostics.rs | 27 --- src/librustc_typeck/lib.rs | 25 +++ src/librustc_typeck/variance/constraints.rs | 14 +- src/librustdoc/clean/mod.rs | 10 +- src/libsyntax/visit.rs | 49 +++--- .../cycle-trait-default-type-trait.rs | 1 + .../generic-non-trailing-defaults.rs | 4 +- .../generic-type-params-forward-mention.rs | 2 +- src/test/compile-fail/issue-18183.rs | 4 +- src/test/compile-fail/resolve-self-in-impl.rs | 2 +- 34 files changed, 394 insertions(+), 385 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8572119e98916..82e644d710dc2 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -525,7 +525,7 @@ impl<'a> LoweringContext<'a> { return n; } assert!(!def_id.is_local()); - let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id); + let n = self.sess.cstore.item_generics(def_id).regions.len(); self.type_def_lifetime_params.insert(def_id, n); n }); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index c3a6a62764d0b..64256247bb50c 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1197,16 +1197,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// as the substitutions for the default, `(T, U)`. pub fn type_var_for_def(&self, span: Span, - def: &ty::TypeParameterDef<'tcx>, + def: &ty::TypeParameterDef, substs: &[Kind<'tcx>]) -> Ty<'tcx> { - let default = def.default.map(|default| { - type_variable::Default { + let default = if def.has_default { + let default = self.tcx.item_type(def.def_id); + Some(type_variable::Default { ty: default.subst_spanned(self.tcx, substs, Some(span)), origin_span: span, - def_id: def.default_def_id - } - }); + def_id: def.def_id + }) + } else { + None + }; let ty_var_id = self.type_variables diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 2d80fc32c469d..671da0d11972b 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -28,7 +28,6 @@ use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; use hir::svh::Svh; use middle::lang_items; -use middle::resolve_lifetime::ObjectLifetimeDefault; use ty::{self, Ty, TyCtxt}; use mir::Mir; use session::Session; @@ -182,11 +181,7 @@ pub trait CrateStore<'tcx> { -> ty::GenericPredicates<'tcx>; fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; - fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::Generics<'tcx>; - fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize); - fn item_generics_object_lifetime_defaults(&self, def: DefId) - -> Vec; + fn item_generics(&self, def: DefId) -> ty::Generics; fn item_attrs(&self, def_id: DefId) -> Vec; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef; @@ -335,13 +330,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { -> ty::GenericPredicates<'tcx> { bug!("item_predicates") } fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } - fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::Generics<'tcx> { bug!("item_generics") } - fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) - { bug!("item_generics_own_param_counts") } - fn item_generics_object_lifetime_defaults(&self, def: DefId) - -> Vec - { bug!("item_generics_object_lifetime_defaults") } + fn item_generics(&self, def: DefId) -> ty::Generics { bug!("item_generics") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef { bug!("trait_def") } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9bad98dda83f8..95cbd738651d5 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -995,7 +995,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else { let cstore = &self.sess.cstore; self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| { - cstore.item_generics_object_lifetime_defaults(def_id) + cstore.item_generics(def_id).types.into_iter().map(|def| { + def.object_lifetime_default + }).collect() }) }; unsubst.iter().map(|set| { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 19bb8a63aa277..2f062e2e5b194 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -64,7 +64,7 @@ pub struct GlobalArenas<'tcx> { layout: TypedArena, // references - generics: TypedArena>, + generics: TypedArena, trait_def: TypedArena, adt_def: TypedArena, mir: TypedArena>>, @@ -467,9 +467,6 @@ pub struct GlobalCtxt<'tcx> { // Cache for the type-contents routine. FIXME -- track deps? pub tc_cache: RefCell, ty::contents::TypeContents>>, - // FIXME no dep tracking, but we should be able to remove this - pub ty_param_defs: RefCell>>, - // FIXME dep tracking -- should be harmless enough pub normalized_cache: RefCell, Ty<'tcx>>>, @@ -646,15 +643,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn type_parameter_def(self, - node_id: NodeId) - -> ty::TypeParameterDef<'tcx> - { - self.ty_param_defs.borrow().get(&node_id).unwrap().clone() - } - - pub fn alloc_generics(self, generics: ty::Generics<'gcx>) - -> &'gcx ty::Generics<'gcx> { + pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { self.global_arenas.generics.alloc(generics) } @@ -785,7 +774,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { tc_cache: RefCell::new(FxHashMap()), associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - ty_param_defs: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FxHashMap()), inhabitedness_cache: RefCell::new(FxHashMap()), lang_items: lang_items, diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 3ab3fc899e78c..44a3aabc0560a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -10,7 +10,7 @@ use hir::def_id::DefId; use infer::type_variable; -use ty::{self, BoundRegion, Region, Ty, TyCtxt}; +use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt}; use std::fmt; use syntax::abi; @@ -287,8 +287,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { db.span_note(span, "a default was defined here..."); } None => { + let item_def_id = self.parent(expected.def_id).unwrap(); db.note(&format!("a default is defined on `{}`", - self.item_path_str(expected.def_id))); + self.item_path_str(item_def_id))); } } @@ -301,8 +302,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { db.span_note(span, "a second default was defined here..."); } None => { + let item_def_id = self.parent(found.def_id).unwrap(); db.note(&format!("a second default is defined on `{}`", - self.item_path_str(found.def_id))); + self.item_path_str(item_def_id))); } } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index d7341d148b720..d2c237d5db61d 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -35,7 +35,7 @@ macro_rules! dep_map_ty { dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem } dep_map_ty! { Types: ItemSignature(DefId) -> Ty<'tcx> } -dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> } +dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics } dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7937d2ccfe46d..1275530b1bdf9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -19,9 +19,10 @@ use dep_graph::{self, DepNode}; use hir::{map as hir_map, FreevarMap, TraitMap}; use middle; use hir::def::{Def, CtorKind, ExportMap}; -use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; +use middle::resolve_lifetime::ObjectLifetimeDefault; use mir::Mir; use traits; use ty; @@ -33,6 +34,7 @@ use util::nodemap::{NodeSet, NodeMap, FxHashMap}; use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; use std::cell::{Cell, RefCell, Ref}; +use std::collections::BTreeMap; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::rc::Rc; @@ -585,13 +587,13 @@ pub enum IntVarValue { UintType(ast::UintTy), } -#[derive(Clone, RustcEncodable, RustcDecodable)] -pub struct TypeParameterDef<'tcx> { +#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] +pub struct TypeParameterDef { pub name: Name, pub def_id: DefId, pub index: u32, - pub default_def_id: DefId, // for use in error reporing about defaults - pub default: Option>, + pub has_default: bool, + pub object_lifetime_default: ObjectLifetimeDefault, /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute /// on generic parameter `T`, asserts data behind the parameter @@ -628,16 +630,21 @@ impl RegionParameterDef { /// Information about the formal type/lifetime parameters associated /// with an item or method. Analogous to hir::Generics. #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub struct Generics<'tcx> { +pub struct Generics { pub parent: Option, pub parent_regions: u32, pub parent_types: u32, pub regions: Vec, - pub types: Vec>, + pub types: Vec, + + /// Reverse map to each `TypeParameterDef`'s `index` field, from + /// `def_id.index` (`def_id.krate` is the same as the item's). + pub type_param_to_index: BTreeMap, + pub has_self: bool, } -impl<'tcx> Generics<'tcx> { +impl Generics { pub fn parent_count(&self) -> usize { self.parent_regions as usize + self.parent_types as usize } @@ -651,10 +658,12 @@ impl<'tcx> Generics<'tcx> { } pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef { + assert_eq!(self.parent_count(), 0); &self.regions[param.index as usize - self.has_self as usize] } - pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef<'tcx> { + pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef { + assert_eq!(self.parent_count(), 0); &self.types[param.idx as usize - self.has_self as usize - self.regions.len()] } } @@ -2319,10 +2328,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Given the did of an item, returns its generics. - pub fn item_generics(self, did: DefId) -> &'gcx Generics<'gcx> { + pub fn item_generics(self, did: DefId) -> &'gcx Generics { lookup_locally_or_in_crate_store( "generics", did, &self.generics, - || self.alloc_generics(self.sess.cstore.item_generics(self.global_tcx(), did))) + || self.alloc_generics(self.sess.cstore.item_generics(did))) } /// Given the did of an item, returns its full set of predicates. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index aa74e7cc0d043..a1bf58a12eb09 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -353,7 +353,7 @@ macro_rules! CopyImpls { } } -CopyImpls! { (), hir::Unsafety, abi::Abi, ty::RegionParameterDef } +CopyImpls! { (), hir::Unsafety, abi::Abi } impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) { @@ -716,40 +716,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TypeParameterDef { - name: self.name, - def_id: self.def_id, - index: self.index, - default: self.default.fold_with(folder), - default_def_id: self.default_def_id, - pure_wrt_drop: self.pure_wrt_drop, - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.default.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::Generics { - parent: self.parent, - parent_regions: self.parent_regions, - parent_types: self.parent_types, - regions: self.regions.fold_with(folder), - types: self.types.fold_with(folder), - has_self: self.has_self, - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.regions.visit_with(visitor) || self.types.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::GenericPredicates { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index c0a529b936b0f..0a2cc1c30f40f 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { mut mk_type: FT) -> &'tcx Substs<'tcx> where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region, - FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> { + FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> { let defs = tcx.item_generics(def_id); let mut substs = Vec::with_capacity(defs.count()); Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type); @@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { mut mk_type: FT) -> &'tcx Substs<'tcx> where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region, - FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> + FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> { let defs = tcx.item_generics(def_id); let mut result = Vec::with_capacity(defs.count()); @@ -209,11 +209,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { fn fill_item(substs: &mut Vec>, tcx: TyCtxt<'a, 'gcx, 'tcx>, - defs: &ty::Generics<'tcx>, + defs: &ty::Generics, mk_region: &mut FR, mk_type: &mut FT) where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region, - FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> { + FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> { if let Some(def_id) = defs.parent { let parent_defs = tcx.item_generics(def_id); @@ -223,11 +223,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } fn fill_single(substs: &mut Vec>, - defs: &ty::Generics<'tcx>, + defs: &ty::Generics, mk_region: &mut FR, mk_type: &mut FT) where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region, - FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> { + FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> { // Handle Self first, before all regions. let mut types = defs.types.iter(); if defs.parent.is_none() && defs.has_self { @@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned()) } - pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>) + pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics) -> &'tcx Substs<'tcx> { tcx.mk_substs(self.iter().take(generics.count()).cloned()) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a45c43235ebf8..2a5cd7b37cae4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -137,11 +137,14 @@ pub fn parameterized(f: &mut fmt::Formatter, } if !verbose { - if generics.types.last().map_or(false, |def| def.default.is_some()) { + if generics.types.last().map_or(false, |def| def.has_default) { if let Some(substs) = tcx.lift(&substs) { let tps = substs.types().rev().skip(child_types); for (def, actual) in generics.types.iter().rev().zip(tps) { - if def.default.subst(tcx, substs) != Some(actual) { + if !def.has_default { + break; + } + if tcx.item_type(def.def_id).subst(tcx, substs) != actual { break; } num_supplied_defaults += 1; @@ -326,7 +329,7 @@ impl<'tcx> fmt::Display for &'tcx ty::Slice> { } } -impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> { +impl fmt::Debug for ty::TypeParameterDef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "TypeParameterDef({}, {:?}, {})", self.name, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7b0177bfd23ed..bd184c5c5e69f 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -17,7 +17,6 @@ use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternC use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro}; use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; -use rustc::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -104,22 +103,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).get_super_predicates(def.index, tcx) } - fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::Generics<'tcx> - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_generics(def.index, tcx) - } - - fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).generics_own_param_counts(def.index) - } - - fn item_generics_object_lifetime_defaults(&self, def: DefId) - -> Vec { + fn item_generics(&self, def: DefId) -> ty::Generics { self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).generics_object_lifetime_defaults(def.index) + self.get_crate_data(def.krate).get_generics(def.index) } fn item_attrs(&self, def_id: DefId) -> Vec diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 53883e50a5be2..22fa9411cc117 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -20,7 +20,6 @@ use rustc::middle::cstore::LinkagePreference; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::middle::lang_items; -use rustc::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; @@ -601,30 +600,8 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_generics(&self, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::Generics<'tcx> { - let g = self.entry(item_id).generics.unwrap().decode(self); - ty::Generics { - parent: g.parent, - parent_regions: g.parent_regions, - parent_types: g.parent_types, - regions: g.regions.decode((self, tcx)).collect(), - types: g.types.decode((self, tcx)).collect(), - has_self: g.has_self, - } - } - - pub fn generics_own_param_counts(&self, item_id: DefIndex) -> (usize, usize) { - let g = self.entry(item_id).generics.unwrap().decode(self); - (g.regions.len, g.types.len) - } - - pub fn generics_object_lifetime_defaults(&self, item_id: DefIndex) - -> Vec { + pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics { self.entry(item_id).generics.unwrap().decode(self) - .object_lifetime_defaults.decode(self).collect() } pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0f9491aaf15b4..a643ed59af136 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -423,26 +423,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_generics(&mut self, def_id: DefId) -> Lazy> { + fn encode_generics(&mut self, def_id: DefId) -> Lazy { let tcx = self.tcx; - let g = tcx.item_generics(def_id); - let regions = self.lazy_seq_ref(&g.regions); - let types = self.lazy_seq_ref(&g.types); - let mut object_lifetime_defaults = LazySeq::empty(); - if let Some(id) = tcx.hir.as_local_node_id(def_id) { - if let Some(o) = tcx.named_region_map.object_lifetime_defaults.get(&id) { - object_lifetime_defaults = self.lazy_seq_ref(o); - } - } - self.lazy(&Generics { - parent: g.parent, - parent_regions: g.parent_regions, - parent_types: g.parent_types, - regions: regions, - types: types, - has_self: g.has_self, - object_lifetime_defaults: object_lifetime_defaults, - }) + self.lazy(tcx.item_generics(def_id)) } fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { @@ -1008,6 +991,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { EncodeContext::encode_info_for_foreign_item, (def_id, ni)); } + fn visit_generics(&mut self, generics: &'tcx hir::Generics) { + intravisit::walk_generics(self, generics); + self.index.encode_info_for_generics(generics); + } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { intravisit::walk_ty(self, ty); self.index.encode_info_for_ty(ty); @@ -1019,6 +1006,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { + fn encode_info_for_generics(&mut self, generics: &hir::Generics) { + for ty_param in &generics.ty_params { + let def_id = self.tcx.hir.local_def_id(ty_param.id); + let has_default = Untracked(ty_param.default.is_some()); + self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default)); + } + } + fn encode_info_for_ty(&mut self, ty: &hir::Ty) { if let hir::TyImplTrait(_) = ty.node { let def_id = self.tcx.hir.local_def_id(ty.id); @@ -1038,6 +1033,34 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn encode_info_for_ty_param(&mut self, + (def_id, Untracked(has_default)): (DefId, Untracked)) + -> Entry<'tcx> { + let tcx = self.tcx; + Entry { + kind: EntryKind::Type, + visibility: self.lazy(&ty::Visibility::Public), + span: self.lazy(&tcx.def_span(def_id)), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, + + ty: if has_default { + Some(self.encode_item_type(def_id)) + } else { + None + }, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: None, + predicates: None, + + ast: None, + mir: None, + } + } + fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> { let tcx = self.tcx; Entry { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 777af02772ec1..ee30063fcbd06 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -16,7 +16,6 @@ use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId}; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; -use rustc::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc::mir; use rustc::ty::{self, Ty, ReprOptions}; use rustc_back::PanicStrategy; @@ -212,7 +211,7 @@ pub struct Entry<'tcx> { pub ty: Option>>, pub inherent_impls: LazySeq, pub variances: LazySeq, - pub generics: Option>>, + pub generics: Option>, pub predicates: Option>>, pub ast: Option>>, @@ -246,20 +245,6 @@ pub enum EntryKind<'tcx> { AssociatedConst(AssociatedContainer), } -/// A copy of `ty::Generics` which allows lazy decoding of -/// `regions` and `types` (e.g. knowing the number of type -/// and lifetime parameters before `TyCtxt` is created). -#[derive(RustcEncodable, RustcDecodable)] -pub struct Generics<'tcx> { - pub parent: Option, - pub parent_regions: u32, - pub parent_types: u32, - pub regions: LazySeq, - pub types: LazySeq>, - pub has_self: bool, - pub object_lifetime_defaults: LazySeq, -} - #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { pub reexports: LazySeq, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9dc94745cff7b..72347f1616eb6 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -334,7 +334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { fn generics(&mut self) -> &mut Self { - self.ev.tcx.item_generics(self.item_def_id).visit_with(self); + for def in &self.ev.tcx.item_generics(self.item_def_id).types { + if def.has_default { + self.ev.tcx.item_type(def.def_id).visit_with(self); + } + } self } @@ -892,7 +896,11 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { fn generics(&mut self) -> &mut Self { - self.tcx.item_generics(self.item_def_id).visit_with(self); + for def in &self.tcx.item_generics(self.item_def_id).types { + if def.has_default { + self.tcx.item_type(def.def_id).visit_with(self); + } + } self } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 2fada8a9ec212..8f6b1b8971e5b 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -15,6 +15,33 @@ // use `gq` to wrap paragraphs. Use `:set tw=0` to disable. register_long_diagnostics! { +E0128: r##" +Type parameter defaults can only use parameters that occur before them. +Erroneous code example: + +```compile_fail,E0128 +struct Foo { + field1: T, + filed2: U, +} +// error: type parameters with a default cannot use forward declared +// identifiers +``` + +Since type parameters are evaluated in-order, you may be able to fix this issue +by doing: + +``` +struct Foo { + field1: T, + filed2: U, +} +``` + +Please also verify that this wasn't because of a name-clash and rename the type +parameter if so. +"##, + E0154: r##" ## Note: this error code is no longer emitted by the compiler. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index eefe83d7da6f5..0565db28ec5c9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -136,6 +136,8 @@ enum ResolutionError<'a> { AttemptToUseNonConstantValueInConstant, /// error E0530: X bindings cannot shadow Ys BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>), + /// error E0128: type parameters with a default cannot use forward declared identifiers + ForwardDeclaredTyParam, } fn resolve_error<'sess, 'a>(resolver: &'sess Resolver, @@ -322,6 +324,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, err.span_label(binding.span, msg); err } + ResolutionError::ForwardDeclaredTyParam => { + let mut err = struct_span_err!(resolver.session, span, E0128, + "type parameters with a default cannot use \ + forward declared identifiers"); + err.span_label(span, &format!("defaulted type parameters \ + cannot be forward declared")); + err + } } } @@ -674,6 +684,32 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { self.label_ribs.pop(); self.ribs[ValueNS].pop(); } + fn visit_generics(&mut self, generics: &'tcx Generics) { + // For type parameter defaults, we have to ban access + // to following type parameters, as the Substs can only + // provide previous type parameters as they're built. + let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); + default_ban_rib.bindings.extend(generics.ty_params.iter() + .skip_while(|p| p.default.is_none()) + .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err))); + + for param in &generics.ty_params { + for bound in ¶m.bounds { + self.visit_ty_param_bound(bound); + } + + if let Some(ref ty) = param.default { + self.ribs[TypeNS].push(default_ban_rib); + self.visit_ty(ty); + default_ban_rib = self.ribs[TypeNS].pop().unwrap(); + } + + // Allow all following defaults to refer to this type parameter. + default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name)); + } + for lt in &generics.lifetimes { self.visit_lifetime_def(lt); } + for p in &generics.where_clause.predicates { self.visit_where_predicate(p); } + } } pub type ErrorMessage = Option<(Span, String)>; @@ -718,6 +754,11 @@ enum RibKind<'a> { // We passed through a `macro_rules!` statement with the given expansion MacroDefinition(Mark), + + // All bindings in this rib are type parameters that can't be used + // from the default of a type parameter because they're not declared + // before said type parameter. Also see the `visit_generics` override. + ForwardTyParamBanRibKind, } /// One local scope. @@ -736,13 +777,6 @@ impl<'a> Rib<'a> { } } -/// A definition along with the index of the rib it was found on -#[derive(Copy, Clone, Debug)] -struct LocalDef { - ribs: Option<(Namespace, usize)>, - def: Def, -} - enum LexicalScopeBinding<'a> { Item(&'a NameBinding<'a>), Def(Def), @@ -1428,7 +1462,7 @@ impl<'a> Resolver<'a> { if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Def( - self.adjust_local_def(LocalDef { ribs: Some((ns, i)), def: def }, record_used) + self.adjust_local_def(ns, i, def, record_used) )); } @@ -2527,12 +2561,23 @@ impl<'a> Resolver<'a> { } // Resolve a local definition, potentially adjusting for closures. - fn adjust_local_def(&mut self, local_def: LocalDef, record_used: Option) -> Def { - let ribs = match local_def.ribs { - Some((ns, i)) => &self.ribs[ns][i + 1..], - None => &[] as &[_], - }; - let mut def = local_def.def; + fn adjust_local_def(&mut self, + ns: Namespace, + rib_index: usize, + mut def: Def, + record_used: Option) -> Def { + let ribs = &self.ribs[ns][rib_index + 1..]; + + // An invalid forward use of a type parameter from a previous default. + if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind { + if let Some(span) = record_used { + resolve_error(self, span, + ResolutionError::ForwardDeclaredTyParam); + } + assert_eq!(def, Def::Err); + return Def::Err; + } + match def { Def::Upvar(..) => { span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def) @@ -2540,7 +2585,8 @@ impl<'a> Resolver<'a> { Def::Local(def_id) => { for rib in ribs { match rib.kind { - NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => { + NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) | + ForwardTyParamBanRibKind => { // Nothing to do. Continue. } ClosureRibKind(function_id) => { @@ -2593,7 +2639,7 @@ impl<'a> Resolver<'a> { for rib in ribs { match rib.kind { NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) | - ModuleRibKind(..) | MacroDefinition(..) => { + ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind => { diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index e9b592ec8fd79..4a8b0ff45522f 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -332,7 +332,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, substs: &Substs<'tcx>, file_metadata: DIFile, name_to_append_suffix_to: &mut String) @@ -382,9 +382,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, return create_DIArray(DIB(cx), &template_params[..]); } - fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - generics: &ty::Generics<'tcx>) - -> Vec { + fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec { let mut names = generics.parent.map_or(vec![], |def_id| { get_type_parameter_names(cx, cx.tcx().item_generics(def_id)) }); diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 15a1c990aadc6..ceff96a39b2c9 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -14,6 +14,7 @@ use super::{CrateDebugContext}; use super::namespace::item_namespace; use rustc::hir::def_id::DefId; +use rustc::ty::DefIdTree; use llvm; use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray}; @@ -74,11 +75,8 @@ pub fn DIB(cx: &CrateContext) -> DIBuilderRef { pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId) -> (DIScope, Span) { - let containing_scope = item_namespace(cx, DefId { - krate: def_id.krate, - index: cx.tcx().def_key(def_id).parent - .expect("get_namespace_and_span_for_item: missing parent?") - }); + let containing_scope = item_namespace(cx, cx.tcx().parent(def_id) + .expect("get_namespace_and_span_for_item: missing parent?")); // Try to get some span information, if we have an inlined item. let definition_span = cx.tcx().def_span(def_id); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ab1897101eb6f..8f556726f22f5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -42,7 +42,7 @@ use std::cell::RefCell; use std::iter; use syntax::{abi, ast}; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::Symbol; use syntax_pos::Span; pub trait AstConv<'gcx, 'tcx> { @@ -53,7 +53,7 @@ pub trait AstConv<'gcx, 'tcx> { /// Returns the generic type and lifetime parameters for an item. fn get_generics(&self, span: Span, id: DefId) - -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>; + -> Result<&'tcx ty::Generics, ErrorReported>; /// Identify the type for an item, like a type alias, fn, or struct. fn get_item_type(&self, span: Span, id: DefId) -> Result, ErrorReported>; @@ -89,7 +89,7 @@ pub trait AstConv<'gcx, 'tcx> { /// Same as ty_infer, but with a known type parameter definition. fn ty_infer_for_def(&self, - _def: &ty::TypeParameterDef<'tcx>, + _def: &ty::TypeParameterDef, _substs: &[Kind<'tcx>], span: Span) -> Ty<'tcx> { self.ty_infer(span) @@ -277,9 +277,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); - let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| { - if let Some(ref default) = p.default { - if is_object && default.has_self_ty() { + let default_needs_object_self = |p: &ty::TypeParameterDef| { + if is_object && p.has_default { + let default = self.get_item_type(span, p.def_id).ok(); + if default.has_self_ty() { // There is no suitable inference default for a type parameter // that references self, in an object type. return true; @@ -327,7 +328,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.ty_infer(span) }; ty_var - } else if let Some(default) = def.default { + } else if def.has_default { // No type parameter provided, but a default exists. // If we are converting an object type, then the @@ -346,7 +347,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.err } else { // This is a default type parameter. - default.subst_spanned(tcx, substs, Some(span)) + match self.get_item_type(span, def.def_id) { + Ok(ty) => ty.subst_spanned(tcx, substs, Some(span)), + Err(ErrorReported) => tcx.types.err + } } } else { // We've already errored above about the mismatch. @@ -954,19 +958,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => { - let trait_node_id = tcx.hir.as_local_node_id(trait_did).unwrap(); - match self.find_bound_for_assoc_item(trait_node_id, - keywords::SelfType.name(), - assoc_name, - span) { - Ok(bound) => bound, - Err(ErrorReported) => return (tcx.types.err, Def::Err), - } - } + (&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) | (&ty::TyParam(_), Def::TyParam(param_did)) => { let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap(); - let param_name = tcx.type_parameter_def(param_node_id).name; + let param_name = ::ty_param_name(tcx, param_node_id); match self.find_bound_for_assoc_item(param_node_id, param_name, assoc_name, @@ -1063,21 +1058,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.prohibit_type_params(&path.segments); let node_id = tcx.hir.as_local_node_id(did).unwrap(); - let param = tcx.ty_param_defs.borrow().get(&node_id) - .map(ty::ParamTy::for_def); - if let Some(p) = param { - p.to_ty(tcx) - } else { - // Only while computing defaults of earlier type - // parameters can a type parameter be missing its def. - struct_span_err!(tcx.sess, span, E0128, - "type parameters with a default cannot use \ - forward declared identifiers") - .span_label(span, &format!("defaulted type parameters \ - cannot be forward declared")) - .emit(); - tcx.types.err - } + let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); + let index = match self.get_generics(span, item_def_id) { + Ok(generics) => { + generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index] + } + Err(ErrorReported) => return tcx.types.err + }; + tcx.mk_param(index, ::ty_param_name(tcx, node_id)) } Def::SelfTy(_, Some(def_id)) => { // Self in impl (we know the concrete type). @@ -1510,7 +1498,7 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, ty_param_defs: &[ty::TypeParameterDef]) { let accepted = ty_param_defs.len(); - let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count(); + let required = ty_param_defs.iter().take_while(|x| !x.has_default).count(); if supplied < required { let expected = if required < accepted { "expected at least" diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index d110c16cf3313..bdeb716535655 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -386,8 +386,8 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, impl_m: &ty::AssociatedItem, - trait_generics: &ty::Generics<'tcx>, - impl_generics: &ty::Generics<'tcx>, + trait_generics: &ty::Generics, + impl_generics: &ty::Generics, trait_to_skol_substs: &Substs<'tcx>, impl_to_skol_substs: &Substs<'tcx>) -> Result<(), ErrorReported> { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 14dacb0ca97cb..60805625b7b32 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1360,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { } fn get_generics(&self, _: Span, id: DefId) - -> Result<&'tcx ty::Generics<'tcx>, ErrorReported> + -> Result<&'tcx ty::Generics, ErrorReported> { Ok(self.tcx().item_generics(id)) } @@ -1390,14 +1390,17 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { node_id: ast::NodeId) -> Result>, ErrorReported> { - let def = self.tcx.type_parameter_def(node_id); + let tcx = self.tcx; + let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); + let generics = tcx.item_generics(item_def_id); + let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; let r = self.parameter_environment .caller_bounds .iter() .filter_map(|predicate| { match *predicate { ty::Predicate::Trait(ref data) => { - if data.0.self_ty().is_param(def.index) { + if data.0.self_ty().is_param(index) { Some(data.to_poly_trait_ref()) } else { None @@ -1426,7 +1429,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { } fn ty_infer_for_def(&self, - ty_param_def: &ty::TypeParameterDef<'tcx>, + ty_param_def: &ty::TypeParameterDef, substs: &[Kind<'tcx>], span: Span) -> Ty<'tcx> { self.type_var_for_def(span, ty_param_def, substs) @@ -4423,8 +4426,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(ast_ty) = types.get(i) { // A provided type parameter. self.to_ty(ast_ty) - } else if let (false, Some(default)) = (infer_types, def.default) { + } else if !infer_types && def.has_default { // No type parameter provided, but a default exists. + let default = self.tcx.item_type(def.def_id); default.subst_spanned(self.tcx, substs, Some(span)) } else { // No type parameters were provided, we can infer all. @@ -4537,9 +4541,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &generics.types } }); - let required_len = type_defs.iter() - .take_while(|d| d.default.is_none()) - .count(); + let required_len = type_defs.iter().take_while(|d| !d.has_default).count(); if types.len() > type_defs.len() { let span = types[type_defs.len()].span; let expected_text = count_type_params(type_defs.len()); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 217405a81ec2d..d168f5d424105 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -62,6 +62,7 @@ use lint; use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; +use middle::resolve_lifetime as rl; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; @@ -76,6 +77,7 @@ use CrateCtxt; use rustc_const_math::ConstInt; use std::cell::RefCell; +use std::collections::BTreeMap; use syntax::{abi, ast, attr}; use syntax::symbol::{Symbol, keywords}; @@ -186,6 +188,16 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { intravisit::walk_item(self, item); } + fn visit_generics(&mut self, generics: &'tcx hir::Generics) { + for param in &generics.ty_params { + if param.default.is_some() { + let def_id = self.ccx.tcx.hir.local_def_id(param.id); + type_of_def_id(self.ccx, def_id); + } + } + intravisit::walk_generics(self, generics); + } + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if let hir::ExprClosure(..) = expr.node { let def_id = self.ccx.tcx.hir.local_def_id(expr.id); @@ -277,11 +289,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { tcx.item_path_str(def_id))); } AstConvRequest::GetTypeParameterBounds(id) => { - let def = tcx.type_parameter_def(id); err.note( &format!("the cycle begins when computing the bounds \ for type parameter `{}`...", - def.name)); + ::ty_param_name(tcx, id))); } } @@ -300,11 +311,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { tcx.item_path_str(def_id))); } AstConvRequest::GetTypeParameterBounds(id) => { - let def = tcx.type_parameter_def(id); err.note( &format!("...which then requires computing the bounds \ for type parameter `{}`...", - def.name)); + ::ty_param_name(tcx, id))); } } } @@ -324,11 +334,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { tcx.item_path_str(def_id))); } AstConvRequest::GetTypeParameterBounds(id) => { - let def = tcx.type_parameter_def(id); err.note( &format!("...which then again requires computing the bounds \ for type parameter `{}`, completing the cycle.", - def.name)); + ::ty_param_name(tcx, id))); } } err.emit(); @@ -385,7 +394,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } fn get_generics(&self, span: Span, id: DefId) - -> Result<&'tcx ty::Generics<'tcx>, ErrorReported> + -> Result<&'tcx ty::Generics, ErrorReported> { self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || { Ok(generics_of_def_id(self.ccx, id)) @@ -531,20 +540,23 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { node_id: ast::NodeId) -> Vec> { - let def = astconv.tcx().type_parameter_def(node_id); + let tcx = astconv.tcx(); + let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); + let generics = tcx.item_generics(item_def_id); + let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; let mut results = self.parent.map_or(vec![], |def_id| { - let parent = astconv.tcx().item_predicates(def_id); + let parent = tcx.item_predicates(def_id); parent.get_type_parameter_bounds(astconv, span, node_id) }); results.extend(self.predicates.iter().filter(|predicate| { match **predicate { ty::Predicate::Trait(ref data) => { - data.skip_binder().self_ty().is_param(def.index) + data.skip_binder().self_ty().is_param(index) } ty::Predicate::TypeOutlives(ref data) => { - data.skip_binder().0.is_param(def.index) + data.skip_binder().0.is_param(index) } ty::Predicate::Equate(..) | ty::Predicate::RegionOutlives(..) | @@ -568,7 +580,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics { fn get_type_parameter_bounds(&self, astconv: &AstConv<'tcx, 'tcx>, - _: Span, + span: Span, node_id: ast::NodeId) -> Vec> { @@ -576,8 +588,15 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics { // written inline like `` or in a where clause like // `where T:Foo`. - let def = astconv.tcx().type_parameter_def(node_id); - let ty = astconv.tcx().mk_param_from_def(&def); + let tcx = astconv.tcx(); + let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); + let index = match astconv.get_generics(span, item_def_id) { + Ok(generics) => { + generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index] + } + Err(ErrorReported) => return vec![] + }; + let ty = tcx.mk_param(index, ::ty_param_name(tcx, node_id)); let from_ty_params = self.ty_params @@ -594,7 +613,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics { hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), _ => None }) - .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id)) + .filter(|bp| is_param(tcx, &bp.bounded_ty, node_id)) .flat_map(|bp| bp.bounds.iter()) .flat_map(|b| predicates_from_bound(astconv, ty, b)); @@ -625,7 +644,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - struct_generics: &'tcx ty::Generics<'tcx>, + struct_generics: &'tcx ty::Generics, struct_predicates: &ty::GenericPredicates<'tcx>, field: &hir::StructField, ty_f: &'tcx ty::FieldDef) @@ -938,7 +957,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def: &'tcx ty::AdtDef, ty: Ty<'tcx>, - generics: &'tcx ty::Generics<'tcx>, + generics: &'tcx ty::Generics, predicates: ty::GenericPredicates<'tcx>, variants: &[hir::Variant]) { // fill the field types @@ -1325,7 +1344,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id: DefId) - -> &'tcx ty::Generics<'tcx> { + -> &'tcx ty::Generics { let tcx = ccx.tcx; let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { id @@ -1402,18 +1421,14 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // the node id for the Self type parameter. let param_id = item.id; - let parent = ccx.tcx.hir.get_parent(param_id); - - let def = ty::TypeParameterDef { + opt_self = Some(ty::TypeParameterDef { index: 0, name: keywords::SelfType.name(), def_id: tcx.hir.local_def_id(param_id), - default_def_id: tcx.hir.local_def_id(parent), - default: None, + has_default: false, + object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, - }; - tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); - opt_self = Some(def); + }); allow_defaults = true; generics @@ -1459,11 +1474,36 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }).collect::>(); + let object_lifetime_defaults = + tcx.named_region_map.object_lifetime_defaults.get(&node_id); + // Now create the real type parameters. let type_start = own_start + regions.len() as u32; let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { - let i = type_start + i as u32; - get_or_create_type_parameter_def(ccx, i, p, allow_defaults) + if p.name == keywords::SelfType.name() { + span_bug!(p.span, "`Self` should not be the name of a regular parameter"); + } + + if !allow_defaults && p.default.is_some() { + if !tcx.sess.features.borrow().default_type_parameter_fallback { + tcx.sess.add_lint( + lint::builtin::INVALID_TYPE_PARAM_DEFAULT, + p.id, + p.span, + format!("defaults for type parameters are only allowed in `struct`, \ + `enum`, `type`, or `trait` definitions.")); + } + } + + ty::TypeParameterDef { + index: type_start + i as u32, + name: p.name, + def_id: tcx.hir.local_def_id(p.id), + has_default: p.default.is_some(), + object_lifetime_default: + object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]), + pure_wrt_drop: p.pure_wrt_drop, + } }); let mut types: Vec<_> = opt_self.into_iter().chain(types).collect(); @@ -1476,19 +1516,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, index: type_start + i as u32, name: Symbol::intern(""), def_id: def_id, - default_def_id: parent_def_id.unwrap(), - default: None, + has_default: false, + object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, })); }); } + let mut type_param_to_index = BTreeMap::new(); + for param in &types { + type_param_to_index.insert(param.def_id.index, param.index); + } + tcx.alloc_generics(ty::Generics { parent: parent_def_id, parent_regions: parent_regions, parent_types: parent_types, regions: regions, types: types, + type_param_to_index: type_param_to_index, has_self: has_self || parent_has_self }) }) @@ -1576,6 +1622,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, |def, _| ccx.tcx.mk_param_from_def(def) )) } + NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { + ccx.icx(&()).to_ty(ty) + } x => { bug!("unexpected sort of node in type_of_def_id(): {:?}", x); } @@ -1808,54 +1857,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } -fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - index: u32, - param: &hir::TyParam, - allow_defaults: bool) - -> ty::TypeParameterDef<'tcx> -{ - let tcx = ccx.tcx; - match tcx.ty_param_defs.borrow().get(¶m.id) { - Some(d) => { return d.clone(); } - None => { } - } - - let default = - param.default.as_ref().map(|def| ccx.icx(&()).to_ty(def)); - - let parent = tcx.hir.get_parent(param.id); - - if !allow_defaults && default.is_some() { - if !tcx.sess.features.borrow().default_type_parameter_fallback { - tcx.sess.add_lint( - lint::builtin::INVALID_TYPE_PARAM_DEFAULT, - param.id, - param.span, - format!("defaults for type parameters are only allowed in `struct`, \ - `enum`, `type`, or `trait` definitions.")); - } - } - - let def = ty::TypeParameterDef { - index: index, - name: param.name, - def_id: ccx.tcx.hir.local_def_id(param.id), - default_def_id: ccx.tcx.hir.local_def_id(parent), - default: default, - pure_wrt_drop: param.pure_wrt_drop, - }; - - if def.name == keywords::SelfType.name() { - span_bug!(param.span, "`Self` should not be the name of a regular parameter"); - } - - tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); - - debug!("get_or_create_type_parameter_def: def for type param: {:?}", def); - - def -} - pub enum SizedByDefault { Yes, No, } /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 5bfc3a934af05..1ff6944d98dd3 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1701,33 +1701,6 @@ struct Foo { ``` "##, -E0128: r##" -Type parameter defaults can only use parameters that occur before them. -Erroneous code example: - -```compile_fail,E0128 -struct Foo { - field1: T, - filed2: U, -} -// error: type parameters with a default cannot use forward declared -// identifiers -``` - -Since type parameters are evaluated in-order, you may be able to fix this issue -by doing: - -``` -struct Foo { - field1: T, - filed2: U, -} -``` - -Please also verify that this wasn't because of a name-clash and rename the type -parameter if so. -"##, - E0131: r##" It is not possible to define `main` with type parameters, or even with function parameters. When `main` is present, it must take no arguments and return `()`. diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 0bcf8ab7d6c20..03175782c38fd 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -116,6 +116,7 @@ use util::common::time; use syntax::ast; use syntax::abi::Abi; +use syntax::symbol::keywords; use syntax_pos::Span; use std::iter; @@ -193,6 +194,30 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) } +fn ty_param_owner(tcx: TyCtxt, id: ast::NodeId) -> ast::NodeId { + match tcx.hir.get(id) { + hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => id, + hir::map::NodeTyParam(_) => tcx.hir.get_parent_node(id), + _ => { + bug!("ty_param_owner: {} not a type parameter", + tcx.hir.node_to_string(id)) + } + } +} + +fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name { + match tcx.hir.get(id) { + hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => { + keywords::SelfType.name() + } + hir::map::NodeTyParam(tp) => tp.name, + _ => { + bug!("ty_param_name: {} not a type parameter", + tcx.hir.node_to_string(id)) + } + } +} + fn check_main_fn_ty(ccx: &CrateCtxt, main_id: ast::NodeId, main_span: Span) { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 860f6d98370ad..b22db94079891 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -279,7 +279,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } fn add_constraints_from_trait_ref(&mut self, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, trait_ref: ty::TraitRef<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}", @@ -305,7 +305,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// in a context with the generics defined in `generics` and /// ambient variance `variance` fn add_constraints_from_ty(&mut self, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, ty: Ty<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_ty(ty={:?}, variance={:?})", @@ -433,9 +433,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a nominal type (enum, struct, /// object, etc) appearing in a context with ambient variance `variance` fn add_constraints_from_substs(&mut self, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, def_id: DefId, - type_param_defs: &[ty::TypeParameterDef<'tcx>], + type_param_defs: &[ty::TypeParameterDef], region_param_defs: &[ty::RegionParameterDef], substs: &Substs<'tcx>, variance: VarianceTermPtr<'a>) { @@ -465,7 +465,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a function with signature /// `sig` appearing in a context with ambient variance `variance` fn add_constraints_from_sig(&mut self, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, sig: &ty::PolyFnSig<'tcx>, variance: VarianceTermPtr<'a>) { let contra = self.contravariant(variance); @@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a region appearing in a /// context with ambient variance `variance` fn add_constraints_from_region(&mut self, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, region: &'tcx ty::Region, variance: VarianceTermPtr<'a>) { match *region { @@ -518,7 +518,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for a mutability-type pair /// appearing in a context with ambient variance `variance` fn add_constraints_from_mt(&mut self, - generics: &ty::Generics<'tcx>, + generics: &ty::Generics, mt: &ty::TypeAndMut<'tcx>, variance: VarianceTermPtr<'a>) { match mt.mutbl { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 751ed7d443d29..dc09fc2b8d3cc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -596,14 +596,18 @@ impl Clean for hir::TyParam { } } -impl<'tcx> Clean for ty::TypeParameterDef<'tcx> { +impl<'tcx> Clean for ty::TypeParameterDef { fn clean(&self, cx: &DocContext) -> TyParam { cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx)); TyParam { name: self.name.clean(cx), did: self.def_id, bounds: vec![], // these are filled in from the where-clauses - default: self.default.clean(cx), + default: if self.has_default { + Some(cx.tcx.item_type(self.def_id).clean(cx)) + } else { + None + } } } } @@ -965,7 +969,7 @@ impl Clean for hir::Generics { } } -impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, +impl<'a, 'tcx> Clean for (&'a ty::Generics, &'a ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext) -> Generics { use self::WherePredicate as WP; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index bfab7a250c67f..013632141dee6 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -68,6 +68,9 @@ pub trait Visitor<'ast>: Sized { fn visit_expr_post(&mut self, _ex: &'ast Expr) { } fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } + fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { + walk_where_predicate(self, p) + } fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) { walk_fn(self, fk, fd, s) } @@ -488,28 +491,30 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics walk_list!(visitor, visit_attribute, &*param.attrs); } walk_list!(visitor, visit_lifetime_def, &generics.lifetimes); - for predicate in &generics.where_clause.predicates { - match *predicate { - WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, - ref bounds, - ref bound_lifetimes, - ..}) => { - visitor.visit_ty(bounded_ty); - walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_lifetime_def, bound_lifetimes); - } - WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, - ref bounds, - ..}) => { - visitor.visit_lifetime(lifetime); - walk_list!(visitor, visit_lifetime, bounds); - } - WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty, - ref rhs_ty, - ..}) => { - visitor.visit_ty(lhs_ty); - visitor.visit_ty(rhs_ty); - } + walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); +} + +pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) { + match *predicate { + WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, + ref bounds, + ref bound_lifetimes, + ..}) => { + visitor.visit_ty(bounded_ty); + walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_lifetime_def, bound_lifetimes); + } + WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, + ref bounds, + ..}) => { + visitor.visit_lifetime(lifetime); + walk_list!(visitor, visit_lifetime, bounds); + } + WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty, + ref rhs_ty, + ..}) => { + visitor.visit_ty(lhs_ty); + visitor.visit_ty(rhs_ty); } } } diff --git a/src/test/compile-fail/cycle-trait-default-type-trait.rs b/src/test/compile-fail/cycle-trait-default-type-trait.rs index e6caeb34a8c8f..6825572b26c83 100644 --- a/src/test/compile-fail/cycle-trait-default-type-trait.rs +++ b/src/test/compile-fail/cycle-trait-default-type-trait.rs @@ -13,6 +13,7 @@ trait Foo> { //~^ ERROR unsupported cyclic reference + //~| ERROR unsupported cyclic reference } fn main() { } diff --git a/src/test/compile-fail/generic-non-trailing-defaults.rs b/src/test/compile-fail/generic-non-trailing-defaults.rs index 77e5520326379..13b7753082c61 100644 --- a/src/test/compile-fail/generic-non-trailing-defaults.rs +++ b/src/test/compile-fail/generic-non-trailing-defaults.rs @@ -10,10 +10,10 @@ struct Heap; -struct Vec; +struct Vec(A, T); //~^ ERROR type parameters with a default must be trailing -struct Foo, C>; +struct Foo, C>(A, B, C); //~^ ERROR type parameters with a default must be trailing //~| ERROR type parameters with a default cannot use forward declared identifiers diff --git a/src/test/compile-fail/generic-type-params-forward-mention.rs b/src/test/compile-fail/generic-type-params-forward-mention.rs index eda1b014fa7a4..bfa6af0da433b 100644 --- a/src/test/compile-fail/generic-type-params-forward-mention.rs +++ b/src/test/compile-fail/generic-type-params-forward-mention.rs @@ -9,7 +9,7 @@ // except according to those terms. // Ensure that we get an error and not an ICE for this problematic case. -struct Foo, U = bool>; +struct Foo, U = bool>(T, U); //~^ ERROR type parameters with a default cannot use forward declared identifiers fn main() { let x: Foo; diff --git a/src/test/compile-fail/issue-18183.rs b/src/test/compile-fail/issue-18183.rs index b3fc3aea148ee..feab04531b7e1 100644 --- a/src/test/compile-fail/issue-18183.rs +++ b/src/test/compile-fail/issue-18183.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct Foo; //~ ERROR E0128 - //~| NOTE defaulted type parameters cannot be forward declared +pub struct Foo(Bar); //~ ERROR E0128 + //~| NOTE defaulted type parameters cannot be forward declared pub struct Baz(Foo); fn main() {} diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs index 04f98c7ab329f..ab9ac03982599 100644 --- a/src/test/compile-fail/resolve-self-in-impl.rs +++ b/src/test/compile-fail/resolve-self-in-impl.rs @@ -15,7 +15,7 @@ impl Tr for S {} // OK // FIXME: `Self` cannot be used in bounds because it depends on bounds itself. impl> Tr for S {} //~ ERROR `Self` type is used before it's determined -impl Tr for S {} //~ ERROR `Self` type is used before it's determined +impl Tr for S {} impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined impl Tr for S where S: Copy {} //~ ERROR `Self` type is used before it's determined impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined From 86e402904ae68e3a72e5c88d0a1722ab753f98d8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 2 Feb 2017 14:18:13 +0200 Subject: [PATCH 02/17] rustc_typeck: simplify AstConv requests as implemented by collect. --- src/librustc_typeck/astconv.rs | 80 +- src/librustc_typeck/check/mod.rs | 22 +- src/librustc_typeck/collect.rs | 748 +++++++----------- src/test/compile-fail/resolve-self-in-impl.rs | 28 +- .../run-pass/associated-types-sugar-path.rs | 3 + src/test/ui/resolve/issue-23305.stderr | 11 +- 6 files changed, 350 insertions(+), 542 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8f556726f22f5..cd7474cf50b8c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -52,16 +52,14 @@ pub trait AstConv<'gcx, 'tcx> { fn ast_ty_to_ty_cache(&self) -> &RefCell>>; /// Returns the generic type and lifetime parameters for an item. - fn get_generics(&self, span: Span, id: DefId) - -> Result<&'tcx ty::Generics, ErrorReported>; + fn get_generics(&self, id: DefId) -> &'tcx ty::Generics; /// Identify the type for an item, like a type alias, fn, or struct. - fn get_item_type(&self, span: Span, id: DefId) -> Result, ErrorReported>; + fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx>; /// Returns the `TraitDef` for a given trait. This allows you to /// figure out the set of type parameters defined on the trait. - fn get_trait_def(&self, span: Span, id: DefId) - -> Result<&'tcx ty::TraitDef, ErrorReported>; + fn get_trait_def(&self, id: DefId) -> &'tcx ty::TraitDef; /// Ensure that the super-predicates for the trait with the given /// id are available and also for the transitive set of @@ -251,14 +249,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - let decl_generics = match self.get_generics(span, def_id) { - Ok(generics) => generics, - Err(ErrorReported) => { - // No convenient way to recover from a cycle here. Just bail. Sorry! - self.tcx().sess.abort_if_errors(); - bug!("ErrorReported returned, but no errors reports?") - } - }; + let decl_generics = self.get_generics(def_id); let expected_num_region_params = decl_generics.regions.len(); let supplied_num_region_params = lifetimes.len(); if expected_num_region_params != supplied_num_region_params { @@ -279,8 +270,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let default_needs_object_self = |p: &ty::TypeParameterDef| { if is_object && p.has_default { - let default = self.get_item_type(span, p.def_id).ok(); - if default.has_self_ty() { + if self.get_item_type(span, p.def_id).has_self_ty() { // There is no suitable inference default for a type parameter // that references self, in an object type. return true; @@ -347,10 +337,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.err } else { // This is a default type parameter. - match self.get_item_type(span, def.def_id) { - Ok(ty) => ty.subst_spanned(tcx, substs, Some(span)), - Err(ErrorReported) => tcx.types.err - } + self.get_item_type(span, def.def_id).subst_spanned(tcx, substs, Some(span)) } } else { // We've already errored above about the mismatch. @@ -499,14 +486,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); - let trait_def = match self.get_trait_def(span, trait_def_id) { - Ok(trait_def) => trait_def, - Err(ErrorReported) => { - // No convenient way to recover from a cycle here. Just bail. Sorry! - self.tcx().sess.abort_if_errors(); - bug!("ErrorReported returned, but no errors reports?") - } - }; + let trait_def = self.get_trait_def(trait_def_id); match trait_segment.parameters { hir::AngleBracketedParameters(_) => { @@ -647,16 +627,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { item_segment: &hir::PathSegment) -> Ty<'tcx> { - let tcx = self.tcx(); - let decl_ty = match self.get_item_type(span, did) { - Ok(ty) => ty, - Err(ErrorReported) => { - return tcx.types.err; - } - }; - let substs = self.ast_path_substs_for_ty(span, did, item_segment); - decl_ty.subst(self.tcx(), substs) + self.get_item_type(span, did).subst(self.tcx(), substs) } /// Transform a PolyTraitRef into a PolyExistentialTraitRef by @@ -1058,14 +1030,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.prohibit_type_params(&path.segments); let node_id = tcx.hir.as_local_node_id(did).unwrap(); - let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); - let index = match self.get_generics(span, item_def_id) { - Ok(generics) => { - generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index] - } - Err(ErrorReported) => return tcx.types.err - }; - tcx.mk_param(index, ::ty_param_name(tcx, node_id)) + let item_id = tcx.hir.get_parent_node(node_id); + let item_def_id = tcx.hir.local_def_id(item_id); + let generics = self.get_generics(item_def_id); + let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; + tcx.mk_param(index, tcx.hir.name(node_id)) } Def::SelfTy(_, Some(def_id)) => { // Self in impl (we know the concrete type). @@ -1073,22 +1042,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { assert_eq!(opt_self_ty, None); tcx.prohibit_type_params(&path.segments); - // 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. - let ty = if def_id.is_local() { - tcx.item_types.borrow().get(&def_id).cloned() - } else { - Some(tcx.item_type(def_id)) - }; - if let Some(ty) = ty { - if let Some(free_substs) = self.get_free_substs() { - ty.subst(tcx, free_substs) - } else { - ty - } + let ty = self.get_item_type(span, def_id); + if let Some(free_substs) = self.get_free_substs() { + ty.subst(tcx, free_substs) } else { - tcx.sess.span_err(span, "`Self` type is used before it's determined"); - tcx.types.err + ty } } Def::SelfTy(Some(_), None) => { @@ -1241,9 +1199,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Create the anonymized type. if allow { let def_id = tcx.hir.local_def_id(ast_ty.id); - if let Err(ErrorReported) = self.get_generics(ast_ty.span, def_id) { - return tcx.types.err; - } + self.get_generics(def_id); let substs = Substs::identity_for_item(tcx, def_id); let ty = tcx.mk_anon(tcx.hir.local_def_id(ast_ty.id), substs); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 60805625b7b32..d4895d638ba0d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,7 +91,7 @@ use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; -use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility}; +use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPolyTraitRef}; use rustc::ty::{MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; @@ -1359,21 +1359,16 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { &self.ast_ty_to_ty_cache } - fn get_generics(&self, _: Span, id: DefId) - -> Result<&'tcx ty::Generics, ErrorReported> - { - Ok(self.tcx().item_generics(id)) + fn get_generics(&self, id: DefId) -> &'tcx ty::Generics { + self.tcx().item_generics(id) } - fn get_item_type(&self, _: Span, id: DefId) -> Result, ErrorReported> - { - Ok(self.tcx().item_type(id)) + fn get_item_type(&self, _: Span, id: DefId) -> Ty<'tcx> { + self.tcx().item_type(id) } - fn get_trait_def(&self, _: Span, id: DefId) - -> Result<&'tcx ty::TraitDef, ErrorReported> - { - Ok(self.tcx().lookup_trait_def(id)) + fn get_trait_def(&self, id: DefId) -> &'tcx ty::TraitDef { + self.tcx().lookup_trait_def(id) } fn ensure_super_predicates(&self, _: Span, _: DefId) -> Result<(), ErrorReported> { @@ -1391,7 +1386,8 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { -> Result>, ErrorReported> { let tcx = self.tcx; - let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); + let item_id = ::ty_param_owner(tcx, node_id); + let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.item_generics(item_def_id); let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; let r = self.parameter_environment diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d168f5d424105..975a9aa994624 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -104,21 +104,17 @@ pub fn collect_item_types(ccx: &CrateCtxt) { /// available in various different forms at various points in the /// process. So we can't just store a pointer to e.g. the AST or the /// parsed ty form, we have to be more flexible. To this end, the -/// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object -/// that it uses to satisfy `get_type_parameter_bounds` requests. -/// This object might draw the information from the AST -/// (`hir::Generics`) or it might draw from a `ty::GenericPredicates` -/// or both (a tuple). +/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy +/// `get_type_parameter_bounds` requests, drawing the information from +/// the AST (`hir::Generics`), recursively. struct ItemCtxt<'a,'tcx:'a> { ccx: &'a CrateCtxt<'a,'tcx>, - param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a), + item_def_id: DefId, } #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstConvRequest { - GetGenerics(DefId), - GetItemTypeScheme(DefId), - GetTraitDef(DefId), + GetItemType(DefId), EnsureSuperPredicates(DefId), GetTypeParameterBounds(ast::NodeId), } @@ -234,10 +230,10 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { // Utility types and common code for the above passes. impl<'a,'tcx> CrateCtxt<'a,'tcx> { - fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> { + fn icx(&'a self, item_def_id: DefId) -> ItemCtxt<'a,'tcx> { ItemCtxt { ccx: self, - param_bounds: param_bounds, + item_def_id: item_def_id, } } @@ -276,9 +272,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { err.span_label(span, &format!("cyclic reference")); match cycle[0] { - AstConvRequest::GetGenerics(def_id) | - AstConvRequest::GetItemTypeScheme(def_id) | - AstConvRequest::GetTraitDef(def_id) => { + AstConvRequest::GetItemType(def_id) => { err.note( &format!("the cycle begins when processing `{}`...", tcx.item_path_str(def_id))); @@ -298,9 +292,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { for request in &cycle[1..] { match *request { - AstConvRequest::GetGenerics(def_id) | - AstConvRequest::GetItemTypeScheme(def_id) | - AstConvRequest::GetTraitDef(def_id) => { + AstConvRequest::GetItemType(def_id) => { err.note( &format!("...which then requires processing `{}`...", tcx.item_path_str(def_id))); @@ -320,9 +312,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { } match cycle[0] { - AstConvRequest::GetGenerics(def_id) | - AstConvRequest::GetItemTypeScheme(def_id) | - AstConvRequest::GetTraitDef(def_id) => { + AstConvRequest::GetItemType(def_id) => { err.note( &format!("...which then again requires processing `{}`, completing the cycle.", tcx.item_path_str(def_id))); @@ -343,25 +333,6 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { err.emit(); } - /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises. - fn get_trait_def(&self, def_id: DefId) - -> &'tcx ty::TraitDef - { - let tcx = self.tcx; - - if let Some(trait_id) = tcx.hir.as_local_node_id(def_id) { - let item = match tcx.hir.get(trait_id) { - hir_map::NodeItem(item) => item, - _ => bug!("get_trait_def({:?}): not an item", trait_id) - }; - - generics_of_def_id(self, def_id); - trait_def_of_item(self, &item) - } else { - tcx.lookup_trait_def(def_id) - } - } - /// Ensure that the (transitive) super predicates for /// `trait_def_id` are available. This will report a cycle error /// if a trait `X` (transitively) extends itself in some form. @@ -393,26 +364,24 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { &self.ccx.ast_ty_to_ty_cache } - fn get_generics(&self, span: Span, id: DefId) - -> Result<&'tcx ty::Generics, ErrorReported> - { - self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || { - Ok(generics_of_def_id(self.ccx, id)) - }) + fn get_generics(&self, id: DefId) -> &'tcx ty::Generics { + generics_of_def_id(self.ccx, id) } - fn get_item_type(&self, span: Span, id: DefId) -> Result, ErrorReported> { - self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || { + fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx> { + self.ccx.cycle_check(span, AstConvRequest::GetItemType(id), || { Ok(type_of_def_id(self.ccx, id)) - }) + }).unwrap_or(self.ccx.tcx.types.err) } - fn get_trait_def(&self, span: Span, id: DefId) - -> Result<&'tcx ty::TraitDef, ErrorReported> - { - self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || { - Ok(self.ccx.get_trait_def(id)) - }) + fn get_trait_def(&self, def_id: DefId) -> &'tcx ty::TraitDef { + let tcx = self.ccx.tcx; + + if let Some(trait_id) = tcx.hir.as_local_node_id(def_id) { + trait_def_of_item(self.ccx, tcx.hir.expect_item(trait_id)) + } else { + tcx.lookup_trait_def(def_id) + } } fn ensure_super_predicates(&self, @@ -426,17 +395,16 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { self.ccx.ensure_super_predicates(span, trait_def_id) } - fn get_type_parameter_bounds(&self, span: Span, node_id: ast::NodeId) -> Result>, ErrorReported> { self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || { - let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id) - .into_iter() - .filter_map(|p| p.to_opt_poly_trait_ref()) - .collect(); + let v = self.ccx.get_type_parameter_bounds(self.item_def_id, node_id) + .into_iter() + .filter_map(|p| p.to_opt_poly_trait_ref()) + .collect(); Ok(v) }) } @@ -492,130 +460,119 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } } -/// Interface used to find the bounds on a type parameter from within -/// an `ItemCtxt`. This allows us to use multiple kinds of sources. -trait GetTypeParameterBounds<'tcx> { - fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx, 'tcx>, - span: Span, - node_id: ast::NodeId) - -> Vec>; -} - -/// Find bounds from both elements of the tuple. -impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B) - where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx> -{ +impl<'a, 'tcx> CrateCtxt<'a, 'tcx> { fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx, 'tcx>, - span: Span, - node_id: ast::NodeId) + item_def_id: DefId, + param_id: ast::NodeId) -> Vec> { - let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id); - v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id)); - v - } -} + use rustc::hir::map::*; + use rustc::hir::*; -/// Empty set of bounds. -impl<'tcx> GetTypeParameterBounds<'tcx> for () { - fn get_type_parameter_bounds(&self, - _astconv: &AstConv<'tcx, 'tcx>, - _span: Span, - _node_id: ast::NodeId) - -> Vec> - { - Vec::new() - } -} + // In the AST, bounds can derive from two places. Either + // written inline like `` or in a where clause like + // `where T:Foo`. -/// Find bounds from the parsed and converted predicates. This is -/// used when converting methods, because by that time the predicates -/// from the trait/impl have been fully converted. -impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { - fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx, 'tcx>, - span: Span, - node_id: ast::NodeId) - -> Vec> - { - let tcx = astconv.tcx(); - let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); - let generics = tcx.item_generics(item_def_id); - let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; - - let mut results = self.parent.map_or(vec![], |def_id| { - let parent = tcx.item_predicates(def_id); - parent.get_type_parameter_bounds(astconv, span, node_id) + let tcx = self.tcx; + let param_owner_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, param_id)); + let generics = generics_of_def_id(self, param_owner_def_id); + let index = generics.type_param_to_index[&tcx.hir.local_def_id(param_id).index]; + let ty = tcx.mk_param(index, ::ty_param_name(tcx, param_id)); + + // Don't look for bounds where the type parameter isn't in scope. + let parent = if item_def_id == param_owner_def_id { + None + } else { + generics_of_def_id(self, item_def_id).parent + }; + + let mut results = parent.map_or(vec![], |def_id| { + self.get_type_parameter_bounds(def_id, param_id) }); - results.extend(self.predicates.iter().filter(|predicate| { - match **predicate { - ty::Predicate::Trait(ref data) => { - data.skip_binder().self_ty().is_param(index) + let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); + let ast_generics = match tcx.hir.get(item_node_id) { + NodeTraitItem(item) => { + match item.node { + TraitItemKind::Method(ref sig, _) => &sig.generics, + _ => return results } - ty::Predicate::TypeOutlives(ref data) => { - data.skip_binder().0.is_param(index) + } + + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => &sig.generics, + _ => return results } - ty::Predicate::Equate(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::WellFormed(..) | - ty::Predicate::ObjectSafe(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::Projection(..) => { - false + } + + NodeItem(item) => { + match item.node { + ItemFn(.., ref generics, _) | + ItemImpl(_, _, ref generics, ..) | + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) | + ItemUnion(_, ref generics) => generics, + ItemTrait(_, ref generics, ..) => { + // Implied `Self: Trait` and supertrait bounds. + if param_id == item_node_id { + results.push(ty::TraitRef { + def_id: item_def_id, + substs: mk_item_substs(self, item_def_id) + }.to_predicate()); + } + generics + } + _ => return results } } - }).cloned()); + NodeForeignItem(item) => { + match item.node { + ForeignItemFn(_, _, ref generics) => generics, + _ => return results + } + } + + _ => return results + }; + + let icx = self.icx(item_def_id); + results.extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); results } } -/// Find bounds from hir::Generics. This requires scanning through the -/// AST. We do this to avoid having to convert *all* the bounds, which -/// would create artificial cycles. Instead we can only convert the -/// bounds for a type parameter `X` if `X::Foo` is used. -impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics { - fn get_type_parameter_bounds(&self, - astconv: &AstConv<'tcx, 'tcx>, - span: Span, - node_id: ast::NodeId) - -> Vec> +impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { + /// Find bounds from hir::Generics. This requires scanning through the + /// AST. We do this to avoid having to convert *all* the bounds, which + /// would create artificial cycles. Instead we can only convert the + /// bounds for a type parameter `X` if `X::Foo` is used. + fn type_parameter_bounds_in_generics(&self, + ast_generics: &hir::Generics, + param_id: ast::NodeId, + ty: Ty<'tcx>) + -> Vec> { - // In the AST, bounds can derive from two places. Either - // written inline like `` or in a where clause like - // `where T:Foo`. - - let tcx = astconv.tcx(); - let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id)); - let index = match astconv.get_generics(span, item_def_id) { - Ok(generics) => { - generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index] - } - Err(ErrorReported) => return vec![] - }; - let ty = tcx.mk_param(index, ::ty_param_name(tcx, node_id)); - let from_ty_params = - self.ty_params + ast_generics.ty_params .iter() - .filter(|p| p.id == node_id) + .filter(|p| p.id == param_id) .flat_map(|p| p.bounds.iter()) - .flat_map(|b| predicates_from_bound(astconv, ty, b)); + .flat_map(|b| predicates_from_bound(self, ty, b)); let from_where_clauses = - self.where_clause + ast_generics.where_clause .predicates .iter() .filter_map(|wp| match *wp { hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), _ => None }) - .filter(|bp| is_param(tcx, &bp.bounded_ty, node_id)) + .filter(|bp| is_param(self.ccx.tcx, &bp.bounded_ty, param_id)) .flat_map(|bp| bp.bounds.iter()) - .flat_map(|b| predicates_from_bound(astconv, ty, b)); + .flat_map(|b| predicates_from_bound(self, ty, b)); from_ty_params.chain(from_where_clauses).collect() } @@ -644,38 +601,27 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - struct_generics: &'tcx ty::Generics, - struct_predicates: &ty::GenericPredicates<'tcx>, field: &hir::StructField, ty_f: &'tcx ty::FieldDef) { - let tt = ccx.icx(struct_predicates).to_ty(&field.ty); + generics_of_def_id(ccx, ty_f.did); + let tt = ccx.icx(ty_f.did).to_ty(&field.ty); ccx.tcx.item_types.borrow_mut().insert(ty_f.did, tt); - - let def_id = ccx.tcx.hir.local_def_id(field.id); - assert_eq!(def_id, ty_f.did); - ccx.tcx.generics.borrow_mut().insert(def_id, struct_generics); - ccx.tcx.predicates.borrow_mut().insert(def_id, struct_predicates.clone()); + ccx.tcx.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { + parent: Some(ccx.tcx.hir.get_parent_did(field.id)), + predicates: vec![] + }); } -fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - id: ast::NodeId, - sig: &hir::MethodSig, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) { +fn convert_method(ccx: &CrateCtxt, id: ast::NodeId, sig: &hir::MethodSig) { let def_id = ccx.tcx.hir.local_def_id(id); - let ty_generics = generics_of_def_id(ccx, def_id); - - let ty_generic_predicates = - ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false); - - let fty = AstConv::ty_of_fn(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), - sig.unsafety, sig.abi, &sig.decl); - let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), - ccx.tcx.hir.span(id), def_id); + let fty = AstConv::ty_of_fn(&ccx.icx(def_id), sig.unsafety, sig.abi, &sig.decl); + let substs = mk_item_substs(ccx, def_id); let fty = ccx.tcx.mk_fn_def(def_id, substs, fty); ccx.tcx.item_types.borrow_mut().insert(def_id, fty); - ccx.tcx.predicates.borrow_mut().insert(def_id, ty_generic_predicates); + + ty_generic_predicates(ccx, def_id, &sig.generics); } fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -752,6 +698,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let tcx = ccx.tcx; debug!("convert: item {} with id {}", it.name, it.id); let def_id = ccx.tcx.hir.local_def_id(it.id); + let icx = ccx.icx(def_id); match it.node { // These don't define types. hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => { @@ -762,19 +709,17 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } hir::ItemEnum(ref enum_definition, _) => { + generics_of_def_id(ccx, def_id); + predicates_of_item(ccx, it); let ty = type_of_def_id(ccx, def_id); - let generics = generics_of_def_id(ccx, def_id); - let predicates = predicates_of_item(ccx, it); convert_enum_variant_types(ccx, tcx.lookup_adt_def(ccx.tcx.hir.local_def_id(it.id)), ty, - generics, - predicates, &enum_definition.variants); }, hir::ItemDefaultImpl(_, ref ast_trait_ref) => { let trait_ref = - AstConv::instantiate_mono_trait_ref(&ccx.icx(&()), + AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, tcx.mk_self_type()); @@ -783,73 +728,50 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.impl_trait_refs.borrow_mut().insert(ccx.tcx.hir.local_def_id(it.id), Some(trait_ref)); } - hir::ItemImpl(.., - ref generics, - ref opt_trait_ref, - ref selfty, - _) => { - // Create generics from the generics specified in the impl head. - debug!("convert: ast_generics={:?}", generics); + hir::ItemImpl(.., ref opt_trait_ref, _, _) => { generics_of_def_id(ccx, def_id); - let mut ty_predicates = - ty_generic_predicates(ccx, generics, None, vec![], false); - - debug!("convert: impl_bounds={:?}", ty_predicates); - - let selfty = ccx.icx(&ty_predicates).to_ty(&selfty); - tcx.item_types.borrow_mut().insert(def_id, selfty); + let selfty = type_of_def_id(ccx, def_id); let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { - AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), - ast_trait_ref, - selfty) + AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) }); tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref); - // Subtle: before we store the predicates into the tcx, we - // sort them so that predicates like `T: Foo` come - // before uses of `U`. This avoids false ambiguity errors - // in trait checking. See `setup_constraining_predicates` - // for details. - ctp::setup_constraining_predicates(&mut ty_predicates.predicates, - trait_ref, - &mut ctp::parameters_for_impl(selfty, trait_ref)); - - tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone()); + predicates_of_item(ccx, it); }, hir::ItemTrait(..) => { generics_of_def_id(ccx, def_id); trait_def_of_item(ccx, it); let _: Result<(), ErrorReported> = // any error is already reported, can ignore ccx.ensure_super_predicates(it.span, def_id); - convert_trait_predicates(ccx, it); + predicates_of_item(ccx, it); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { + generics_of_def_id(ccx, def_id); + predicates_of_item(ccx, it); let ty = type_of_def_id(ccx, def_id); - let generics = generics_of_def_id(ccx, def_id); - let predicates = predicates_of_item(ccx, it); let variant = tcx.lookup_adt_def(def_id).struct_variant(); for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) { - convert_field(ccx, generics, &predicates, f, ty_f) + convert_field(ccx, f, ty_f) } if !struct_def.is_struct() { - convert_variant_ctor(ccx, struct_def.id(), variant, ty, predicates); + convert_variant_ctor(ccx, struct_def.id(), variant, ty); } }, hir::ItemTy(_, ref generics) => { ensure_no_ty_param_bounds(ccx, it.span, generics, "type"); - type_of_def_id(ccx, def_id); generics_of_def_id(ccx, def_id); predicates_of_item(ccx, it); + type_of_def_id(ccx, def_id); }, _ => { - type_of_def_id(ccx, def_id); generics_of_def_id(ccx, def_id); predicates_of_item(ccx, it); + type_of_def_id(ccx, def_id); }, } } @@ -860,13 +782,12 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) { // we can lookup details about the trait because items are visited // before trait-items let trait_def_id = tcx.hir.get_parent_did(trait_item.id); - let trait_predicates = tcx.item_predicates(trait_def_id); + let def_id = ccx.tcx.hir.local_def_id(trait_item.id); match trait_item.node { hir::TraitItemKind::Const(ref ty, _) => { - let const_def_id = ccx.tcx.hir.local_def_id(trait_item.id); - generics_of_def_id(ccx, const_def_id); - let ty = ccx.icx(&trait_predicates).to_ty(&ty); + generics_of_def_id(ccx, def_id); + let ty = ccx.icx(def_id).to_ty(&ty); convert_associated_const(ccx, TraitContainer(trait_def_id), trait_item.id, @@ -874,18 +795,15 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) { } hir::TraitItemKind::Type(_, ref opt_ty) => { - let type_def_id = ccx.tcx.hir.local_def_id(trait_item.id); - generics_of_def_id(ccx, type_def_id); + generics_of_def_id(ccx, def_id); - let typ = opt_ty.as_ref().map({ - |ty| ccx.icx(&trait_predicates).to_ty(&ty) - }); + let typ = opt_ty.as_ref().map(|ty| ccx.icx(def_id).to_ty(&ty)); convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ); } hir::TraitItemKind::Method(ref sig, _) => { - convert_method(ccx, trait_item.id, sig, &trait_predicates); + convert_method(ccx, trait_item.id, sig); } } } @@ -896,14 +814,12 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { // we can lookup details about the impl because items are visited // before impl-items let impl_def_id = tcx.hir.get_parent_did(impl_item.id); - let impl_predicates = tcx.item_predicates(impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + let def_id = ccx.tcx.hir.local_def_id(impl_item.id); match impl_item.node { hir::ImplItemKind::Const(ref ty, _) => { - let const_def_id = ccx.tcx.hir.local_def_id(impl_item.id); - generics_of_def_id(ccx, const_def_id); - let ty = ccx.icx(&impl_predicates).to_ty(&ty); + generics_of_def_id(ccx, def_id); + let ty = ccx.icx(def_id).to_ty(&ty); convert_associated_const(ccx, ImplContainer(impl_def_id), impl_item.id, @@ -911,21 +827,20 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { } hir::ImplItemKind::Type(ref ty) => { - let type_def_id = ccx.tcx.hir.local_def_id(impl_item.id); - generics_of_def_id(ccx, type_def_id); + generics_of_def_id(ccx, def_id); - if impl_trait_ref.is_none() { + if tcx.impl_trait_ref(impl_def_id).is_none() { span_err!(tcx.sess, impl_item.span, E0202, "associated types are not allowed in inherent impls"); } - let typ = ccx.icx(&impl_predicates).to_ty(ty); + let typ = ccx.icx(def_id).to_ty(ty); convert_associated_type(ccx, ImplContainer(impl_def_id), impl_item.id, Some(typ)); } hir::ImplItemKind::Method(ref sig, _) => { - convert_method(ccx, impl_item.id, sig, &impl_predicates); + convert_method(ccx, impl_item.id, sig); } } } @@ -933,8 +848,7 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ctor_id: ast::NodeId, variant: &'tcx ty::VariantDef, - ty: Ty<'tcx>, - predicates: ty::GenericPredicates<'tcx>) { + ty: Ty<'tcx>) { let tcx = ccx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); generics_of_def_id(ccx, def_id); @@ -942,7 +856,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, CtorKind::Fictive | CtorKind::Const => ty, CtorKind::Fn => { let inputs = variant.fields.iter().map(|field| tcx.item_type(field.did)); - let substs = mk_item_substs(&ccx.icx(&predicates), ccx.tcx.hir.span(ctor_id), def_id); + let substs = mk_item_substs(ccx, def_id); tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: abi::Abi::Rust, @@ -951,30 +865,25 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; tcx.item_types.borrow_mut().insert(def_id, ctor_ty); - tcx.predicates.borrow_mut().insert(tcx.hir.local_def_id(ctor_id), predicates); + tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + parent: Some(ccx.tcx.hir.get_parent_did(ctor_id)), + predicates: vec![] + }); } fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def: &'tcx ty::AdtDef, ty: Ty<'tcx>, - generics: &'tcx ty::Generics, - predicates: ty::GenericPredicates<'tcx>, variants: &[hir::Variant]) { // fill the field types for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) { for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) { - convert_field(ccx, generics, &predicates, f, ty_f) + convert_field(ccx, f, ty_f) } // Convert the ctor, if any. This also registers the variant as // an item. - convert_variant_ctor( - ccx, - variant.node.data.id(), - ty_variant, - ty, - predicates.clone() - ); + convert_variant_ctor(ccx, variant.node.data.id(), ty_variant, ty); } } @@ -1180,24 +1089,11 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, "ensure_super_predicates_step invoked on non-trait"), }; - // In-scope when converting the superbounds for `Trait` are - // that `Self:Trait` as well as any bounds that appear on the - // generic types: - generics_of_def_id(ccx, trait_def_id); - trait_def_of_item(ccx, item); - let trait_ref = ty::TraitRef { - def_id: trait_def_id, - substs: Substs::identity_for_item(tcx, trait_def_id) - }; - let self_predicate = ty::GenericPredicates { - parent: None, - predicates: vec![trait_ref.to_predicate()] - }; - let scope = &(generics, &self_predicate); + let icx = ccx.icx(trait_def_id); // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. let self_param_ty = tcx.mk_self_type(); - let superbounds1 = compute_bounds(&ccx.icx(scope), + let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, @@ -1207,7 +1103,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Convert any explicit superbounds in the where clause, // e.g. `trait Foo where Self : Bar`: - let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id); + let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty); // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2).collect(); @@ -1236,8 +1132,8 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, } fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef { - let def_id = ccx.tcx.hir.local_def_id(it.id); let tcx = ccx.tcx; + let def_id = tcx.hir.local_def_id(it.id); tcx.trait_defs.memoize(def_id, || { let unsafety = match it.node { @@ -1246,8 +1142,8 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'t }; let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar"); - if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures { - let mut err = ccx.tcx.sess.struct_span_err( + if paren_sugar && !tcx.sess.features.borrow().unboxed_closures { + let mut err = tcx.sess.struct_span_err( it.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ which traits can use parenthetical notation"); @@ -1262,86 +1158,6 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'t }) } -fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) { - let tcx = ccx.tcx; - - let def_id = ccx.tcx.hir.local_def_id(it.id); - - generics_of_def_id(ccx, def_id); - trait_def_of_item(ccx, it); - - let (generics, items) = match it.node { - hir::ItemTrait(_, ref generics, _, ref items) => (generics, items), - ref s => { - span_bug!( - it.span, - "trait_def_of_item invoked on {:?}", - s); - } - }; - - let super_predicates = ccx.tcx.item_super_predicates(def_id); - - // `ty_generic_predicates` below will consider the bounds on the type - // parameters (including `Self`) and the explicit where-clauses, - // but to get the full set of predicates on a trait we need to add - // in the supertrait bounds and anything declared on the - // associated types. - let mut base_predicates = super_predicates.predicates; - - // Add in a predicate that `Self:Trait` (where `Trait` is the - // current trait). This is needed for builtin bounds. - let trait_ref = ty::TraitRef { - def_id: def_id, - substs: Substs::identity_for_item(tcx, def_id) - }; - let self_predicate = trait_ref.to_poly_trait_ref().to_predicate(); - base_predicates.push(self_predicate); - - // add in the explicit where-clauses - let mut trait_predicates = - ty_generic_predicates(ccx, generics, None, base_predicates, true); - - let assoc_predicates = predicates_for_associated_types(ccx, - generics, - &trait_predicates, - trait_ref, - items); - trait_predicates.predicates.extend(assoc_predicates); - - tcx.predicates.borrow_mut().insert(def_id, trait_predicates); - return; - - fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - ast_generics: &hir::Generics, - trait_predicates: &ty::GenericPredicates<'tcx>, - self_trait_ref: ty::TraitRef<'tcx>, - trait_item_refs: &[hir::TraitItemRef]) - -> Vec> - { - trait_item_refs.iter().flat_map(|trait_item_ref| { - let trait_item = ccx.tcx.hir.trait_item(trait_item_ref.id); - let bounds = match trait_item.node { - hir::TraitItemKind::Type(ref bounds, _) => bounds, - _ => { - return vec![].into_iter(); - } - }; - - let assoc_ty = ccx.tcx.mk_projection(self_trait_ref, - trait_item.name); - - let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)), - assoc_ty, - bounds, - SizedByDefault::Yes, - trait_item.span); - - bounds.predicates(ccx.tcx, assoc_ty).into_iter() - }).collect() - } -} - fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id: DefId) -> &'tcx ty::Generics { @@ -1360,7 +1176,8 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, NodeImplItem(_) | NodeTraitItem(_) | NodeVariant(_) | - NodeStructCtor(_) => { + NodeStructCtor(_) | + NodeField(_) => { let parent_id = tcx.hir.get_parent(node_id); Some(tcx.hir.local_def_id(parent_id)) } @@ -1460,8 +1277,8 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics.parent_types + generics.types.len() as u32) }); - let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); - let regions = early_lifetimes.iter().enumerate().map(|(i, l)| { + let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); + let regions = early_lifetimes.enumerate().map(|(i, l)| { let issue_32330 = ccx.tcx.named_region_map.issue_32330 .get(&l.lifetime.id) .cloned(); @@ -1555,38 +1372,37 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Alway bring in generics, as computing the type needs them. generics_of_def_id(ccx, def_id); + let icx = ccx.icx(def_id); + let ty = match ccx.tcx.hir.get(node_id) { NodeItem(item) => { match item.node { - ItemStatic(ref t, ..) | ItemConst(ref t, _) => { - ccx.icx(&()).to_ty(&t) + ItemStatic(ref t, ..) | ItemConst(ref t, _) | + ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { + icx.to_ty(t) } - ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { - let tofd = AstConv::ty_of_fn(&ccx.icx(generics), unsafety, abi, &decl); - let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ItemFn(ref decl, unsafety, _, abi, _, _) => { + let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); + let substs = mk_item_substs(ccx, def_id); ccx.tcx.mk_fn_def(def_id, substs, tofd) } - ItemTy(ref t, ref generics) => { - ccx.icx(generics).to_ty(&t) - } - ItemEnum(ref ei, ref generics) => { + ItemEnum(ref ei, _) => { let def = convert_enum_def(ccx, item, ei); - let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + let substs = mk_item_substs(ccx, def_id); ccx.tcx.mk_adt(def, substs) } - ItemStruct(ref si, ref generics) => { + ItemStruct(ref si, _) => { let def = convert_struct_def(ccx, item, si); - let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + let substs = mk_item_substs(ccx, def_id); ccx.tcx.mk_adt(def, substs) } - ItemUnion(ref un, ref generics) => { + ItemUnion(ref un, _) => { let def = convert_union_def(ccx, item, un); - let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + let substs = mk_item_substs(ccx, def_id); ccx.tcx.mk_adt(def, substs) } ItemDefaultImpl(..) | ItemTrait(..) | - ItemImpl(..) | ItemMod(..) | ItemForeignMod(..) | ItemExternCrate(..) | @@ -1602,14 +1418,10 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let abi = ccx.tcx.hir.get_foreign_abi(node_id); match foreign_item.node { - ForeignItemFn(ref fn_decl, _, ref generics) => { - compute_type_of_foreign_fn_decl( - ccx, ccx.tcx.hir.local_def_id(foreign_item.id), - fn_decl, generics, abi) - } - ForeignItemStatic(ref t, _) => { - ccx.icx(&()).to_ty(t) + ForeignItemFn(ref fn_decl, _, _) => { + compute_type_of_foreign_fn_decl(ccx, def_id, fn_decl, abi) } + ForeignItemStatic(ref t, _) => icx.to_ty(t) } } NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { @@ -1623,7 +1435,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, )) } NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { - ccx.icx(&()).to_ty(ty) + icx.to_ty(ty) } x => { bug!("unexpected sort of node in type_of_def_id(): {:?}", x); @@ -1634,9 +1446,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) } -fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - it: &hir::Item) - -> ty::GenericPredicates<'tcx> { +fn predicates_of_item(ccx: &CrateCtxt, it: &hir::Item) { let def_id = ccx.tcx.hir.local_def_id(it.id); let no_generics = hir::Generics::empty(); @@ -1645,14 +1455,13 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ItemTy(_, ref generics) | hir::ItemEnum(_, ref generics) | hir::ItemStruct(_, ref generics) | - hir::ItemUnion(_, ref generics) => generics, + hir::ItemUnion(_, ref generics) | + hir::ItemTrait(_, ref generics, _, _) | + hir::ItemImpl(_, _, ref generics, ..) => generics, _ => &no_generics }; - let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); - ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone()); - - predicates + ty_generic_predicates(ccx, def_id, generics); } fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1663,8 +1472,8 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // moral failing, but at the moment it seems like the only // convenient way to extract the ABI. - ndm let def_id = ccx.tcx.hir.local_def_id(it.id); - type_of_def_id(ccx, def_id); generics_of_def_id(ccx, def_id); + type_of_def_id(ccx, def_id); let no_generics = hir::Generics::empty(); let generics = match it.node { @@ -1672,8 +1481,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ForeignItemStatic(..) => &no_generics }; - let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); - ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); + ty_generic_predicates(ccx, def_id, generics); } // Is it marked with ?Sized @@ -1725,60 +1533,72 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, /// the lifetimes that are declared. For fns or methods, we have to /// screen out those that do not appear in any where-clauses etc using /// `resolve_lifetime::early_bound_lifetimes`. -fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>( - ccx: &CrateCtxt<'a, 'tcx>, - ast_generics: &'hir hir::Generics) - -> Vec<&'hir hir::LifetimeDef> +fn early_bound_lifetimes_from_generics<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + ast_generics: &'a hir::Generics) + -> impl Iterator { ast_generics .lifetimes .iter() - .filter(|l| !ccx.tcx.named_region_map.late_bound.contains(&l.lifetime.id)) - .collect() + .filter(move |l| !tcx.named_region_map.late_bound.contains(&l.lifetime.id)) } -fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - ast_generics: &hir::Generics, - parent: Option, - super_predicates: Vec>, - has_self: bool) - -> ty::GenericPredicates<'tcx> -{ +fn ty_generic_predicates(ccx: &CrateCtxt, def_id: DefId, ast_generics: &hir::Generics) { let tcx = ccx.tcx; - let parent_count = parent.map_or(0, |def_id| { - let generics = generics_of_def_id(ccx, def_id); - assert_eq!(generics.parent, None); - assert_eq!(generics.parent_regions, 0); - assert_eq!(generics.parent_types, 0); - generics.count() as u32 - }); - let ref base_predicates = match parent { - Some(def_id) => { - assert_eq!(super_predicates, vec![]); - tcx.item_predicates(def_id) - } - None => { - ty::GenericPredicates { - parent: None, - predicates: super_predicates.clone() + let icx = ccx.icx(def_id); + let generics = generics_of_def_id(ccx, def_id); + let parent_count = generics.parent_count() as u32; + let has_own_self = generics.has_self && parent_count == 0; + + let mut predicates = vec![]; + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let (is_trait, is_impl) = match tcx.hir.get(node_id) { + hir::map::NodeItem(item) => { + match item.node { + hir::ItemTrait(.., ref items) => { + (Some((ty::TraitRef { + def_id: def_id, + substs: mk_item_substs(ccx, def_id) + }, items)), None) + } + hir::ItemImpl(..) => { + let self_ty = type_of_def_id(ccx, def_id); + let trait_ref = tcx.impl_trait_ref(def_id); + (None, Some((self_ty, trait_ref))) + } + _ => (None, None) } } + _ => (None, None) }; - let mut predicates = super_predicates; + + // Below we'll consider the bounds on the type parameters (including `Self`) + // and the explicit where-clauses, but to get the full set of predicates + // on a trait we need to add in the supertrait bounds and bounds found on + // associated types. + if let Some((trait_ref, _)) = is_trait { + predicates = tcx.item_super_predicates(def_id).predicates; + + // Add in a predicate that `Self:Trait` (where `Trait` is the + // current trait). This is needed for builtin bounds. + predicates.push(trait_ref.to_poly_trait_ref().to_predicate()); + } // Collect the region predicates that were declared inline as // well. In the case of parameters declared on a fn or method, we // have to be careful to only iterate over early-bound regions. - let own_start = parent_count + has_self as u32; - let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); - for (index, param) in early_lifetimes.iter().enumerate() { - let index = own_start + index as u32; - let region = ccx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { + let mut index = parent_count + has_own_self as u32; + for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { + let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { index: index, name: param.lifetime.name })); + index += 1; + for bound in ¶m.bounds { - let bound_region = AstConv::ast_region_to_region(&ccx.icx(&()), bound, None); + let bound_region = AstConv::ast_region_to_region(&icx, bound, None); let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); predicates.push(outlives.to_predicate()); } @@ -1786,16 +1606,16 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). - let type_start = own_start + early_lifetimes.len() as u32; - for (index, param) in ast_generics.ty_params.iter().enumerate() { - let index = type_start + index as u32; - let param_ty = ty::ParamTy::new(index, param.name).to_ty(ccx.tcx); - let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), + for param in &ast_generics.ty_params { + let param_ty = ty::ParamTy::new(index, param.name).to_ty(tcx); + index += 1; + + let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, SizedByDefault::Yes, param.span); - predicates.extend(bounds.predicates(ccx.tcx, param_ty)); + predicates.extend(bounds.predicates(tcx, param_ty)); } // Add in the bounds that appear in the where-clause @@ -1803,8 +1623,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for predicate in &where_clause.predicates { match predicate { &hir::WherePredicate::BoundPredicate(ref bound_pred) => { - let ty = AstConv::ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)), - &bound_pred.bounded_ty); + let ty = icx.to_ty(&bound_pred.bounded_ty); for bound in bound_pred.bounds.iter() { match bound { @@ -1812,8 +1631,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let mut projections = Vec::new(); let trait_ref = - AstConv::instantiate_poly_trait_ref(&ccx.icx(&(base_predicates, - ast_generics)), + AstConv::instantiate_poly_trait_ref(&icx, poly_trait_ref, ty, &mut projections); @@ -1826,7 +1644,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { - let region = AstConv::ast_region_to_region(&ccx.icx(&()), + let region = AstConv::ast_region_to_region(&icx, lifetime, None); let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); @@ -1837,9 +1655,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } &hir::WherePredicate::RegionPredicate(ref region_pred) => { - let r1 = AstConv::ast_region_to_region(&ccx.icx(&()), ®ion_pred.lifetime, None); + let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None); for bound in ®ion_pred.bounds { - let r2 = AstConv::ast_region_to_region(&ccx.icx(&()), bound, None); + let r2 = AstConv::ast_region_to_region(&icx, bound, None); let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); predicates.push(ty::Predicate::RegionOutlives(pred)) } @@ -1851,10 +1669,44 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } - ty::GenericPredicates { - parent: parent, - predicates: predicates + // Add predicates from associated type bounds. + if let Some((self_trait_ref, trait_items)) = is_trait { + predicates.extend(trait_items.iter().flat_map(|trait_item_ref| { + let trait_item = tcx.hir.trait_item(trait_item_ref.id); + let bounds = match trait_item.node { + hir::TraitItemKind::Type(ref bounds, _) => bounds, + _ => { + return vec![].into_iter(); + } + }; + + let assoc_ty = tcx.mk_projection(self_trait_ref, trait_item.name); + + let bounds = compute_bounds(&ccx.icx(def_id), + assoc_ty, + bounds, + SizedByDefault::Yes, + trait_item.span); + + bounds.predicates(tcx, assoc_ty).into_iter() + })) + } + + // Subtle: before we store the predicates into the tcx, we + // sort them so that predicates like `T: Foo` come + // before uses of `U`. This avoids false ambiguity errors + // in trait checking. See `setup_constraining_predicates` + // for details. + if let Some((self_ty, trait_ref)) = is_impl { + ctp::setup_constraining_predicates(&mut predicates, + trait_ref, + &mut ctp::parameters_for_impl(self_ty, trait_ref)); } + + tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + parent: generics.parent, + predicates: predicates + }); } pub enum SizedByDefault { Yes, No, } @@ -1947,11 +1799,10 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, def_id: DefId, decl: &hir::FnDecl, - ast_generics: &hir::Generics, abi: abi::Abi) -> Ty<'tcx> { - let fty = AstConv::ty_of_fn(&ccx.icx(ast_generics), hir::Unsafety::Unsafe, abi, decl); + let fty = AstConv::ty_of_fn(&ccx.icx(def_id), hir::Unsafety::Unsafe, abi, decl); // feature gate SIMD types in FFI, since I (huonw) am not sure the // ABIs are handled at all correctly. @@ -1975,22 +1826,15 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let id = ccx.tcx.hir.as_local_node_id(def_id).unwrap(); - let substs = mk_item_substs(&ccx.icx(ast_generics), ccx.tcx.hir.span(id), def_id); + let substs = mk_item_substs(ccx, def_id); ccx.tcx.mk_fn_def(def_id, substs, fty) } -fn mk_item_substs<'tcx>(astconv: &AstConv<'tcx, 'tcx>, - span: Span, - def_id: DefId) - -> &'tcx Substs<'tcx> { - let tcx = astconv.tcx(); +fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + def_id: DefId) + -> &'tcx Substs<'tcx> { // FIXME(eddyb) Do this request from Substs::for_item in librustc. - if let Err(ErrorReported) = astconv.get_generics(span, def_id) { - // No convenient way to recover from a cycle here. Just bail. Sorry! - tcx.sess.abort_if_errors(); - bug!("ErrorReported returned, but no errors reports?") - } + generics_of_def_id(ccx, def_id); - Substs::identity_for_item(tcx, def_id) + Substs::identity_for_item(ccx.tcx, def_id) } diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs index ab9ac03982599..7a5ef3540e93d 100644 --- a/src/test/compile-fail/resolve-self-in-impl.rs +++ b/src/test/compile-fail/resolve-self-in-impl.rs @@ -8,22 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(associated_type_defaults)] + struct S(T); -trait Tr {} +trait Tr { + type A = (); +} impl Tr for S {} // OK +impl> Tr for S {} // OK +impl Tr for S {} // OK +impl Tr for S where Self: Copy {} // OK +impl Tr for S where S: Copy {} // OK +impl Tr for S where Self::A: Copy {} // OK -// FIXME: `Self` cannot be used in bounds because it depends on bounds itself. -impl> Tr for S {} //~ ERROR `Self` type is used before it's determined -impl Tr for S {} -impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined -impl Tr for S where S: Copy {} //~ ERROR `Self` type is used before it's determined -impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined - //~^ ERROR `Self` type is used before it's determined -impl Tr for Self {} //~ ERROR `Self` type is used before it's determined -impl Tr for S {} //~ ERROR `Self` type is used before it's determined -impl Self {} //~ ERROR `Self` type is used before it's determined -impl S {} //~ ERROR `Self` type is used before it's determined -impl Tr for S {} //~ ERROR `Self` type is used before it's determined +impl Tr for Self {} //~ ERROR unsupported cyclic reference between types/traits detected +impl Tr for S {} //~ ERROR unsupported cyclic reference between types/traits detected +impl Self {} //~ ERROR unsupported cyclic reference between types/traits detected +impl S {} //~ ERROR unsupported cyclic reference between types/traits detected +impl Tr for S {} //~ ERROR `Self` type is used before it's determined fn main() {} diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 1432369f7143d..587fb3f80d6c8 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -10,10 +10,13 @@ // Test paths to associated types using the type-parameter-only sugar. +use std::ops::Deref; pub trait Foo { type A; fn boo(&self) -> Self::A; + + fn baz(_: Self::Target) where Self: Deref {} } impl Foo for isize { diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 881f04300ed03..fda87de9b9c50 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -1,8 +1,15 @@ -error: `Self` type is used before it's determined +error[E0391]: unsupported cyclic reference between types/traits detected --> $DIR/issue-23305.rs:15:12 | 15 | impl ToNbt {} - | ^^^^ + | ^^^^ cyclic reference + | +note: the cycle begins when processing ``... + --> $DIR/issue-23305.rs:15:1 + | +15 | impl ToNbt {} + | ^^^^^^^^^^^^^^^^^^^ + = note: ...which then again requires processing ``, completing the cycle. error: aborting due to previous error From e96a171453973bad66ed9b5df3a7f6e37d9bce31 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 5 Feb 2017 07:01:48 +0200 Subject: [PATCH 03/17] rustc: move the actual values of enum discriminants into a map. --- src/librustc/dep_graph/dep_node.rs | 2 + src/librustc/mir/tcx.rs | 4 +- src/librustc/ty/context.rs | 9 +- src/librustc/ty/layout.rs | 15 ++- src/librustc/ty/maps.rs | 2 + src/librustc/ty/mod.rs | 50 +++++++--- src/librustc/ty/util.rs | 90 ++++++++++++++--- .../borrowck/mir/elaborate_drops.rs | 11 +-- src/librustc_const_math/int.rs | 8 -- src/librustc_metadata/decoder.rs | 27 ++++-- src/librustc_metadata/encoder.rs | 20 ++-- src/librustc_metadata/schema.rs | 6 +- src/librustc_mir/build/matches/test.rs | 11 +-- src/librustc_trans/callee.rs | 4 +- src/librustc_trans/debuginfo/metadata.rs | 10 +- src/librustc_trans/disr.rs | 38 +++++++- src/librustc_trans/glue.rs | 7 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/rvalue.rs | 6 +- src/librustc_typeck/check/mod.rs | 15 ++- src/librustc_typeck/collect.rs | 97 +++++++++++-------- src/test/compile-fail/E0081.rs | 6 +- src/test/compile-fail/issue-15524.rs | 18 ++-- 23 files changed, 311 insertions(+), 147 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 96d1a925425e8..8da032f59353a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -114,6 +114,7 @@ pub enum DepNode { InherentImpls(D), TypeckTables(D), UsedTraitImports(D), + MonomorphicConstEval(D), // The set of impls for a given trait. Ultimately, it would be // nice to get more fine-grained here (e.g., to include a @@ -263,6 +264,7 @@ impl DepNode { InherentImpls(ref d) => op(d).map(InherentImpls), TypeckTables(ref d) => op(d).map(TypeckTables), UsedTraitImports(ref d) => op(d).map(UsedTraitImports), + MonomorphicConstEval(ref d) => op(d).map(MonomorphicConstEval), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 5c8d031caf60d..527f115277082 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -173,7 +173,9 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::Discriminant(ref lval) => { let ty = lval.ty(mir, tcx).to_ty(tcx); if let ty::TyAdt(adt_def, _) = ty.sty { - Some(adt_def.discr_ty.to_ty(tcx)) + let repr_hints = tcx.lookup_repr_hints(adt_def.did); + let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + Some(repr_type.to_ty(tcx)) } else { // Undefined behaviour, bug for now; may want to return something for // the `discriminant` intrinsic later. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2f062e2e5b194..c7e7fac275981 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -507,6 +507,10 @@ pub struct GlobalCtxt<'tcx> { /// FIXME(arielb1): why is this separate from populated_external_types? pub populated_external_primitive_impls: RefCell, + /// Results of evaluating monomorphic constants embedded in + /// other items, such as enum variant explicit discriminants. + pub monomorphic_const_eval: RefCell>>, + /// Maps any item's def-id to its stability index. pub stability: RefCell>, @@ -662,12 +666,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn alloc_adt_def(self, did: DefId, kind: AdtKind, - discr_ty: Option, variants: Vec, repr: ReprOptions) -> &'gcx ty::AdtDef { - let discr_ty = discr_ty.unwrap_or(attr::UnsignedInt(ast::UintTy::U8)); - let def = ty::AdtDef::new(self, did, kind, discr_ty, variants, repr); + let def = ty::AdtDef::new(self, did, kind, variants, repr); self.global_arenas.adt_def.alloc(def) } @@ -783,6 +785,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), + monomorphic_const_eval: RefCell::new(DepTrackingMap::new(dep_graph.clone())), stability: RefCell::new(stability), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index f429053d8bb12..5829ae195c941 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -20,6 +20,7 @@ use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; +use rustc_const_math::ConstInt; use std::cmp; use std::fmt; @@ -1181,8 +1182,12 @@ impl<'a, 'gcx, 'tcx> Layout { let (mut min, mut max, mut non_zero) = (i64::max_value(), i64::min_value(), true); - for v in &def.variants { - let x = v.disr_val as i128 as i64; + for discr in def.discriminants(tcx) { + let x = match discr.erase_type() { + ConstInt::InferSigned(i) => i as i64, + ConstInt::Infer(i) => i as u64 as i64, + _ => bug!() + }; if x == 0 { non_zero = false; } if x < min { min = x; } if x > max { max = x; } @@ -1240,7 +1245,7 @@ impl<'a, 'gcx, 'tcx> Layout { // non-empty body, explicit discriminants should have // been rejected by a checker before this point. for (i, v) in def.variants.iter().enumerate() { - if i as u128 != v.disr_val { + if v.discr != ty::VariantDiscr::Relative(i) { bug!("non-C-like enum {} with specified discriminants", tcx.item_path_str(def.did)); } @@ -1348,7 +1353,9 @@ impl<'a, 'gcx, 'tcx> Layout { return Err(LayoutError::SizeOverflow(ty)); } - let typeck_ity = Integer::from_attr(dl, def.discr_ty); + let repr_hints = tcx.lookup_repr_hints(def.did); + let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + let typeck_ity = Integer::from_attr(dl, repr_type); if typeck_ity < min_ity { // It is a bug if Layout decided on a greater discriminant size than typeck for // some reason at this point (based on values discriminant can take on). Mostly diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index d2c237d5db61d..cedb030749560 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -10,6 +10,7 @@ use dep_graph::{DepNode, DepTrackingMapConfig}; use hir::def_id::DefId; +use middle::const_val::ConstVal; use mir; use ty::{self, Ty}; use util::nodemap::DefIdSet; @@ -51,3 +52,4 @@ dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> } dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet } +dep_map_ty! { MonomorphicConstEval: MonomorphicConstEval(DefId) -> Result } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 1275530b1bdf9..be4ec881482d1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -20,6 +20,7 @@ use hir::{map as hir_map, FreevarMap, TraitMap}; use middle; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; +use middle::const_val::ConstVal; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use middle::resolve_lifetime::ObjectLifetimeDefault; @@ -27,6 +28,7 @@ use mir::Mir; use traits; use ty; use ty::subst::{Subst, Substs}; +use ty::util::IntTypeExt; use ty::walk::TypeWalker; use util::common::MemoizationMap; use util::nodemap::{NodeSet, NodeMap, FxHashMap}; @@ -45,6 +47,7 @@ use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{DUMMY_SP, Span}; +use rustc_const_math::ConstInt; use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; @@ -96,8 +99,6 @@ mod flags; mod structural_impls; mod sty; -pub type Disr = u128; - // Data types /// The complete set of all analyses described in this module. This is @@ -1309,11 +1310,24 @@ pub struct VariantDef { /// this is the DefId of the struct's ctor. pub did: DefId, pub name: Name, // struct's name if this is a struct - pub disr_val: Disr, + pub discr: VariantDiscr, pub fields: Vec, pub ctor_kind: CtorKind, } +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] +pub enum VariantDiscr { + /// Explicit value for this variant, i.e. `X = 123`. + /// The `DefId` corresponds to the embedded constant. + Explicit(DefId), + + /// The previous variant's discriminant plus one. + /// For efficiency reasons, the distance from the + /// last `Explicit` discriminant is being stored, + /// or `0` for the first variant, if it has none. + Relative(usize), +} + #[derive(Debug)] pub struct FieldDef { pub did: DefId, @@ -1327,12 +1341,6 @@ pub struct FieldDef { /// table. pub struct AdtDef { pub did: DefId, - /// Type of the discriminant - /// - /// Note, that this is the type specified in `repr()` or a default type of some sort, and might - /// not match the actual type that layout algorithm decides to use when translating this type - /// into LLVM. That being said, layout algorithm may not use a type larger than specified here. - pub discr_ty: attr::IntType, pub variants: Vec, destructor: Cell>, flags: Cell, @@ -1395,7 +1403,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, did: DefId, kind: AdtKind, - discr_ty: attr::IntType, variants: Vec, repr: ReprOptions) -> Self { let mut flags = AdtFlags::NO_ADT_FLAGS; @@ -1419,7 +1426,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { } AdtDef { did: did, - discr_ty: discr_ty, variants: variants, flags: Cell::new(flags), destructor: Cell::new(None), @@ -1577,6 +1583,28 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.destructor.set(Some(dtor)); } + pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>) + -> impl Iterator + 'a { + let repr_hints = tcx.lookup_repr_hints(self.did); + let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + let initial = repr_type.initial_discriminant(tcx.global_tcx()); + let mut prev_discr = None::; + self.variants.iter().map(move |v| { + let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr()); + if let VariantDiscr::Explicit(expr_did) = v.discr { + match tcx.monomorphic_const_eval.borrow()[&expr_did] { + Ok(ConstVal::Integral(v)) => { + discr = v; + } + _ => {} + } + } + prev_discr = Some(discr); + + discr + }) + } + /// Returns a simpler type such that `Self: Sized` if and only /// if that type is Sized, or `TyErr` if this type is recursive. /// diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 16492de6c3d27..af25990978793 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -16,13 +16,14 @@ use infer::InferCtxt; use hir::map as hir_map; use traits::{self, Reveal}; use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; -use ty::{Disr, ParameterEnvironment}; +use ty::{ParameterEnvironment}; use ty::fold::TypeVisitor; use ty::layout::{Layout, LayoutError}; use ty::TypeVariants::*; use util::nodemap::FxHashMap; use middle::lang_items; +use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult}; use std::cell::RefCell; @@ -35,21 +36,88 @@ use syntax_pos::Span; use hir; -pub trait IntTypeExt { - fn to_ty<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>; - fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr; -} +type Disr = ConstInt; + + pub trait IntTypeExt { + fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>; + fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option) + -> Option; + fn assert_ty_matches(&self, val: Disr); + fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr; + } + impl IntTypeExt for attr::IntType { - fn to_ty<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { - match self { - SignedInt(i) => tcx.mk_mach_int(i), - UnsignedInt(i) => tcx.mk_mach_uint(i), + fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { + match *self { + SignedInt(ast::IntTy::I8) => tcx.types.i8, + SignedInt(ast::IntTy::I16) => tcx.types.i16, + SignedInt(ast::IntTy::I32) => tcx.types.i32, + SignedInt(ast::IntTy::I64) => tcx.types.i64, + SignedInt(ast::IntTy::I128) => tcx.types.i128, + SignedInt(ast::IntTy::Is) => tcx.types.isize, + UnsignedInt(ast::UintTy::U8) => tcx.types.u8, + UnsignedInt(ast::UintTy::U16) => tcx.types.u16, + UnsignedInt(ast::UintTy::U32) => tcx.types.u32, + UnsignedInt(ast::UintTy::U64) => tcx.types.u64, + UnsignedInt(ast::UintTy::U128) => tcx.types.u128, + UnsignedInt(ast::UintTy::Us) => tcx.types.usize, + } + } + + fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr { + match *self { + SignedInt(ast::IntTy::I8) => ConstInt::I8(0), + SignedInt(ast::IntTy::I16) => ConstInt::I16(0), + SignedInt(ast::IntTy::I32) => ConstInt::I32(0), + SignedInt(ast::IntTy::I64) => ConstInt::I64(0), + SignedInt(ast::IntTy::I128) => ConstInt::I128(0), + SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type { + ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)), + ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)), + ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)), + _ => bug!(), + }, + UnsignedInt(ast::UintTy::U8) => ConstInt::U8(0), + UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0), + UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0), + UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0), + UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0), + UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type { + ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)), + ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)), + ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)), + _ => bug!(), + }, } } - fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr { - 0 + fn assert_ty_matches(&self, val: Disr) { + match (*self, val) { + (SignedInt(ast::IntTy::I8), ConstInt::I8(_)) => {}, + (SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {}, + (SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {}, + (SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {}, + (SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {}, + (SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {}, + (UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {}, + (UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {}, + (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {}, + (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {}, + (UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {}, + (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {}, + _ => bug!("disr type mismatch: {:?} vs {:?}", self, val), + } + } + + fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option) + -> Option { + if let Some(val) = val { + self.assert_ty_matches(val); + (val + ConstInt::Infer(1)).ok() + } else { + Some(self.initial_discriminant(tcx)) + } } } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 5899c9f31d14d..c64b25032c9ef 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -20,7 +20,7 @@ use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::util::IntTypeExt; use rustc::mir::*; use rustc::mir::transform::{Pass, MirPass, MirSource}; -use rustc::middle::const_val::{ConstVal, ConstInt}; +use rustc::middle::const_val::ConstVal; use rustc::middle::lang_items; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_set::IdxSetBuf; @@ -639,10 +639,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let mut values = Vec::with_capacity(adt.variants.len()); let mut blocks = Vec::with_capacity(adt.variants.len()); let mut otherwise = None; - for (variant_index, variant) in adt.variants.iter().enumerate() { - let discr = ConstInt::new_inttype(variant.disr_val, adt.discr_ty, - self.tcx.sess.target.uint_type, - self.tcx.sess.target.int_type).unwrap(); + for (variant_index, discr) in adt.discriminants(self.tcx).enumerate() { let subpath = super::move_path_children_matching( self.move_data(), c.path, |proj| match proj { &Projection { @@ -680,7 +677,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // Additionally, we do not want to switch on the // discriminant after it is free-ed, because that // way lies only trouble. - let discr_ty = adt.discr_ty.to_ty(self.tcx); + let repr_hints = self.tcx.lookup_repr_hints(adt.did); + let repr_type = self.tcx.enum_repr_type(repr_hints.get(0)); + let discr_ty = repr_type.to_ty(self.tcx); let discr = Lvalue::Local(self.patch.new_temp(discr_ty)); let switch_block = self.patch.new_block(BasicBlockData { statements: vec![ diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index bc3809db1c63a..17714f2fb2d6c 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -77,14 +77,6 @@ mod ibounds { } impl ConstInt { - pub fn new_inttype(val: u128, ty: IntType, usize_ty: UintTy, isize_ty: IntTy) - -> Option { - match ty { - IntType::SignedInt(i) => ConstInt::new_signed(val as i128, i, isize_ty), - IntType::UnsignedInt(i) => ConstInt::new_unsigned(val, i, usize_ty), - } - } - /// Creates a new unsigned ConstInt with matching type while also checking that overflow does /// not happen. pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 22fa9411cc117..88b06e29e103c 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -515,7 +515,8 @@ impl<'a, 'tcx> CrateMetadata { fn get_variant(&self, item: &Entry<'tcx>, - index: DefIndex) + index: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) -> (ty::VariantDef, Option) { let data = match item.kind { EntryKind::Variant(data) | @@ -524,6 +525,11 @@ impl<'a, 'tcx> CrateMetadata { _ => bug!(), }; + if let ty::VariantDiscr::Explicit(def_id) = data.discr { + let result = data.evaluated_discr.map_or(Err(()), Ok); + tcx.monomorphic_const_eval.borrow_mut().insert(def_id, result); + } + (ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), name: self.item_name(index), @@ -535,7 +541,7 @@ impl<'a, 'tcx> CrateMetadata { vis: f.visibility.decode(self) } }).collect(), - disr_val: data.disr, + discr: data.discr, ctor_kind: data.ctor_kind, }, data.struct_ctor) } @@ -546,10 +552,10 @@ impl<'a, 'tcx> CrateMetadata { -> &'tcx ty::AdtDef { let item = self.entry(item_id); let did = self.local_def_id(item_id); - let (kind, ty) = match item.kind { - EntryKind::Enum(dt, _) => (ty::AdtKind::Enum, Some(dt.decode(self))), - EntryKind::Struct(_, _) => (ty::AdtKind::Struct, None), - EntryKind::Union(_, _) => (ty::AdtKind::Union, None), + let kind = match item.kind { + EntryKind::Enum(_) => ty::AdtKind::Enum, + EntryKind::Struct(_, _) => ty::AdtKind::Struct, + EntryKind::Union(_, _) => ty::AdtKind::Union, _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; let mut ctor_index = None; @@ -557,24 +563,25 @@ impl<'a, 'tcx> CrateMetadata { item.children .decode(self) .map(|index| { - let (variant, struct_ctor) = self.get_variant(&self.entry(index), index); + let (variant, struct_ctor) = + self.get_variant(&self.entry(index), index, tcx); assert_eq!(struct_ctor, None); variant }) .collect() } else { - let (variant, struct_ctor) = self.get_variant(&item, item_id); + let (variant, struct_ctor) = self.get_variant(&item, item_id, tcx); ctor_index = struct_ctor; vec![variant] }; let (kind, repr) = match item.kind { - EntryKind::Enum(_, repr) => (ty::AdtKind::Enum, repr), + EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; - let adt = tcx.alloc_adt_def(did, kind, ty, variants, repr); + let adt = tcx.alloc_adt_def(did, kind, variants, repr); if let Some(ctor_index) = ctor_index { // Make adt definition available through constructor id as well. tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index a643ed59af136..725d54c227a30 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -261,7 +261,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, - disr: variant.disr_val, + discr: variant.discr, + evaluated_discr: match variant.discr { + ty::VariantDiscr::Explicit(def_id) => { + tcx.monomorphic_const_eval.borrow()[&def_id].clone().ok() + } + ty::VariantDiscr::Relative(_) => None + }, struct_ctor: None, }; @@ -388,7 +394,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, - disr: variant.disr_val, + discr: variant.discr, + evaluated_discr: None, struct_ctor: Some(def_id.index), }; @@ -644,8 +651,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemForeignMod(_) => EntryKind::ForeignMod, hir::ItemTy(..) => EntryKind::Type, - hir::ItemEnum(..) => EntryKind::Enum(self.lazy(&tcx.lookup_adt_def(def_id).discr_ty), - get_repr_options(&tcx, def_id)), + hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)), hir::ItemStruct(ref struct_def, _) => { let variant = tcx.lookup_adt_def(def_id).struct_variant(); @@ -662,7 +668,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { EntryKind::Struct(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, - disr: variant.disr_val, + discr: variant.discr, + evaluated_discr: None, struct_ctor: struct_ctor, }), repr_options) } @@ -672,7 +679,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { EntryKind::Union(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, - disr: variant.disr_val, + discr: variant.discr, + evaluated_discr: None, struct_ctor: None, }), repr_options) } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index ee30063fcbd06..6307d4eda308e 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -14,6 +14,7 @@ use index; use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId}; +use rustc::middle::const_val::ConstVal; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; use rustc::mir; @@ -227,7 +228,7 @@ pub enum EntryKind<'tcx> { ForeignMutStatic, ForeignMod, Type, - Enum(Lazy, ReprOptions), + Enum(ReprOptions), Field, Variant(Lazy), Struct(Lazy, ReprOptions), @@ -264,7 +265,8 @@ pub struct FnData { #[derive(RustcEncodable, RustcDecodable)] pub struct VariantData { pub ctor_kind: CtorKind, - pub disr: u128, + pub discr: ty::VariantDiscr, + pub evaluated_discr: Option, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 01c0433112bf3..3256bdf9c25e3 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -20,7 +20,7 @@ use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::bitvec::BitVector; -use rustc::middle::const_val::{ConstVal, ConstInt}; +use rustc::middle::const_val::ConstVal; use rustc::ty::{self, Ty}; use rustc::ty::util::IntTypeExt; use rustc::mir::*; @@ -191,11 +191,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut targets = Vec::with_capacity(used_variants + 1); let mut values = Vec::with_capacity(used_variants); let tcx = self.hir.tcx(); - for (idx, variant) in adt_def.variants.iter().enumerate() { + for (idx, discr) in adt_def.discriminants(tcx).enumerate() { target_blocks.place_back() <- if variants.contains(idx) { - let discr = ConstInt::new_inttype(variant.disr_val, adt_def.discr_ty, - tcx.sess.target.uint_type, - tcx.sess.target.int_type).unwrap(); values.push(discr); *(targets.place_back() <- self.cfg.start_new_block()) } else { @@ -212,7 +209,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}", num_enum_variants, values, variants); - let discr_ty = adt_def.discr_ty.to_ty(tcx); + let repr_hints = tcx.lookup_repr_hints(adt_def.did); + let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + let discr_ty = repr_type.to_ty(tcx); let discr = self.temp(discr_ty); self.cfg.push_assign(block, source_info, &discr, Rvalue::Discriminant(lvalue.clone())); diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 4a8658dd2e308..9a06820115f63 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -93,9 +93,9 @@ impl<'tcx> Callee<'tcx> { // FIXME(eddyb) Detect ADT constructors more efficiently. if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() { - if let Some(v) = adt_def.variants.iter().find(|v| def_id == v.did) { + if let Some(i) = adt_def.variants.iter().position(|v| def_id == v.did) { return Callee { - data: NamedTupleConstructor(Disr::from(v.disr_val)), + data: NamedTupleConstructor(Disr::for_variant(tcx, adt_def, i)), ty: fn_ty }; } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 11c0bf852f727..2b584344ed1c7 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1465,10 +1465,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // let file_metadata = unknown_file_metadata(cx); - let variants = &enum_type.ty_adt_def().unwrap().variants; - let enumerators_metadata: Vec = variants - .iter() - .map(|v| { + let def = enum_type.ty_adt_def().unwrap(); + let enumerators_metadata: Vec = def.discriminants(cx.tcx()) + .zip(&def.variants) + .map(|(discr, v)| { let token = v.name.as_str(); let name = CString::new(token.as_bytes()).unwrap(); unsafe { @@ -1476,7 +1476,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, DIB(cx), name.as_ptr(), // FIXME: what if enumeration has i128 discriminant? - v.disr_val as u64) + discr.to_u128_unchecked() as u64) } }) .collect(); diff --git a/src/librustc_trans/disr.rs b/src/librustc_trans/disr.rs index f3a62bc85b8d9..00c0e0d541586 100644 --- a/src/librustc_trans/disr.rs +++ b/src/librustc_trans/disr.rs @@ -8,10 +8,42 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::middle::const_val::ConstVal; +use rustc::ty::{self, TyCtxt}; +use rustc_const_math::ConstInt; + #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct Disr(pub u64); impl Disr { + pub fn for_variant(tcx: TyCtxt, + def: &ty::AdtDef, + variant_index: usize) -> Self { + let mut explicit_index = variant_index; + let mut explicit_value = Disr(0); + loop { + match def.variants[explicit_index].discr { + ty::VariantDiscr::Relative(0) => break, + ty::VariantDiscr::Relative(distance) => { + explicit_index -= distance; + } + ty::VariantDiscr::Explicit(expr_did) => { + match tcx.monomorphic_const_eval.borrow()[&expr_did] { + Ok(ConstVal::Integral(v)) => { + explicit_value = Disr::from(v); + break; + } + _ => { + explicit_index -= 1; + } + } + } + } + } + let distance = variant_index - explicit_index; + explicit_value.wrapping_add(Disr::from(distance)) + } + pub fn wrapping_add(self, other: Self) -> Self { Disr(self.0.wrapping_add(other.0)) } @@ -24,10 +56,10 @@ impl ::std::ops::BitAnd for Disr { } } -impl From<::rustc::ty::Disr> for Disr { - fn from(i: ::rustc::ty::Disr) -> Disr { +impl From for Disr { + fn from(i: ConstInt) -> Disr { // FIXME: what if discr has 128 bit discr? - Disr(i as u64) + Disr(i.to_u128_unchecked() as u64) } } diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 9963514acd736..58e0a9e589f33 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -521,11 +521,10 @@ fn drop_structural_ty<'a, 'tcx>( let llswitch = cx.switch(lldiscrim_a, ret_void_cx.llbb(), n_variants); let next_cx = cx.build_sibling_block("enum-iter-next"); - for (i, variant) in adt.variants.iter().enumerate() { - let variant_cx_name = format!("enum-iter-variant-{}", - &variant.disr_val.to_string()); + for (i, discr) in adt.discriminants(cx.tcx()).enumerate() { + let variant_cx_name = format!("enum-iter-variant-{}", i); let variant_cx = cx.build_sibling_block(&variant_cx_name); - let case_val = adt::trans_case(&cx, t, Disr::from(variant.disr_val)); + let case_val = adt::trans_case(&cx, t, Disr::from(discr)); variant_cx.add_case(llswitch, case_val, variant_cx.llbb()); ptr.ty = LvalueTy::Downcast { adt_def: adt, diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index e6cae2f9f3296..6a0e05803c355 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -1001,7 +1001,7 @@ fn trans_const<'a, 'tcx>( layout::CEnum { discr: d, min, max, .. } => { let discr = match *kind { mir::AggregateKind::Adt(adt_def, _, _, _) => { - Disr::from(adt_def.variants[variant_index].disr_val) + Disr::for_variant(ccx.tcx(), adt_def, variant_index) }, _ => Disr(0), }; diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 6f6d81a25350f..c3dffd476e133 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -106,9 +106,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { mir::Rvalue::Aggregate(ref kind, ref operands) => { match *kind { mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => { - let disr = Disr::from(adt_def.variants[variant_index].disr_val); + let disr = Disr::for_variant(bcx.tcx(), adt_def, variant_index); let dest_ty = dest.ty.to_ty(bcx.tcx()); - adt::trans_set_discr(&bcx, dest_ty, dest.llval, Disr::from(disr)); + adt::trans_set_discr(&bcx, dest_ty, dest.llval, disr); for (i, operand) in operands.iter().enumerate() { let op = self.trans_operand(&bcx, operand); // Do not generate stores and GEPis for zero-sized fields. @@ -119,7 +119,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { val.ty = LvalueTy::Downcast { adt_def: adt_def, substs: self.monomorphize(&substs), - variant_index: disr.0 as usize, + variant_index: variant_index, }; let (lldest_i, align) = val.trans_field_ptr(&bcx, field_index); self.store_operand(&bcx, lldest_i, align.to_align(), op); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d4895d638ba0d..6a003ef734020 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -124,6 +124,7 @@ use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; use rustc_back::slice; use rustc_const_eval::eval_length; +use rustc_const_math::ConstInt; mod assoc; mod autoderef; @@ -1323,14 +1324,12 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let def_id = ccx.tcx.hir.local_def_id(id); - let variants = &ccx.tcx.lookup_adt_def(def_id).variants; - let mut disr_vals: Vec = Vec::new(); - for (v, variant) in vs.iter().zip(variants.iter()) { - let current_disr_val = variant.disr_val; - + let def = ccx.tcx.lookup_adt_def(def_id); + let mut disr_vals: Vec = Vec::new(); + for (discr, v) in def.discriminants(ccx.tcx).zip(vs) { // Check for duplicate discriminant values - if let Some(i) = disr_vals.iter().position(|&x| x == current_disr_val) { - let variant_i_node_id = ccx.tcx.hir.as_local_node_id(variants[i].did).unwrap(); + 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 = ccx.tcx.hir.expect_variant(variant_i_node_id); let i_span = match variant_i.node.disr_expr { Some(expr) => ccx.tcx.hir.span(expr.node_id), @@ -1346,7 +1345,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, .span_label(span , &format!("enum already has `{}`", disr_vals[i])) .emit(); } - disr_vals.push(current_disr_val); + disr_vals.push(discr); } check_representable(ccx.tcx, sp, def_id); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 975a9aa994624..3f3fc40320eb6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -875,8 +875,36 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def: &'tcx ty::AdtDef, ty: Ty<'tcx>, variants: &[hir::Variant]) { - // fill the field types + let tcx = ccx.tcx; + let repr_hints = tcx.lookup_repr_hints(def.did); + let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + let initial = repr_type.initial_discriminant(tcx); + let mut prev_discr = None::; + + // fill the discriminant values and field types for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) { + let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr()); + prev_discr = Some(if let Some(e) = variant.node.disr_expr { + let result = evaluate_disr_expr(ccx, repr_type, e); + + let expr_did = tcx.hir.local_def_id(e.node_id); + tcx.monomorphic_const_eval.borrow_mut() + .insert(expr_did, result.map(ConstVal::Integral)); + + result.ok() + } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { + Some(discr) + } else { + struct_span_err!(tcx.sess, variant.span, E0370, + "enum discriminant overflowed") + .span_label(variant.span, &format!("overflowed on value after {}", + prev_discr.unwrap())) + .note(&format!("explicitly set `{} = {}` if that is desired outcome", + variant.node.name, wrapped_discr)) + .emit(); + None + }.unwrap_or(wrapped_discr)); + for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) { convert_field(ccx, f, ty_f) } @@ -890,7 +918,7 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, did: DefId, name: ast::Name, - disr_val: ty::Disr, + discr: ty::VariantDiscr, def: &hir::VariantData) -> ty::VariantDef { let mut seen_fields: FxHashMap = FxHashMap(); @@ -918,7 +946,7 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty::VariantDef { did: did, name: name, - disr_val: disr_val, + discr: discr, fields: fields, ctor_kind: CtorKind::from_hir(def), } @@ -932,8 +960,9 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let did = ccx.tcx.hir.local_def_id(it.id); // Use separate constructor id for unit/tuple structs and reuse did for braced structs. let ctor_id = if !def.is_struct() { Some(ccx.tcx.hir.local_def_id(def.id())) } else { None }; - let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name, 0, def)]; - let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, None, variants, + let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name, + ty::VariantDiscr::Relative(0), def)]; + let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants, ReprOptions::new(&ccx.tcx, did)); if let Some(ctor_id) = ctor_id { // Make adt definition available through constructor id as well. @@ -950,15 +979,16 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, -> &'tcx ty::AdtDef { let did = ccx.tcx.hir.local_def_id(it.id); - let variants = vec![convert_struct_variant(ccx, did, it.name, 0, def)]; - let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, None, variants, - ReprOptions::new(&ccx.tcx, did)); + let variants = vec![convert_struct_variant(ccx, did, it.name, + ty::VariantDiscr::Relative(0), def)]; + + let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did)); ccx.tcx.adt_defs.borrow_mut().insert(did, adt); adt } fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId) - -> Option { + -> Result { let e = &ccx.tcx.hir.body(body).value; debug!("disr expr, checking {}", ccx.tcx.hir.node_to_pretty_string(e.id)); @@ -987,17 +1017,16 @@ fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId (attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) | (attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) | (attr::UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) | - (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => - Some(i), + (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Ok(i), (_, i) => { print_err(ConstVal::Integral(i)); - None + Err(()) }, } }, Ok(cv) => { print_err(cv); - None + Err(()) }, // enum variant evaluation happens before the global constant check // so we need to report the real error @@ -1005,7 +1034,7 @@ fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId let mut diag = report_const_eval_err( ccx.tcx, &err, e.span, "enum discriminant"); diag.emit(); - None + Err(()) } } } @@ -1016,36 +1045,22 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, -> &'tcx ty::AdtDef { let tcx = ccx.tcx; - let did = tcx.hir.local_def_id(it.id); - let repr_hints = tcx.lookup_repr_hints(did); - let repr_type = tcx.enum_repr_type(repr_hints.get(0)); - let initial = ConstInt::new_inttype(repr_type.initial_discriminant(tcx), repr_type, - tcx.sess.target.uint_type, tcx.sess.target.int_type) - .unwrap(); - let mut prev_disr = None::; + let mut distance_from_explicit = 0; let variants = def.variants.iter().map(|v| { - let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr()); - let disr = if let Some(e) = v.node.disr_expr { - // FIXME: i128 discriminants - evaluate_disr_expr(ccx, repr_type, e) - } else if let Some(disr) = prev_disr.map_or(Some(initial), - |v| (v + ConstInt::Infer(1)).ok()) { - Some(disr) - } else { - struct_span_err!(tcx.sess, v.span, E0370, - "enum discriminant overflowed") - .span_label(v.span, &format!("overflowed on value after {}", prev_disr.unwrap())) - .note(&format!("explicitly set `{} = {}` if that is desired outcome", - v.node.name, wrapped_disr)) - .emit(); - None - }.unwrap_or(wrapped_disr); - prev_disr = Some(disr); let did = tcx.hir.local_def_id(v.node.data.id()); - convert_struct_variant(ccx, did, v.node.name, disr.to_u128_unchecked(), &v.node.data) + let discr = if let Some(e) = v.node.disr_expr { + distance_from_explicit = 0; + ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.node_id)) + } else { + ty::VariantDiscr::Relative(distance_from_explicit) + }; + distance_from_explicit += 1; + + convert_struct_variant(ccx, did, v.node.name, discr, &v.node.data) }).collect(); - let adt = tcx.alloc_adt_def(did, AdtKind::Enum, Some(repr_type), variants, - ReprOptions::new(&ccx.tcx, did)); + + let did = tcx.hir.local_def_id(it.id); + let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did)); tcx.adt_defs.borrow_mut().insert(did, adt); adt } diff --git a/src/test/compile-fail/E0081.rs b/src/test/compile-fail/E0081.rs index e12eff72c7f41..9911e093a8980 100644 --- a/src/test/compile-fail/E0081.rs +++ b/src/test/compile-fail/E0081.rs @@ -9,10 +9,10 @@ // except according to those terms. enum Enum { - P = 3, //~ NOTE first use of `3` + P = 3, //~ NOTE first use of `3isize` X = 3, - //~^ ERROR discriminant value `3` already exists - //~| NOTE enum already has `3` + //~^ ERROR discriminant value `3isize` already exists + //~| NOTE enum already has `3isize` Y = 5 } diff --git a/src/test/compile-fail/issue-15524.rs b/src/test/compile-fail/issue-15524.rs index 0d5f5fd75eba8..658a0c1546b9f 100644 --- a/src/test/compile-fail/issue-15524.rs +++ b/src/test/compile-fail/issue-15524.rs @@ -12,20 +12,20 @@ const N: isize = 1; enum Foo { A = 1, - //~^ NOTE first use of `1` - //~| NOTE first use of `1` - //~| NOTE first use of `1` + //~^ NOTE first use of `1isize` + //~| NOTE first use of `1isize` + //~| NOTE first use of `1isize` B = 1, - //~^ ERROR discriminant value `1` already exists - //~| NOTE enum already has `1` + //~^ ERROR discriminant value `1isize` already exists + //~| NOTE enum already has `1isize` C = 0, D, - //~^ ERROR discriminant value `1` already exists - //~| NOTE enum already has `1` + //~^ ERROR discriminant value `1isize` already exists + //~| NOTE enum already has `1isize` E = N, - //~^ ERROR discriminant value `1` already exists - //~| NOTE enum already has `1` + //~^ ERROR discriminant value `1isize` already exists + //~| NOTE enum already has `1isize` } From cc8a3a93b70f6805e235199029c3948515f99226 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 7 Feb 2017 11:47:35 +0200 Subject: [PATCH 04/17] rustc: consolidate dep-tracked hashmaps in tcx.maps. --- src/librustc/middle/dead.rs | 2 +- src/librustc/mir/transform.rs | 4 +- src/librustc/traits/fulfill.rs | 2 +- src/librustc/ty/context.rs | 96 +--------------- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/maps.rs | 116 +++++++++++++++----- src/librustc/ty/mod.rs | 60 +++++----- src/librustc/util/ppaux.rs | 2 +- src/librustc_const_eval/eval.rs | 10 +- src/librustc_driver/pretty.rs | 6 +- src/librustc_lint/bad_style.rs | 2 +- src/librustc_metadata/decoder.rs | 6 +- src/librustc_metadata/encoder.rs | 10 +- src/librustc_mir/mir_map.rs | 2 +- src/librustc_passes/mir_stats.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_trans/disr.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/writeback.rs | 10 +- src/librustc_typeck/check_unused.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 4 +- src/librustc_typeck/coherence/overlap.rs | 2 +- src/librustc_typeck/collect.rs | 46 ++++---- src/librustc_typeck/variance/constraints.rs | 13 +-- src/librustc_typeck/variance/solve.rs | 2 +- src/librustc_typeck/variance/terms.rs | 9 +- src/librustdoc/clean/inline.rs | 2 +- 29 files changed, 200 insertions(+), 222 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ae349667f9dc6..592e4cb92359c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -478,7 +478,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { // method of a private type is used, but the type itself is never // called directly. if let Some(impl_list) = - self.tcx.inherent_impls.borrow().get(&self.tcx.hir.local_def_id(id)) { + self.tcx.maps.inherent_impls.borrow().get(&self.tcx.hir.local_def_id(id)) { for &impl_did in impl_list.iter() { for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] { if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) { diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 652fef76f288a..4cbbb67c7e43d 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -114,14 +114,14 @@ impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T { tcx: TyCtxt<'a, 'tcx, 'tcx>, hooks: &mut [Box MirPassHook<'s>>]) { - let def_ids = tcx.mir_map.borrow().keys(); + let def_ids = tcx.maps.mir.borrow().keys(); for def_id in def_ids { if !def_id.is_local() { continue; } let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); - let mir = &mut tcx.mir_map.borrow()[&def_id].borrow_mut(); + let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut(); tcx.dep_graph.write(DepNode::Mir(def_id)); let id = tcx.hir.as_local_node_id(def_id).unwrap(); diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 23c28037a3c2d..e28a8392e58d7 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -155,7 +155,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { -> Option>> { if let ty::TyAnon(def_id, substs) = self.predicate.skip_binder().self_ty().sty { let ty = if def_id.is_local() { - tcx.item_types.borrow().get(&def_id).cloned() + tcx.maps.types.borrow().get(&def_id).cloned() } else { Some(tcx.item_type(def_id)) }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c7e7fac275981..665d60281d1a9 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -10,7 +10,7 @@ //! type context book-keeping -use dep_graph::{DepGraph, DepTrackingMap}; +use dep_graph::DepGraph; use session::Session; use lint; use middle; @@ -412,44 +412,9 @@ pub struct GlobalCtxt<'tcx> { // borrowck. (They are not used during trans, and hence are not // serialized or needed for cross-crate fns.) free_region_maps: RefCell>, - // FIXME: jroesch make this a refcell - - pub tables: RefCell>>, - - /// Maps from a trait item to the trait item "descriptor" - pub associated_items: RefCell>>, - - /// Maps from an impl/trait def-id to a list of the def-ids of its items - pub associated_item_def_ids: RefCell>>, - - pub impl_trait_refs: RefCell>>, - pub trait_defs: RefCell>>, - pub adt_defs: RefCell>>, - pub adt_sized_constraint: RefCell>>, - - /// Maps from the def-id of an item (trait/struct/enum/fn) to its - /// associated generics and predicates. - pub generics: RefCell>>, - pub predicates: RefCell>>, - - /// Maps from the def-id of a trait to the list of - /// super-predicates. This is a subset of the full list of - /// predicates. We store these in a separate map because we must - /// evaluate them even during type conversion, often before the - /// full predicates are available (note that supertraits have - /// additional acyclicity requirements). - pub super_predicates: RefCell>>, pub hir: hir_map::Map<'tcx>, - - /// Maps from the def-id of a function/method or const/static - /// to its MIR. Mutation is done at an item granularity to - /// allow MIR optimization passes to function and still - /// access cross-crate MIR (e.g. inlining or const eval). - /// - /// Note that cross-crate MIR appears to be always borrowed - /// (in the `RefCell` sense) to prevent accidental mutation. - pub mir_map: RefCell>>, + pub maps: maps::Maps<'tcx>, // Records the free variables refrenced by every closure // expression. Do not track deps for this, just recompute it from @@ -458,9 +423,6 @@ pub struct GlobalCtxt<'tcx> { pub maybe_unused_trait_imports: NodeSet, - // Records the type of every item. - pub item_types: RefCell>>, - // Internal cache for metadata decoding. No need to track deps on this. pub rcache: RefCell>>, @@ -474,18 +436,9 @@ pub struct GlobalCtxt<'tcx> { pub lang_items: middle::lang_items::LanguageItems, - /// Maps from def-id of a type or region parameter to its - /// (inferred) variance. - pub item_variance_map: RefCell>>, - /// True if the variance has been computed yet; false otherwise. pub variance_computed: Cell, - /// Maps a DefId of a type to a list of its inherent impls. - /// Contains implementations of methods that are inherent to a type. - /// Methods in these implementations don't need to be exported. - pub inherent_impls: RefCell>>, - /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not /// present in this set can be warned about. pub used_unsafe: RefCell, @@ -495,10 +448,6 @@ pub struct GlobalCtxt<'tcx> { /// about. pub used_mut_nodes: RefCell, - /// Set of trait imports actually used in the method resolution. - /// This is used for warning unused imports. - pub used_trait_imports: RefCell>>, - /// The set of external nominal types whose implementations have been read. /// This is used for lazy resolution of methods. pub populated_external_types: RefCell, @@ -507,10 +456,6 @@ pub struct GlobalCtxt<'tcx> { /// FIXME(arielb1): why is this separate from populated_external_types? pub populated_external_primitive_impls: RefCell, - /// Results of evaluating monomorphic constants embedded in - /// other items, such as enum variant explicit discriminants. - pub monomorphic_const_eval: RefCell>>, - /// Maps any item's def-id to its stability index. pub stability: RefCell>, @@ -529,23 +474,9 @@ pub struct GlobalCtxt<'tcx> { /// (i.e., no type or lifetime parameters). pub fulfilled_predicates: RefCell>, - /// Caches the representation hints for struct definitions. - repr_hint_cache: RefCell>>, - /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. pub rvalue_promotable_to_static: RefCell>, - /// Caches CoerceUnsized kinds for impls on custom types. - pub custom_coerce_unsized_kinds: RefCell>, - - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_tys: RefCell>>, - - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_kinds: RefCell>>, - /// Maps Fn items to a collection of fragment infos. /// /// The main goal is to identify data (each of which may be moved @@ -754,46 +685,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { named_region_map: named_region_map, region_maps: region_maps, free_region_maps: RefCell::new(FxHashMap()), - item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), variance_computed: Cell::new(false), sess: s, trait_map: resolutions.trait_map, - tables: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - adt_sized_constraint: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - generics: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), fulfilled_predicates: RefCell::new(fulfilled_predicates), hir: hir, - mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + maps: maps::Maps::new(dep_graph), freevars: RefCell::new(resolutions.freevars), maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, - item_types: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rcache: RefCell::new(FxHashMap()), tc_cache: RefCell::new(FxHashMap()), - associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), normalized_cache: RefCell::new(FxHashMap()), inhabitedness_cache: RefCell::new(FxHashMap()), lang_items: lang_items, - inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())), used_unsafe: RefCell::new(NodeSet()), used_mut_nodes: RefCell::new(NodeSet()), - used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), - monomorphic_const_eval: RefCell::new(DepTrackingMap::new(dep_graph.clone())), stability: RefCell::new(stability), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), - repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rvalue_promotable_to_static: RefCell::new(NodeMap()), - custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), - closure_tys: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - closure_kinds: RefCell::new(DepTrackingMap::new(dep_graph.clone())), fragment_infos: RefCell::new(DefIdMap()), crate_name: Symbol::intern(crate_name), data_layout: data_layout, @@ -1541,7 +1453,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Obtain the representation annotation for a struct definition. pub fn lookup_repr_hints(self, did: DefId) -> Rc> { - self.repr_hint_cache.memoize(did, || { + self.maps.repr_hints.memoize(did, || { Rc::new(self.get_attrs(did).iter().flat_map(|meta| { attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter() }).collect()) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index f45f00b4dec96..c31895b3e9df7 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -201,7 +201,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } else { // for local crates, check whether type info is // available; typeck might not have completed yet - self.impl_trait_refs.borrow().contains_key(&impl_def_id) + self.maps.impl_trait_refs.borrow().contains_key(&impl_def_id) }; if !use_types { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index cedb030749560..3e37bd50f942c 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::{DepNode, DepTrackingMapConfig}; +use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; use hir::def_id::DefId; use middle::const_val::ConstVal; -use mir; use ty::{self, Ty}; use util::nodemap::DefIdSet; @@ -20,36 +19,101 @@ use std::marker::PhantomData; use std::rc::Rc; use syntax::attr; -macro_rules! dep_map_ty { - ($ty_name:ident : $node_name:ident ($key:ty) -> $value:ty) => { - pub struct $ty_name<'tcx> { +macro_rules! define_maps { + ($($(#[$attr:meta])* pub $field:ident: $node_name:ident($key:ty) -> $value:ty),*) => { + pub struct Maps<'tcx> { + $($(#[$attr])* pub $field: RefCell>>),* + } + + impl<'tcx> Maps<'tcx> { + pub fn new(dep_graph: DepGraph) -> Self { + Maps { + $($field: RefCell::new(DepTrackingMap::new(dep_graph.clone()))),* + } + } + } + + $(#[allow(bad_style)] + pub struct $field<'tcx> { data: PhantomData<&'tcx ()> } - impl<'tcx> DepTrackingMapConfig for $ty_name<'tcx> { + impl<'tcx> DepTrackingMapConfig for $field<'tcx> { type Key = $key; type Value = $value; fn to_dep_node(key: &$key) -> DepNode { DepNode::$node_name(*key) } - } + })* } } -dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem } -dep_map_ty! { Types: ItemSignature(DefId) -> Ty<'tcx> } -dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics } -dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } -dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } -dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc> } -dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option> } -dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef } -dep_map_ty! { AdtDefs: ItemSignature(DefId) -> &'tcx ty::AdtDef } -dep_map_ty! { AdtSizedConstraint: SizedConstraint(DefId) -> Ty<'tcx> } -dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc> } -dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } -dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } -dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } -dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } -dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } -dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> } -dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet } -dep_map_ty! { MonomorphicConstEval: MonomorphicConstEval(DefId) -> Result } +define_maps! { + /// Maps from a trait item to the trait item "descriptor" + pub associated_items: AssociatedItems(DefId) -> ty::AssociatedItem, + + /// Records the type of every item. + pub types: ItemSignature(DefId) -> Ty<'tcx>, + + /// Maps from the def-id of an item (trait/struct/enum/fn) to its + /// associated generics and predicates. + pub generics: ItemSignature(DefId) -> &'tcx ty::Generics, + pub predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, + + /// Maps from the def-id of a trait to the list of + /// super-predicates. This is a subset of the full list of + /// predicates. We store these in a separate map because we must + /// evaluate them even during type conversion, often before the + /// full predicates are available (note that supertraits have + /// additional acyclicity requirements). + pub super_predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, + + /// Maps from an impl/trait def-id to a list of the def-ids of its items + pub associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc>, + + pub impl_trait_refs: ItemSignature(DefId) -> Option>, + pub trait_defs: ItemSignature(DefId) -> &'tcx ty::TraitDef, + pub adt_defs: ItemSignature(DefId) -> &'tcx ty::AdtDef, + pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>, + + /// Maps from def-id of a type or region parameter to its + /// (inferred) variance. + pub variances: ItemSignature(DefId) -> Rc>, + + /// Maps a DefId of a type to a list of its inherent impls. + /// Contains implementations of methods that are inherent to a type. + /// Methods in these implementations don't need to be exported. + pub inherent_impls: InherentImpls(DefId) -> Vec, + + /// Caches the representation hints for struct definitions. + pub repr_hints: ReprHints(DefId) -> Rc>, + + /// Maps from the def-id of a function/method or const/static + /// to its MIR. Mutation is done at an item granularity to + /// allow MIR optimization passes to function and still + /// access cross-crate MIR (e.g. inlining or const eval). + /// + /// Note that cross-crate MIR appears to be always borrowed + /// (in the `RefCell` sense) to prevent accidental mutation. + pub mir: Mir(DefId) -> &'tcx RefCell<::mir::Mir<'tcx>>, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_kinds: ItemSignature(DefId) -> ty::ClosureKind, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_types: ItemSignature(DefId) -> ty::ClosureTy<'tcx>, + + /// Caches CoerceUnsized kinds for impls on custom types. + pub custom_coerce_unsized_kinds: ItemSignature(DefId) + -> ty::adjustment::CustomCoerceUnsized, + + pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, + + /// Set of trait imports actually used in the method resolution. + /// This is used for warning unused imports. + pub used_trait_imports: UsedTraitImports(DefId) -> DefIdSet, + + /// Results of evaluating monomorphic constants embedded in + /// other items, such as enum variant explicit discriminants. + pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result +} diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index be4ec881482d1..7e0a35916d0bc 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1592,7 +1592,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().map(move |v| { let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr()); if let VariantDiscr::Explicit(expr_did) = v.discr { - match tcx.monomorphic_const_eval.borrow()[&expr_did] { + match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] { Ok(ConstVal::Integral(v)) => { discr = v; } @@ -1646,7 +1646,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { stack: &mut Vec) -> Ty<'tcx> { - if let Some(ty) = tcx.adt_sized_constraint.borrow().get(&self.did) { + if let Some(ty) = tcx.maps.adt_sized_constraint.borrow().get(&self.did) { return ty; } @@ -1660,7 +1660,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { // // Consider the type as Sized in the meanwhile to avoid // further errors. - tcx.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err); + tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err); return tcx.types.err; } @@ -1684,7 +1684,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { _ => tcx.intern_tup(&tys[..], false) }; - let old = tcx.adt_sized_constraint.borrow().get(&self.did).cloned(); + let old = tcx.maps.adt_sized_constraint.borrow().get(&self.did).cloned(); match old { Some(old_ty) => { debug!("calculate_sized_constraint: {:?} recurred", self); @@ -1693,7 +1693,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } None => { debug!("calculate_sized_constraint: {:?} => {:?}", self, ty); - tcx.adt_sized_constraint.borrow_mut().insert(self.did, ty); + tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, ty); ty } } @@ -1969,7 +1969,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn item_tables(self, def_id: DefId) -> &'gcx TypeckTables<'gcx> { - self.tables.memoize(def_id, || { + self.maps.typeck_tables.memoize(def_id, || { if def_id.is_local() { // Closures' tables come from their outermost function, // as they are part of the same "inference environment". @@ -1983,7 +1983,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Cross-crate side-tables only exist alongside serialized HIR. self.sess.cstore.maybe_get_item_body(self.global_tcx(), def_id).map(|_| { - self.tables.borrow()[&def_id] + self.maps.typeck_tables.borrow()[&def_id] }).unwrap_or_else(|| { bug!("tcx.item_tables({:?}): missing from metadata", def_id) }) @@ -2095,7 +2095,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized { - self.custom_coerce_unsized_kinds.memoize(did, || { + self.maps.custom_coerce_unsized_kinds.memoize(did, || { let (kind, src) = if did.krate != LOCAL_CRATE { (self.sess.cstore.custom_coerce_unsized_kind(did), "external") } else { @@ -2114,7 +2114,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn associated_item(self, def_id: DefId) -> AssociatedItem { - self.associated_items.memoize(def_id, || { + self.maps.associated_items.memoize(def_id, || { if !def_id.is_local() { return self.sess.cstore.associated_item(def_id) .expect("missing AssociatedItem in metadata"); @@ -2141,7 +2141,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.associated_item_from_impl_item_ref(parent_def_id, impl_trait_ref.is_some(), impl_item_ref); - self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item); + self.maps.associated_items.borrow_mut() + .insert(assoc_item.def_id, assoc_item); } } @@ -2149,7 +2150,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { for trait_item_ref in trait_item_refs { let assoc_item = self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref); - self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item); + self.maps.associated_items.borrow_mut() + .insert(assoc_item.def_id, assoc_item); } } @@ -2160,7 +2162,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // memoize wants us to return something, so return // the one we generated for this def-id - *self.associated_items.borrow().get(&def_id).unwrap() + *self.maps.associated_items.borrow().get(&def_id).unwrap() }) } @@ -2218,7 +2220,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn associated_item_def_ids(self, def_id: DefId) -> Rc> { - self.associated_item_def_ids.memoize(def_id, || { + self.maps.associated_item_def_ids.memoize(def_id, || { if !def_id.is_local() { return Rc::new(self.sess.cstore.associated_item_def_ids(def_id)); } @@ -2255,7 +2257,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// an inherent impl. pub fn impl_trait_ref(self, id: DefId) -> Option> { lookup_locally_or_in_crate_store( - "impl_trait_refs", id, &self.impl_trait_refs, + "impl_trait_refs", id, &self.maps.impl_trait_refs, || self.sess.cstore.impl_trait_ref(self.global_tcx(), id)) } @@ -2336,14 +2338,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // the type cache. Returns the type parameters and type. pub fn item_type(self, did: DefId) -> Ty<'gcx> { lookup_locally_or_in_crate_store( - "item_types", did, &self.item_types, + "item_types", did, &self.maps.types, || self.sess.cstore.item_type(self.global_tcx(), did)) } /// Given the did of a trait, returns its canonical trait ref. pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef { lookup_locally_or_in_crate_store( - "trait_defs", did, &self.trait_defs, + "trait_defs", did, &self.maps.trait_defs, || self.alloc_trait_def(self.sess.cstore.trait_def(self.global_tcx(), did)) ) } @@ -2351,34 +2353,34 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Given the did of an ADT, return a reference to its definition. pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef { lookup_locally_or_in_crate_store( - "adt_defs", did, &self.adt_defs, + "adt_defs", did, &self.maps.adt_defs, || self.sess.cstore.adt_def(self.global_tcx(), did)) } /// Given the did of an item, returns its generics. pub fn item_generics(self, did: DefId) -> &'gcx Generics { lookup_locally_or_in_crate_store( - "generics", did, &self.generics, + "generics", did, &self.maps.generics, || self.alloc_generics(self.sess.cstore.item_generics(did))) } /// Given the did of an item, returns its full set of predicates. pub fn item_predicates(self, did: DefId) -> GenericPredicates<'gcx> { lookup_locally_or_in_crate_store( - "predicates", did, &self.predicates, + "predicates", did, &self.maps.predicates, || self.sess.cstore.item_predicates(self.global_tcx(), did)) } /// Given the did of a trait, returns its superpredicates. pub fn item_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> { lookup_locally_or_in_crate_store( - "super_predicates", did, &self.super_predicates, + "super_predicates", did, &self.maps.super_predicates, || self.sess.cstore.item_super_predicates(self.global_tcx(), did)) } /// Given the did of an item, returns its MIR, borrowed immutably. pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> { - lookup_locally_or_in_crate_store("mir_map", did, &self.mir_map, || { + lookup_locally_or_in_crate_store("mir_map", did, &self.maps.mir, || { let mir = self.sess.cstore.get_item_mir(self.global_tcx(), did); let mir = self.alloc_mir(mir); @@ -2450,7 +2452,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn item_variances(self, item_id: DefId) -> Rc> { lookup_locally_or_in_crate_store( - "item_variance_map", item_id, &self.item_variance_map, + "item_variance_map", item_id, &self.maps.variances, || Rc::new(self.sess.cstore.item_variances(item_id))) } @@ -2488,7 +2490,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id); - self.inherent_impls.borrow_mut().insert(type_id, inherent_impls); + self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls); self.populated_external_types.borrow_mut().insert(type_id); } @@ -2529,12 +2531,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(&kind) = self.closure_kinds.borrow().get(&def_id) { + if let Some(&kind) = self.maps.closure_kinds.borrow().get(&def_id) { return kind; } let kind = self.sess.cstore.closure_kind(def_id); - self.closure_kinds.borrow_mut().insert(def_id, kind); + self.maps.closure_kinds.borrow_mut().insert(def_id, kind); kind } @@ -2546,12 +2548,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(ty) = self.closure_tys.borrow().get(&def_id) { + if let Some(ty) = self.maps.closure_types.borrow().get(&def_id) { return ty.subst(self, substs.substs); } let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id); - self.closure_tys.borrow_mut().insert(def_id, ty.clone()); + self.maps.closure_types.borrow_mut().insert(def_id, ty.clone()); ty.subst(self, substs.substs) } @@ -2572,7 +2574,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } }); } - match self.associated_items.borrow().get(&def_id).cloned() { + match self.maps.associated_items.borrow().get(&def_id).cloned() { Some(trait_item) => { match trait_item.container { TraitContainer(_) => None, @@ -2590,7 +2592,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if def_id.krate != LOCAL_CRATE { return self.sess.cstore.trait_of_item(def_id); } - match self.associated_items.borrow().get(&def_id) { + match self.maps.associated_items.borrow().get(&def_id) { Some(associated_item) => { match associated_item.container { TraitContainer(def_id) => Some(def_id), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 2a5cd7b37cae4..fa53760eca466 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -770,7 +770,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { TyAdt(def, substs) => { ty::tls::with(|tcx| { if def.did.is_local() && - !tcx.item_types.borrow().contains_key(&def.did) { + !tcx.maps.types.borrow().contains_key(&def.did) { write!(f, "{}<..>", tcx.item_path_str(def.did)) } else { parameterized(f, substs, def.did, &[]) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index af4f63a05613e..13ece31f4ce13 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -58,7 +58,7 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return variant.node.disr_expr.map(|e| { let def_id = tcx.hir.body_owner_def_id(e); (&tcx.hir.body(e).value, - tcx.tables.borrow().get(&def_id).cloned()) + tcx.maps.typeck_tables.borrow().get(&def_id).cloned()) }); } } @@ -89,7 +89,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node: hir::ImplItemKind::Const(ref ty, body), .. })) => { Some((&tcx.hir.body(body).value, - tcx.tables.borrow().get(&def_id).cloned(), + tcx.maps.typeck_tables.borrow().get(&def_id).cloned(), tcx.ast_ty_to_prim_ty(ty))) } Some(hir_map::NodeTraitItem(ti)) => match ti.node { @@ -102,7 +102,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_id = tcx.hir.local_def_id(trait_id); let default_value = default.map(|body| { (&tcx.hir.body(body).value, - tcx.tables.borrow().get(&def_id).cloned(), + tcx.maps.typeck_tables.borrow().get(&def_id).cloned(), tcx.ast_ty_to_prim_ty(ty)) }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) @@ -156,7 +156,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) FnLikeNode::from_node(tcx.hir.get(node_id)).and_then(|fn_like| { if fn_like.constness() == hir::Constness::Const { Some((tcx.hir.body(fn_like.body()), - tcx.tables.borrow().get(&def_id).cloned())) + tcx.maps.typeck_tables.borrow().get(&def_id).cloned())) } else { None } @@ -231,7 +231,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> { let def_id = tcx.hir.body_owner_def_id(body); ConstContext { tcx: tcx, - tables: tcx.tables.borrow().get(&def_id).cloned(), + tables: tcx.maps.typeck_tables.borrow().get(&def_id).cloned(), fn_args: None } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 21fe13997b787..429e4ffef0c2a 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -996,11 +996,13 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, } else { match ppm { PpmMir => { - write_mir_pretty(tcx, tcx.mir_map.borrow().keys().into_iter(), &mut out) + write_mir_pretty(tcx, + tcx.maps.mir.borrow().keys().into_iter(), + &mut out) } PpmMirCFG => { write_mir_graphviz(tcx, - tcx.mir_map.borrow().keys().into_iter(), + tcx.maps.mir.borrow().keys().into_iter(), &mut out) } _ => unreachable!(), diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 0c86eb42e7acb..5fcefe0d53997 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -29,7 +29,7 @@ pub enum MethodLateContext { pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext { let def_id = cx.tcx.hir.local_def_id(id); - match cx.tcx.associated_items.borrow().get(&def_id) { + match cx.tcx.maps.associated_items.borrow().get(&def_id) { None => span_bug!(span, "missing method descriptor?!"), Some(item) => { match item.container { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 88b06e29e103c..aa18fbe2ba8cd 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -527,7 +527,7 @@ impl<'a, 'tcx> CrateMetadata { if let ty::VariantDiscr::Explicit(def_id) = data.discr { let result = data.evaluated_discr.map_or(Err(()), Ok); - tcx.monomorphic_const_eval.borrow_mut().insert(def_id, result); + tcx.maps.monomorphic_const_eval.borrow_mut().insert(def_id, result); } (ty::VariantDef { @@ -584,7 +584,7 @@ impl<'a, 'tcx> CrateMetadata { let adt = tcx.alloc_adt_def(did, kind, variants, repr); if let Some(ctor_index) = ctor_index { // Make adt definition available through constructor id as well. - tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt); + tcx.maps.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt); } adt @@ -789,7 +789,7 @@ impl<'a, 'tcx> CrateMetadata { let ast = ast.decode(self); let tables = ast.tables.decode((self, tcx)); - tcx.tables.borrow_mut().insert(def_id, tcx.alloc_tables(tables)); + tcx.maps.typeck_tables.borrow_mut().insert(def_id, tcx.alloc_tables(tables)); let body = ast.body.decode((self, tcx)); tcx.hir.intern_inlined_body(def_id, body) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 725d54c227a30..e6110172fc41f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { discr: variant.discr, evaluated_discr: match variant.discr { ty::VariantDiscr::Explicit(def_id) => { - tcx.monomorphic_const_eval.borrow()[&def_id].clone().ok() + tcx.maps.monomorphic_const_eval.borrow()[&def_id].clone().ok() } ty::VariantDiscr::Relative(_) => None }, @@ -604,12 +604,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_mir(&mut self, def_id: DefId) -> Option>> { - self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow())) + self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow())) } // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { - match self.tcx.inherent_impls.borrow().get(&def_id) { + match self.tcx.maps.inherent_impls.borrow().get(&def_id) { None => LazySeq::empty(), Some(implementations) => { self.lazy_seq(implementations.iter().map(|&def_id| { @@ -711,7 +711,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ImplData { polarity: polarity, parent_impl: parent, - coerce_unsized_kind: tcx.custom_coerce_unsized_kinds + coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kinds .borrow() .get(&def_id) .cloned(), @@ -1096,7 +1096,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.closure_tys.borrow()[&def_id]), + ty: self.lazy(&tcx.maps.closure_types.borrow()[&def_id]), }; Entry { diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index b7f90682c7c74..913b0d5fb8ae8 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { let mir = tcx.alloc_mir(mir); let def_id = tcx.hir.local_def_id(src.item_id()); - tcx.mir_map.borrow_mut().insert(def_id, mir); + tcx.maps.mir.borrow_mut().insert(def_id, mir); }); let body = self.tcx.hir.body(body_id); diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 33b7089c38214..ad20c535decbb 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -44,7 +44,7 @@ pub fn print_mir_stats<'tcx, 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, title: &str) { // For debugging instrumentation like this, we don't need to worry // about maintaining the dep graph. let _ignore = tcx.dep_graph.in_ignore(); - let mir_map = tcx.mir_map.borrow(); + let mir_map = tcx.maps.mir.borrow(); for def_id in mir_map.keys() { let mir = mir_map.get(&def_id).unwrap(); collector.visit_mir(&mir.borrow()); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 6667a3199a809..3c275e0996dac 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -112,7 +112,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>) { let item_def_id = self.tcx.hir.local_def_id(item_id); - match self.tcx.tables.borrow().get(&item_def_id) { + match self.tcx.maps.typeck_tables.borrow().get(&item_def_id) { Some(tables) => { let old_tables = self.save_ctxt.tables; self.save_ctxt.tables = tables; diff --git a/src/librustc_trans/disr.rs b/src/librustc_trans/disr.rs index 00c0e0d541586..a940faac83877 100644 --- a/src/librustc_trans/disr.rs +++ b/src/librustc_trans/disr.rs @@ -28,7 +28,7 @@ impl Disr { explicit_index -= distance; } ty::VariantDiscr::Explicit(expr_did) => { - match tcx.monomorphic_const_eval.borrow()[&expr_did] { + match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] { Ok(ConstVal::Integral(v)) => { explicit_value = Disr::from(v); break; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cd7474cf50b8c..11ad47eef7159 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1209,7 +1209,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ast_ty.span); let predicates = bounds.predicates(tcx, ty); let predicates = tcx.lift_to_global(&predicates).unwrap(); - tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { parent: None, predicates: predicates }); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index fd29ff0be43b4..468a38cd2bace 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -483,7 +483,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // metadata if necessary. self.tcx.populate_inherent_implementations_for_type_if_necessary(def_id); - if let Some(impl_infos) = self.tcx.inherent_impls.borrow().get(&def_id) { + if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) { for &impl_def_id in impl_infos.iter() { self.assemble_inherent_impl_probe(impl_def_id); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index a25e5f3f283dd..b3a4b83b6832c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -56,12 +56,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_lints(); let tables = self.tcx.alloc_tables(wbcx.tables); - self.tcx.tables.borrow_mut().insert(item_def_id, tables); + self.tcx.maps.typeck_tables.borrow_mut().insert(item_def_id, tables); let used_trait_imports = mem::replace(&mut *self.used_trait_imports.borrow_mut(), DefIdSet()); debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); - self.tcx.used_trait_imports.borrow_mut().insert(item_def_id, used_trait_imports); + self.tcx.maps.used_trait_imports.borrow_mut().insert(item_def_id, used_trait_imports); } } @@ -290,12 +290,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); let def_id = self.tcx().hir.local_def_id(id); - self.tcx().closure_tys.borrow_mut().insert(def_id, closure_ty); + self.tcx().maps.closure_types.borrow_mut().insert(def_id, closure_ty); } for (&id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { let def_id = self.tcx().hir.local_def_id(id); - self.tcx().closure_kinds.borrow_mut().insert(def_id, closure_kind); + self.tcx().maps.closure_kinds.borrow_mut().insert(def_id, closure_kind); } } @@ -361,7 +361,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } }); - gcx.item_types.borrow_mut().insert(def_id, outside_ty); + gcx.maps.types.borrow_mut().insert(def_id, outside_ty); } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 6dff6d57e4fac..0f992f75fce34 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -70,7 +70,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let item_def_id = tcx.hir.local_def_id(item_id); // this will have been written by the main typeck pass - if let Some(imports) = tcx.used_trait_imports.borrow().get(&item_def_id) { + if let Some(imports) = tcx.maps.used_trait_imports.borrow().get(&item_def_id) { debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend(imports); } else { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 96875fce468d2..e15386b87ad97 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -341,7 +341,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id); if let Some(kind) = kind { - tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind); + tcx.maps.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind); } }); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index b6a863fd2ed0d..1301f33d30b08 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -39,7 +39,7 @@ mod unsafety; struct CoherenceCollect<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - inherent_impls: RefMut<'a, DepTrackingMap>>, + inherent_impls: RefMut<'a, DepTrackingMap>>, } impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { @@ -58,7 +58,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> { fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let inherent_impls = tcx.inherent_impls.borrow_mut(); + let inherent_impls = tcx.maps.inherent_impls.borrow_mut(); let mut this = &mut CoherenceCollect { tcx, inherent_impls }; // Check implementations and traits. This populates the tables diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 56c17dc2f6efd..45493d40eb802 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -79,7 +79,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) { let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id)); - let inherent_impls = self.tcx.inherent_impls.borrow(); + let inherent_impls = self.tcx.maps.inherent_impls.borrow(); let impls = match inherent_impls.get(&ty_def_id) { Some(impls) => impls, None => return, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3f3fc40320eb6..3851cd2bb442a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -606,8 +606,8 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, { generics_of_def_id(ccx, ty_f.did); let tt = ccx.icx(ty_f.did).to_ty(&field.ty); - ccx.tcx.item_types.borrow_mut().insert(ty_f.did, tt); - ccx.tcx.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { + ccx.tcx.maps.types.borrow_mut().insert(ty_f.did, tt); + ccx.tcx.maps.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { parent: Some(ccx.tcx.hir.get_parent_did(field.id)), predicates: vec![] }); @@ -619,7 +619,7 @@ fn convert_method(ccx: &CrateCtxt, id: ast::NodeId, sig: &hir::MethodSig) { let fty = AstConv::ty_of_fn(&ccx.icx(def_id), sig.unsafety, sig.abi, &sig.decl); let substs = mk_item_substs(ccx, def_id); let fty = ccx.tcx.mk_fn_def(def_id, substs, fty); - ccx.tcx.item_types.borrow_mut().insert(def_id, fty); + ccx.tcx.maps.types.borrow_mut().insert(def_id, fty); ty_generic_predicates(ccx, def_id, &sig.generics); } @@ -634,8 +634,8 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, predicates: vec![] }; let def_id = ccx.tcx.hir.local_def_id(id); - ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); - ccx.tcx.item_types.borrow_mut().insert(def_id, ty); + ccx.tcx.maps.predicates.borrow_mut().insert(def_id, predicates); + ccx.tcx.maps.types.borrow_mut().insert(def_id, ty); } fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -648,10 +648,10 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, predicates: vec![] }; let def_id = ccx.tcx.hir.local_def_id(id); - ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); + ccx.tcx.maps.predicates.borrow_mut().insert(def_id, predicates); if let Some(ty) = ty { - ccx.tcx.item_types.borrow_mut().insert(def_id, ty); + ccx.tcx.maps.types.borrow_mut().insert(def_id, ty); } } @@ -725,8 +725,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.record_trait_has_default_impl(trait_ref.def_id); - tcx.impl_trait_refs.borrow_mut().insert(ccx.tcx.hir.local_def_id(it.id), - Some(trait_ref)); + tcx.maps.impl_trait_refs.borrow_mut().insert(ccx.tcx.hir.local_def_id(it.id), + Some(trait_ref)); } hir::ItemImpl(.., ref opt_trait_ref, _, _) => { generics_of_def_id(ccx, def_id); @@ -735,7 +735,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) }); - tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref); + tcx.maps.impl_trait_refs.borrow_mut().insert(def_id, trait_ref); predicates_of_item(ccx, it); }, @@ -864,8 +864,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, })) } }; - tcx.item_types.borrow_mut().insert(def_id, ctor_ty); - tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + tcx.maps.types.borrow_mut().insert(def_id, ctor_ty); + tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { parent: Some(ccx.tcx.hir.get_parent_did(ctor_id)), predicates: vec![] }); @@ -888,7 +888,7 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let result = evaluate_disr_expr(ccx, repr_type, e); let expr_did = tcx.hir.local_def_id(e.node_id); - tcx.monomorphic_const_eval.borrow_mut() + tcx.maps.monomorphic_const_eval.borrow_mut() .insert(expr_did, result.map(ConstVal::Integral)); result.ok() @@ -966,10 +966,10 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ReprOptions::new(&ccx.tcx, did)); if let Some(ctor_id) = ctor_id { // Make adt definition available through constructor id as well. - ccx.tcx.adt_defs.borrow_mut().insert(ctor_id, adt); + ccx.tcx.maps.adt_defs.borrow_mut().insert(ctor_id, adt); } - ccx.tcx.adt_defs.borrow_mut().insert(did, adt); + ccx.tcx.maps.adt_defs.borrow_mut().insert(did, adt); adt } @@ -983,7 +983,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty::VariantDiscr::Relative(0), def)]; let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did)); - ccx.tcx.adt_defs.borrow_mut().insert(did, adt); + ccx.tcx.maps.adt_defs.borrow_mut().insert(did, adt); adt } @@ -1061,7 +1061,7 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let did = tcx.hir.local_def_id(it.id); let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did)); - tcx.adt_defs.borrow_mut().insert(did, adt); + tcx.maps.adt_defs.borrow_mut().insert(did, adt); adt } @@ -1091,7 +1091,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, return Vec::new(); }; - let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned(); + let superpredicates = tcx.maps.super_predicates.borrow().get(&trait_def_id).cloned(); let superpredicates = superpredicates.unwrap_or_else(|| { let item = match ccx.tcx.hir.get(trait_node_id) { hir_map::NodeItem(item) => item, @@ -1130,7 +1130,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, tcx.hir.local_def_id(item.id), superpredicates); - tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone()); + tcx.maps.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone()); superpredicates }); @@ -1150,7 +1150,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'t let tcx = ccx.tcx; let def_id = tcx.hir.local_def_id(it.id); - tcx.trait_defs.memoize(def_id, || { + tcx.maps.trait_defs.memoize(def_id, || { let unsafety = match it.node { hir::ItemTrait(unsafety, ..) => unsafety, _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"), @@ -1182,7 +1182,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { return tcx.item_generics(def_id); }; - tcx.generics.memoize(def_id, || { + tcx.maps.generics.memoize(def_id, || { use rustc::hir::map::*; use rustc::hir::*; @@ -1380,7 +1380,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { return ccx.tcx.item_type(def_id); }; - ccx.tcx.item_types.memoize(def_id, || { + ccx.tcx.maps.types.memoize(def_id, || { use rustc::hir::map::*; use rustc::hir::*; @@ -1718,7 +1718,7 @@ fn ty_generic_predicates(ccx: &CrateCtxt, def_id: DefId, ast_generics: &hir::Gen &mut ctp::parameters_for_impl(self_ty, trait_ref)); } - tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { parent: generics.parent, predicates: predicates }); diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index b22db94079891..3d2b746b85548 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -13,12 +13,10 @@ //! The second pass over the AST determines the set of constraints. //! We walk the set of items and, for each member, generate new constraints. -use dep_graph::DepTrackingMapConfig; use hir::def_id::DefId; use middle::resolve_lifetime as rl; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::maps::ItemVariances; use rustc::hir::map as hir_map; use syntax::ast; use rustc::hir; @@ -28,6 +26,8 @@ use super::terms::*; use super::terms::VarianceTerm::*; use super::xform::*; +use dep_graph::DepNode::ItemSignature as VarianceDepNode; + pub struct ConstraintContext<'a, 'tcx: 'a> { pub terms_cx: TermsContext<'a, 'tcx>, @@ -65,8 +65,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) }; // See README.md for a discussion on dep-graph management. - tcx.visit_all_item_likes_in_krate(|def_id| ItemVariances::to_dep_node(&def_id), - &mut constraint_cx); + tcx.visit_all_item_likes_in_krate(VarianceDepNode, &mut constraint_cx); constraint_cx } @@ -291,7 +290,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // This edge is actually implied by the call to // `lookup_trait_def`, but I'm trying to be future-proof. See // README.md for a discussion on dep-graph management. - self.tcx().dep_graph.read(ItemVariances::to_dep_node(&trait_ref.def_id)); + self.tcx().dep_graph.read(VarianceDepNode(trait_ref.def_id)); self.add_constraints_from_substs(generics, trait_ref.def_id, @@ -350,7 +349,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // This edge is actually implied by the call to // `lookup_trait_def`, but I'm trying to be future-proof. See // README.md for a discussion on dep-graph management. - self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did)); + self.tcx().dep_graph.read(VarianceDepNode(def.did)); self.add_constraints_from_substs(generics, def.did, @@ -367,7 +366,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // This edge is actually implied by the call to // `lookup_trait_def`, but I'm trying to be future-proof. See // README.md for a discussion on dep-graph management. - self.tcx().dep_graph.read(ItemVariances::to_dep_node(&trait_ref.def_id)); + self.tcx().dep_graph.read(VarianceDepNode(trait_ref.def_id)); self.add_constraints_from_substs(generics, trait_ref.def_id, diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 3ccec97d606ea..6628c7c521fd1 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -137,7 +137,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { item_variances); } - tcx.item_variance_map + tcx.maps.variances .borrow_mut() .insert(item_def_id, Rc::new(item_variances)); } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 253d7a25b632f..36352f50e4406 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -20,9 +20,7 @@ // a variable. use arena::TypedArena; -use dep_graph::DepTrackingMapConfig; use rustc::ty::{self, TyCtxt}; -use rustc::ty::maps::ItemVariances; use std::fmt; use std::rc::Rc; use syntax::ast; @@ -34,6 +32,8 @@ use self::VarianceTerm::*; pub type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; +use dep_graph::DepNode::ItemSignature as VarianceDepNode; + #[derive(Copy, Clone, Debug)] pub struct InferredIndex(pub usize); @@ -109,7 +109,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> }; // See README.md for a discussion on dep-graph management. - tcx.visit_all_item_likes_in_krate(|def_id| ItemVariances::to_dep_node(&def_id), &mut terms_cx); + tcx.visit_all_item_likes_in_krate(|def_id| VarianceDepNode(def_id), &mut terms_cx); terms_cx } @@ -178,8 +178,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { // parameters". if self.num_inferred() == inferreds_on_entry { let item_def_id = self.tcx.hir.local_def_id(item_id); - self.tcx - .item_variance_map + self.tcx.maps.variances .borrow_mut() .insert(item_def_id, self.empty_variances.clone()); } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 93854193762fb..02d934783d464 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -238,7 +238,7 @@ pub fn build_impls(cx: &DocContext, did: DefId) -> Vec { tcx.populate_inherent_implementations_for_type_if_necessary(did); let mut impls = Vec::new(); - if let Some(i) = tcx.inherent_impls.borrow().get(&did) { + if let Some(i) = tcx.maps.inherent_impls.borrow().get(&did) { for &did in i.iter() { build_impl(cx, did, &mut impls); } From b5c4244c6c46df22bb55531b629f4c314fe2ab22 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 29 Sep 2016 02:30:53 +0300 Subject: [PATCH 05/17] rustc: introduce a query system for type information in ty::maps. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/middle/cstore.rs | 82 +++------ src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/stability.rs | 34 ++-- src/librustc/session/mod.rs | 8 +- src/librustc/traits/fulfill.rs | 2 +- src/librustc/ty/context.rs | 16 +- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/maps.rs | 119 +++++++++---- src/librustc/ty/mod.rs | 147 ++++------------ src/librustc/util/ppaux.rs | 2 +- src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/driver.rs | 9 +- src/librustc_driver/test.rs | 2 + src/librustc_lint/bad_style.rs | 2 +- src/librustc_metadata/cstore.rs | 2 + src/librustc_metadata/cstore_impl.rs | 177 ++++++++++---------- src/librustc_metadata/decoder.rs | 61 +++---- src/librustc_metadata/encoder.rs | 4 +- src/librustc_metadata/lib.rs | 1 + src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_typeck/check/upvar.rs | 2 +- src/librustc_typeck/check/writeback.rs | 6 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/collect.rs | 32 ++-- src/librustdoc/visit_lib.rs | 2 +- 27 files changed, 333 insertions(+), 393 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 82e644d710dc2..bfcaf1e00f06e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -525,7 +525,7 @@ impl<'a> LoweringContext<'a> { return n; } assert!(!def_id.is_local()); - let n = self.sess.cstore.item_generics(def_id).regions.len(); + let n = self.sess.cstore.item_generics_cloned(def_id).regions.len(); self.type_def_lifetime_params.insert(def_id, n); n }); diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 671da0d11972b..cb5ced57bd8b9 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -28,12 +28,12 @@ use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; use hir::svh::Svh; use middle::lang_items; -use ty::{self, Ty, TyCtxt}; -use mir::Mir; +use ty::{self, TyCtxt}; use session::Session; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; +use std::any::Any; use std::collections::BTreeMap; use std::path::PathBuf; use std::rc::Rc; @@ -163,28 +163,18 @@ pub struct ExternCrate { /// A store of Rust crates, through with their metadata /// can be accessed. -pub trait CrateStore<'tcx> { +pub trait CrateStore { + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc; + // item info fn describe_def(&self, def: DefId) -> Option; fn def_span(&self, sess: &Session, def: DefId) -> Span; fn stability(&self, def: DefId) -> Option; fn deprecation(&self, def: DefId) -> Option; fn visibility(&self, def: DefId) -> ty::Visibility; - fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind; - fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> ty::ClosureTy<'tcx>; - fn item_variances(&self, def: DefId) -> Vec; - fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Ty<'tcx>; fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap>; - fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::GenericPredicates<'tcx>; - fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::GenericPredicates<'tcx>; - fn item_generics(&self, def: DefId) -> ty::Generics; + fn item_generics_cloned(&self, def: DefId) -> ty::Generics; fn item_attrs(&self, def_id: DefId) -> Vec; - fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef; - fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef; fn fn_arg_names(&self, did: DefId) -> Vec; fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec; @@ -192,17 +182,12 @@ pub trait CrateStore<'tcx> { fn implementations_of_trait(&self, filter: Option) -> Vec; // impl info - fn associated_item_def_ids(&self, def_id: DefId) -> Vec; - fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option>; fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity; - fn custom_coerce_unsized_kind(&self, def: DefId) - -> Option; fn impl_parent(&self, impl_def_id: DefId) -> Option; // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option; - fn associated_item(&self, def: DefId) -> Option; + fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem; // flags fn is_const_fn(&self, did: DefId) -> bool; @@ -252,12 +237,11 @@ pub trait CrateStore<'tcx> { fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; // misc. metadata - fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option<&'tcx hir::Body>; + fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option<&'tcx hir::Body>; fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap; fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool; - fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>; fn is_item_mir_available(&self, def: DefId) -> bool; // This is basically a 1-based range of ints, which is a little @@ -272,10 +256,10 @@ pub trait CrateStore<'tcx> { fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>; fn used_crate_source(&self, cnum: CrateNum) -> CrateSource; fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; - fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - reexports: &def::ExportMap, - link_meta: &LinkMeta, - reachable: &NodeSet) -> Vec; + fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + reexports: &def::ExportMap, + link_meta: &LinkMeta, + reachable: &NodeSet) -> Vec; fn metadata_encoding_version(&self) -> &[u8]; } @@ -309,33 +293,23 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { /// A dummy crate store that does not support any non-local crates, /// for test purposes. pub struct DummyCrateStore; + #[allow(unused_variables)] -impl<'tcx> CrateStore<'tcx> for DummyCrateStore { +impl CrateStore for DummyCrateStore { + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc + { bug!("crate_data_as_rc_any") } // item info fn describe_def(&self, def: DefId) -> Option { bug!("describe_def") } fn def_span(&self, sess: &Session, def: DefId) -> Span { bug!("def_span") } fn stability(&self, def: DefId) -> Option { bug!("stability") } fn deprecation(&self, def: DefId) -> Option { bug!("deprecation") } fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind { bug!("closure_kind") } - fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> ty::ClosureTy<'tcx> { bug!("closure_ty") } - fn item_variances(&self, def: DefId) -> Vec { bug!("item_variances") } - fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Ty<'tcx> { bug!("item_type") } fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap> { bug!("visible_parent_map") } - fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::GenericPredicates<'tcx> { bug!("item_predicates") } - fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } - fn item_generics(&self, def: DefId) -> ty::Generics { bug!("item_generics") } + fn item_generics_cloned(&self, def: DefId) -> ty::Generics + { bug!("item_generics_cloned") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } - fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef - { bug!("trait_def") } - fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef - { bug!("adt_def") } fn fn_arg_names(&self, did: DefId) -> Vec { bug!("fn_arg_names") } fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec { vec![] } @@ -343,19 +317,13 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn implementations_of_trait(&self, filter: Option) -> Vec { vec![] } // impl info - fn associated_item_def_ids(&self, def_id: DefId) -> Vec - { bug!("associated_items") } - fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option> { bug!("impl_trait_ref") } fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") } - fn custom_coerce_unsized_kind(&self, def: DefId) - -> Option - { bug!("custom_coerce_unsized_kind") } fn impl_parent(&self, def: DefId) -> Option { bug!("impl_parent") } // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option { bug!("trait_of_item") } - fn associated_item(&self, def: DefId) -> Option { bug!("associated_item") } + fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem + { bug!("associated_item_cloned") } // flags fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } @@ -418,8 +386,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } // misc. metadata - fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option<&'tcx hir::Body> { + fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option<&'tcx hir::Body> { bug!("maybe_get_item_body") } fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap { @@ -429,8 +397,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { bug!("const_is_rvalue_promotable_to_static") } - fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Mir<'tcx> { bug!("get_item_mir") } fn is_item_mir_available(&self, def: DefId) -> bool { bug!("is_item_mir_available") } @@ -448,7 +414,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { { vec![] } fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") } fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } - fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, reexports: &def::ExportMap, link_meta: &LinkMeta, reachable: &NodeSet) -> Vec { vec![] } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 95cbd738651d5..37749816eb153 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -995,7 +995,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else { let cstore = &self.sess.cstore; self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| { - cstore.item_generics(def_id).types.into_iter().map(|def| { + cstore.item_generics_cloned(def_id).types.into_iter().map(|def| { def.object_lifetime_default }).collect() }) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 487e13b47fec2..baa22d7061435 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -433,23 +433,27 @@ struct Checker<'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // (See issue #38412) - fn skip_stability_check_due_to_privacy(self, def_id: DefId) -> bool { - let visibility = { - // Check if `def_id` is a trait method. - match self.sess.cstore.associated_item(def_id) { - Some(ty::AssociatedItem { container: ty::TraitContainer(trait_def_id), .. }) => { - // Trait methods do not declare visibility (even - // for visibility info in cstore). Use containing - // trait instead, so methods of pub traits are - // themselves considered pub. - self.sess.cstore.visibility(trait_def_id) - } - _ => { - // Otherwise, cstore info works directly. - self.sess.cstore.visibility(def_id) + fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool { + // Check if `def_id` is a trait method. + match self.sess.cstore.describe_def(def_id) { + Some(Def::Method(_)) | + Some(Def::AssociatedTy(_)) | + Some(Def::AssociatedConst(_)) => { + match self.associated_item(def_id).container { + ty::TraitContainer(trait_def_id) => { + // Trait methods do not declare visibility (even + // for visibility info in cstore). Use containing + // trait instead, so methods of pub traits are + // themselves considered pub. + def_id = trait_def_id; + } + _ => {} } } - }; + _ => {} + } + + let visibility = self.sess.cstore.visibility(def_id); match visibility { // must check stability for pub items. diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 68edcc60779a1..3ba82f34c3266 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -64,7 +64,7 @@ pub struct Session { pub target: config::Config, pub host: Target, pub opts: config::Options, - pub cstore: Rc CrateStore<'a>>, + pub cstore: Rc, pub parse_sess: ParseSess, // For a library crate, this is always none pub entry_fn: RefCell>, @@ -510,7 +510,7 @@ pub fn build_session(sopts: config::Options, dep_graph: &DepGraph, local_crate_source_file: Option, registry: errors::registry::Registry, - cstore: Rc CrateStore<'a>>) + cstore: Rc) -> Session { build_session_with_codemap(sopts, dep_graph, @@ -525,7 +525,7 @@ pub fn build_session_with_codemap(sopts: config::Options, dep_graph: &DepGraph, local_crate_source_file: Option, registry: errors::registry::Registry, - cstore: Rc CrateStore<'a>>, + cstore: Rc, codemap: Rc, emitter_dest: Option>) -> Session { @@ -575,7 +575,7 @@ pub fn build_session_(sopts: config::Options, local_crate_source_file: Option, span_diagnostic: errors::Handler, codemap: Rc, - cstore: Rc CrateStore<'a>>) + cstore: Rc) -> Session { let host = match Target::search(config::host_triple()) { Ok(t) => t, diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index e28a8392e58d7..c31ab2372b69c 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -155,7 +155,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { -> Option>> { if let ty::TyAnon(def_id, substs) = self.predicate.skip_binder().self_ty().sty { let ty = if def_id.is_local() { - tcx.maps.types.borrow().get(&def_id).cloned() + tcx.maps.ty.borrow().get(&def_id).cloned() } else { Some(tcx.item_type(def_id)) }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 665d60281d1a9..62aa6522a7bdc 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -44,6 +44,7 @@ use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; use arena::{TypedArena, DroplessArena}; +use rustc_data_structures::indexed_vec::IndexVec; use std::borrow::Borrow; use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; @@ -220,7 +221,7 @@ pub struct TypeckTables<'tcx> { /// Records the type of each closure. pub closure_tys: NodeMap>, - /// Records the type of each closure. + /// Records the kind of each closure. pub closure_kinds: NodeMap, /// For each fn, records the "liberated" types of its arguments @@ -389,6 +390,8 @@ pub struct GlobalCtxt<'tcx> { global_arenas: &'tcx GlobalArenas<'tcx>, global_interners: CtxtInterners<'tcx>, + pub sess: &'tcx Session, + pub specializes_cache: RefCell, pub dep_graph: DepGraph, @@ -396,8 +399,6 @@ pub struct GlobalCtxt<'tcx> { /// Common types, pre-interned for your convenience. pub types: CommonTypes<'tcx>, - pub sess: &'tcx Session, - /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: TraitMap, @@ -659,6 +660,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// value (types, substs, etc.) can only be used while `ty::tls` has a valid /// reference to the context, to allow formatting values that need it. pub fn create_and_enter(s: &'tcx Session, + local_providers: ty::maps::Providers<'tcx>, + extern_providers: ty::maps::Providers<'tcx>, arenas: &'tcx GlobalArenas<'tcx>, arena: &'tcx DroplessArena, resolutions: ty::Resolutions, @@ -676,7 +679,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let common_types = CommonTypes::new(&interners); let dep_graph = hir.dep_graph.clone(); let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone()); + let max_cnum = s.cstore.crates().iter().map(|c| c.as_usize()).max().unwrap_or(0); + let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); + providers[LOCAL_CRATE] = local_providers; tls::enter_global(GlobalCtxt { + sess: s, specializes_cache: RefCell::new(traits::SpecializesCache::new()), global_arenas: arenas, global_interners: interners, @@ -686,11 +693,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { region_maps: region_maps, free_region_maps: RefCell::new(FxHashMap()), variance_computed: Cell::new(false), - sess: s, trait_map: resolutions.trait_map, fulfilled_predicates: RefCell::new(fulfilled_predicates), hir: hir, - maps: maps::Maps::new(dep_graph), + maps: maps::Maps::new(dep_graph, providers), freevars: RefCell::new(resolutions.freevars), maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, rcache: RefCell::new(FxHashMap()), diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index c31895b3e9df7..7bf1ba155b535 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -201,7 +201,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } else { // for local crates, check whether type info is // available; typeck might not have completed yet - self.maps.impl_trait_refs.borrow().contains_key(&impl_def_id) + self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id) }; if !use_types { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 3e37bd50f942c..4a91cdd24fcaa 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -9,49 +9,102 @@ // except according to those terms. use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; -use hir::def_id::DefId; +use hir::def_id::{CrateNum, DefId}; use middle::const_val::ConstVal; -use ty::{self, Ty}; +use mir; +use ty::{self, Ty, TyCtxt}; +use util::common::MemoizationMap; use util::nodemap::DefIdSet; +use rustc_data_structures::indexed_vec::IndexVec; use std::cell::RefCell; -use std::marker::PhantomData; use std::rc::Rc; use syntax::attr; +trait Key { + fn map_crate(&self) -> CrateNum; +} + +impl Key for DefId { + fn map_crate(&self) -> CrateNum { + self.krate + } +} + macro_rules! define_maps { - ($($(#[$attr:meta])* pub $field:ident: $node_name:ident($key:ty) -> $value:ty),*) => { - pub struct Maps<'tcx> { - $($(#[$attr])* pub $field: RefCell>>),* + (<$tcx:tt> + $($(#[$attr:meta])* + pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => { + pub struct Maps<$tcx> { + providers: IndexVec>, + $($(#[$attr])* pub $name: RefCell>>),* } - impl<'tcx> Maps<'tcx> { - pub fn new(dep_graph: DepGraph) -> Self { + impl<$tcx> Maps<$tcx> { + pub fn new(dep_graph: DepGraph, + providers: IndexVec>) + -> Self { Maps { - $($field: RefCell::new(DepTrackingMap::new(dep_graph.clone()))),* + providers, + $($name: RefCell::new(DepTrackingMap::new(dep_graph.clone()))),* } } } - $(#[allow(bad_style)] - pub struct $field<'tcx> { - data: PhantomData<&'tcx ()> + pub mod queries { + use std::marker::PhantomData; + + $(#[allow(bad_style)] + pub struct $name<$tcx> { + data: PhantomData<&$tcx ()> + })* } - impl<'tcx> DepTrackingMapConfig for $field<'tcx> { - type Key = $key; - type Value = $value; - fn to_dep_node(key: &$key) -> DepNode { DepNode::$node_name(*key) } + $(impl<$tcx> DepTrackingMapConfig for queries::$name<$tcx> { + type Key = $K; + type Value = $V; + fn to_dep_node(key: &$K) -> DepNode { DepNode::$node(*key) } })* + + pub struct Providers<$tcx> { + $(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $V),* + } + + impl<$tcx> Copy for Providers<$tcx> {} + impl<$tcx> Clone for Providers<$tcx> { + fn clone(&self) -> Self { *self } + } + + impl<$tcx> Default for Providers<$tcx> { + fn default() -> Self { + $(fn $name<'a, $tcx>(_: TyCtxt<'a, $tcx, $tcx>, key: $K) -> $V { + bug!("tcx.maps.{}({:?}) unsupported by its crate", + stringify!($name), key); + })* + Providers { $($name),* } + } + } + + impl<$tcx> Maps<$tcx> { + $($(#[$attr])* + pub fn $name<'a, 'lcx>(&self, tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V { + self.$name.memoize(key, || { + (self.providers[key.map_crate()].$name)(tcx.global_tcx(), key) + }) + })* + } } } -define_maps! { - /// Maps from a trait item to the trait item "descriptor" - pub associated_items: AssociatedItems(DefId) -> ty::AssociatedItem, - +// Each of these maps also corresponds to a method on a +// `Provider` trait for requesting a value of that type, +// and a method on `Maps` itself for doing that in a +// a way that memoizes and does dep-graph tracking, +// wrapping around the actual chain of providers that +// the driver creates (using several `rustc_*` crates). +define_maps! { <'tcx> /// Records the type of every item. - pub types: ItemSignature(DefId) -> Ty<'tcx>, + pub ty: ItemSignature(DefId) -> Ty<'tcx>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its /// associated generics and predicates. @@ -66,18 +119,22 @@ define_maps! { /// additional acyclicity requirements). pub super_predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx>, - /// Maps from an impl/trait def-id to a list of the def-ids of its items - pub associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc>, - - pub impl_trait_refs: ItemSignature(DefId) -> Option>, - pub trait_defs: ItemSignature(DefId) -> &'tcx ty::TraitDef, - pub adt_defs: ItemSignature(DefId) -> &'tcx ty::AdtDef, + pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef, + pub adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef, pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>, /// Maps from def-id of a type or region parameter to its /// (inferred) variance. pub variances: ItemSignature(DefId) -> Rc>, + /// Maps from an impl/trait def-id to a list of the def-ids of its items + pub associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc>, + + /// Maps from a trait item to the trait item "descriptor" + pub associated_item: AssociatedItems(DefId) -> ty::AssociatedItem, + + pub impl_trait_ref: ItemSignature(DefId) -> Option>, + /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. @@ -93,18 +150,18 @@ define_maps! { /// /// Note that cross-crate MIR appears to be always borrowed /// (in the `RefCell` sense) to prevent accidental mutation. - pub mir: Mir(DefId) -> &'tcx RefCell<::mir::Mir<'tcx>>, + pub mir: Mir(DefId) -> &'tcx RefCell>, /// Records the type of each closure. The def ID is the ID of the /// expression defining the closure. - pub closure_kinds: ItemSignature(DefId) -> ty::ClosureKind, + pub closure_kind: ItemSignature(DefId) -> ty::ClosureKind, /// Records the type of each closure. The def ID is the ID of the /// expression defining the closure. - pub closure_types: ItemSignature(DefId) -> ty::ClosureTy<'tcx>, + pub closure_type: ItemSignature(DefId) -> ty::ClosureTy<'tcx>, /// Caches CoerceUnsized kinds for impls on custom types. - pub custom_coerce_unsized_kinds: ItemSignature(DefId) + pub custom_coerce_unsized_kind: ItemSignature(DefId) -> ty::adjustment::CustomCoerceUnsized, pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7e0a35916d0bc..dd3ed2d9c2cd8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1908,28 +1908,6 @@ impl LvaluePreference { } } -/// Helper for looking things up in the various maps that are populated during -/// typeck::collect (e.g., `tcx.associated_items`, `tcx.types`, etc). All of -/// these share the pattern that if the id is local, it should have been loaded -/// into the map by the `typeck::collect` phase. If the def-id is external, -/// then we have to go consult the crate loading code (and cache the result for -/// the future). -fn lookup_locally_or_in_crate_store(descr: &str, - def_id: DefId, - map: &M, - load_external: F) - -> M::Value where - M: MemoizationMap, - F: FnOnce() -> M::Value, -{ - map.memoize(def_id, || { - if def_id.is_local() { - bug!("No def'n found for {:?} in tcx.{}", def_id, descr); - } - load_external() - }) -} - impl BorrowKind { pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { match m { @@ -2095,31 +2073,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized { - self.maps.custom_coerce_unsized_kinds.memoize(did, || { - let (kind, src) = if did.krate != LOCAL_CRATE { - (self.sess.cstore.custom_coerce_unsized_kind(did), "external") - } else { - (None, "local") - }; - - match kind { - Some(kind) => kind, - None => { - bug!("custom_coerce_unsized_kind: \ - {} impl `{}` is missing its kind", - src, self.item_path_str(did)); - } - } - }) + self.maps.custom_coerce_unsized_kind(self, did) } pub fn associated_item(self, def_id: DefId) -> AssociatedItem { - self.maps.associated_items.memoize(def_id, || { - if !def_id.is_local() { - return self.sess.cstore.associated_item(def_id) - .expect("missing AssociatedItem in metadata"); - } + if !def_id.is_local() { + return self.maps.associated_item(self, def_id); + } + self.maps.associated_item.memoize(def_id, || { // When the user asks for a given associated item, we // always go ahead and convert all the associated items in // the container. Note that we are also careful only to @@ -2141,7 +2103,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.associated_item_from_impl_item_ref(parent_def_id, impl_trait_ref.is_some(), impl_item_ref); - self.maps.associated_items.borrow_mut() + self.maps.associated_item.borrow_mut() .insert(assoc_item.def_id, assoc_item); } } @@ -2150,7 +2112,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { for trait_item_ref in trait_item_refs { let assoc_item = self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref); - self.maps.associated_items.borrow_mut() + self.maps.associated_item.borrow_mut() .insert(assoc_item.def_id, assoc_item); } } @@ -2162,7 +2124,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // memoize wants us to return something, so return // the one we generated for this def-id - *self.maps.associated_items.borrow().get(&def_id).unwrap() + *self.maps.associated_item.borrow().get(&def_id).unwrap() }) } @@ -2220,11 +2182,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn associated_item_def_ids(self, def_id: DefId) -> Rc> { - self.maps.associated_item_def_ids.memoize(def_id, || { - if !def_id.is_local() { - return Rc::new(self.sess.cstore.associated_item_def_ids(def_id)); - } + if !def_id.is_local() { + return self.maps.associated_item_def_ids(self, def_id); + } + self.maps.associated_item_def_ids.memoize(def_id, || { let id = self.hir.as_local_node_id(def_id).unwrap(); let item = self.hir.expect_item(id); let vec: Vec<_> = match item.node { @@ -2256,9 +2218,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the trait-ref corresponding to a given impl, or None if it is /// an inherent impl. pub fn impl_trait_ref(self, id: DefId) -> Option> { - lookup_locally_or_in_crate_store( - "impl_trait_refs", id, &self.maps.impl_trait_refs, - || self.sess.cstore.impl_trait_ref(self.global_tcx(), id)) + self.maps.impl_trait_ref(self, id) } // Returns `ty::VariantDef` if `def` refers to a struct, @@ -2337,58 +2297,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If the given item is in an external crate, looks up its type and adds it to // the type cache. Returns the type parameters and type. pub fn item_type(self, did: DefId) -> Ty<'gcx> { - lookup_locally_or_in_crate_store( - "item_types", did, &self.maps.types, - || self.sess.cstore.item_type(self.global_tcx(), did)) + self.maps.ty(self, did) } /// Given the did of a trait, returns its canonical trait ref. pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef { - lookup_locally_or_in_crate_store( - "trait_defs", did, &self.maps.trait_defs, - || self.alloc_trait_def(self.sess.cstore.trait_def(self.global_tcx(), did)) - ) + self.maps.trait_def(self, did) } /// Given the did of an ADT, return a reference to its definition. pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef { - lookup_locally_or_in_crate_store( - "adt_defs", did, &self.maps.adt_defs, - || self.sess.cstore.adt_def(self.global_tcx(), did)) + self.maps.adt_def(self, did) } /// Given the did of an item, returns its generics. pub fn item_generics(self, did: DefId) -> &'gcx Generics { - lookup_locally_or_in_crate_store( - "generics", did, &self.maps.generics, - || self.alloc_generics(self.sess.cstore.item_generics(did))) + self.maps.generics(self, did) } /// Given the did of an item, returns its full set of predicates. pub fn item_predicates(self, did: DefId) -> GenericPredicates<'gcx> { - lookup_locally_or_in_crate_store( - "predicates", did, &self.maps.predicates, - || self.sess.cstore.item_predicates(self.global_tcx(), did)) + self.maps.predicates(self, did) } /// Given the did of a trait, returns its superpredicates. pub fn item_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> { - lookup_locally_or_in_crate_store( - "super_predicates", did, &self.maps.super_predicates, - || self.sess.cstore.item_super_predicates(self.global_tcx(), did)) + self.maps.super_predicates(self, did) } /// Given the did of an item, returns its MIR, borrowed immutably. pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> { - lookup_locally_or_in_crate_store("mir_map", did, &self.maps.mir, || { - let mir = self.sess.cstore.get_item_mir(self.global_tcx(), did); - let mir = self.alloc_mir(mir); - - // Perma-borrow MIR from extern crates to prevent mutation. - mem::forget(mir.borrow()); - - mir - }).borrow() + self.maps.mir(self, did).borrow() } /// If `type_needs_drop` returns true, then `ty` is definitely @@ -2451,9 +2390,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn item_variances(self, item_id: DefId) -> Rc> { - lookup_locally_or_in_crate_store( - "item_variance_map", item_id, &self.maps.variances, - || Rc::new(self.sess.cstore.item_variances(item_id))) + self.maps.variances(self, item_id) } pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool { @@ -2528,16 +2465,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind { - // If this is a local def-id, it should be inserted into the - // tables by typeck; else, it will be retreived from - // the external crate metadata. - if let Some(&kind) = self.maps.closure_kinds.borrow().get(&def_id) { - return kind; - } - - let kind = self.sess.cstore.closure_kind(def_id); - self.maps.closure_kinds.borrow_mut().insert(def_id, kind); - kind + self.maps.closure_kind(self, def_id) } pub fn closure_type(self, @@ -2545,16 +2473,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { substs: ClosureSubsts<'tcx>) -> ty::ClosureTy<'tcx> { - // If this is a local def-id, it should be inserted into the - // tables by typeck; else, it will be retreived from - // the external crate metadata. - if let Some(ty) = self.maps.closure_types.borrow().get(&def_id) { + if let Some(ty) = self.maps.closure_type.borrow().get(&def_id) { return ty.subst(self, substs.substs); } - let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id); - self.maps.closure_types.borrow_mut().insert(def_id, ty.clone()); - ty.subst(self, substs.substs) + self.maps.closure_type(self, def_id).subst(self, substs.substs) } /// Given the def_id of an impl, return the def_id of the trait it implements. @@ -2566,15 +2489,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// If the given def ID describes a method belonging to an impl, return the /// ID of the impl that the method belongs to. Otherwise, return `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { - if def_id.krate != LOCAL_CRATE { - return self.sess.cstore.associated_item(def_id).and_then(|item| { - match item.container { - TraitContainer(_) => None, - ImplContainer(def_id) => Some(def_id), - } - }); - } - match self.maps.associated_items.borrow().get(&def_id).cloned() { + let item = if def_id.krate != LOCAL_CRATE { + if let Some(Def::Method(_)) = self.sess.cstore.describe_def(def_id) { + Some(self.associated_item(def_id)) + } else { + None + } + } else { + self.maps.associated_item.borrow().get(&def_id).cloned() + }; + + match item { Some(trait_item) => { match trait_item.container { TraitContainer(_) => None, @@ -2592,7 +2517,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if def_id.krate != LOCAL_CRATE { return self.sess.cstore.trait_of_item(def_id); } - match self.maps.associated_items.borrow().get(&def_id) { + match self.maps.associated_item.borrow().get(&def_id) { Some(associated_item) => { match associated_item.container { TraitContainer(def_id) => Some(def_id), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fa53760eca466..3981c8a7c4f52 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -770,7 +770,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { TyAdt(def, substs) => { ty::tls::with(|tcx| { if def.did.is_local() && - !tcx.maps.types.borrow().contains_key(&def.did) { + !tcx.maps.ty.borrow().contains_key(&def.did) { write!(f, "{}<..>", tcx.item_path_str(def.did)) } else { parameterized(f, substs, def.did, &[]) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 13ece31f4ce13..967705c748161 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -123,7 +123,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { (&body.value, Some(tcx.item_tables(def_id)), - Some(tcx.sess.cstore.item_type(tcx, def_id))) + Some(tcx.item_type(def_id))) }); match tcx.sess.cstore.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index de789d5686fcf..6dbdf55f1ca37 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -28,7 +28,7 @@ use rustc_incremental::{self, IncrementalHashesMap}; use rustc_incremental::ich::Fingerprint; use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::creader::CrateLoader; -use rustc_metadata::cstore::CStore; +use rustc_metadata::cstore::{self, CStore}; use rustc_trans::back::{link, write}; use rustc_trans as trans; use rustc_typeck as typeck; @@ -872,7 +872,14 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let index = stability::Index::new(&hir_map); + let local_providers = ty::maps::Providers::default(); + let mut extern_providers = ty::maps::Providers::default(); + + cstore::provide(&mut extern_providers); + TyCtxt::create_and_enter(sess, + local_providers, + extern_providers, arenas, arena, resolutions, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 5481de1811d78..2aa1b9981b3cd 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -139,6 +139,8 @@ fn test_env(source_string: &str, let region_map = region::resolve_crate(&sess, &hir_map); let index = stability::Index::new(&hir_map); TyCtxt::create_and_enter(&sess, + ty::maps::Providers::default(), + ty::maps::Providers::default(), &arenas, &arena, resolutions, diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 5fcefe0d53997..353b86820c405 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -29,7 +29,7 @@ pub enum MethodLateContext { pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext { let def_id = cx.tcx.hir.local_def_id(id); - match cx.tcx.maps.associated_items.borrow().get(&def_id) { + match cx.tcx.maps.associated_item.borrow().get(&def_id) { None => span_bug!(span, "missing method descriptor?!"), Some(item) => { match item.container { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 4709ca6101c79..bb30245df5f56 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -35,6 +35,8 @@ pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePrefere pub use rustc::middle::cstore::NativeLibraryKind::*; pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource}; +pub use cstore_impl::provide; + // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external // crate may refer to types in other external crates, and each has their diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index bd184c5c5e69f..770591bc17ad7 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -13,20 +13,25 @@ use encoder; use locator; use schema; +use rustc::dep_graph::DepTrackingMapConfig; use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate}; use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro}; use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; use rustc::session::Session; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, TyCtxt}; +use rustc::ty::maps::Providers; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::dep_graph::DepNode; use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData}; -use rustc::mir::Mir; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; +use std::any::Any; +use std::mem; +use std::rc::Rc; + use syntax::ast; use syntax::attr; use syntax::parse::filemap_to_tts; @@ -38,7 +43,73 @@ use rustc::hir; use std::collections::BTreeMap; -impl<'tcx> CrateStore<'tcx> for cstore::CStore { +macro_rules! provide { + (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident $($name:ident => $compute:block)*) => { + pub fn provide<$lt>(providers: &mut Providers<$lt>) { + $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) + -> as + DepTrackingMapConfig>::Value { + assert!(!$def_id.is_local()); + + $tcx.dep_graph.read(DepNode::MetaData($def_id)); + + let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($def_id.krate); + let $cdata = $cdata.downcast_ref::() + .expect("CrateStore crated ata is not a CrateMetadata"); + $compute + })* + + *providers = Providers { + $($name,)* + ..*providers + }; + } + } +} + +provide! { <'tcx> tcx, def_id, cdata + ty => { cdata.get_type(def_id.index, tcx) } + generics => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } + predicates => { cdata.get_predicates(def_id.index, tcx) } + super_predicates => { cdata.get_super_predicates(def_id.index, tcx) } + trait_def => { + tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx)) + } + adt_def => { cdata.get_adt_def(def_id.index, tcx) } + variances => { Rc::new(cdata.get_item_variances(def_id.index)) } + associated_item_def_ids => { + let mut result = vec![]; + cdata.each_child_of_item(def_id.index, |child| result.push(child.def.def_id())); + Rc::new(result) + } + associated_item => { cdata.get_associated_item(def_id.index) } + impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } + custom_coerce_unsized_kind => { + cdata.get_custom_coerce_unsized_kind(def_id.index).unwrap_or_else(|| { + bug!("custom_coerce_unsized_kind: `{:?}` is missing its kind", def_id); + }) + } + mir => { + let mir = cdata.maybe_get_item_mir(tcx, def_id.index).unwrap_or_else(|| { + bug!("get_item_mir: missing MIR for `{:?}`", def_id) + }); + + let mir = tcx.alloc_mir(mir); + + // Perma-borrow MIR from extern crates to prevent mutation. + mem::forget(mir.borrow()); + + mir + } + closure_kind => { cdata.closure_kind(def_id.index) } + closure_type => { cdata.closure_ty(def_id.index, tcx) } +} + +impl CrateStore for cstore::CStore { + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc { + self.get_crate_data(krate) + } + fn describe_def(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_def(def.index) @@ -64,46 +135,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).get_visibility(def.index) } - fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind - { - assert!(!def_id.is_local()); - self.dep_graph.read(DepNode::MetaData(def_id)); - self.get_crate_data(def_id.krate).closure_kind(def_id.index) - } - - fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> { - assert!(!def_id.is_local()); - self.dep_graph.read(DepNode::MetaData(def_id)); - self.get_crate_data(def_id.krate).closure_ty(def_id.index, tcx) - } - - fn item_variances(&self, def: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_item_variances(def.index) - } - - fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Ty<'tcx> - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_type(def.index, tcx) - } - - fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::GenericPredicates<'tcx> - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_predicates(def.index, tcx) - } - - fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::GenericPredicates<'tcx> - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_super_predicates(def.index, tcx) - } - - fn item_generics(&self, def: DefId) -> ty::Generics { + fn item_generics_cloned(&self, def: DefId) -> ty::Generics { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_generics(def.index) } @@ -114,18 +146,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def_id.krate).get_item_attrs(def_id.index) } - fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_trait_def(def.index, tcx) - } - - fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_adt_def(def.index, tcx) - } - fn fn_arg_names(&self, did: DefId) -> Vec { // FIXME(#38501) We've skipped a `read` on the `HirBody` of @@ -154,34 +174,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn associated_item_def_ids(&self, def_id: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(def_id)); - let mut result = vec![]; - self.get_crate_data(def_id.krate) - .each_child_of_item(def_id.index, |child| result.push(child.def.def_id())); - result - } - fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_impl_polarity(def.index) } - fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option> - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_impl_trait(def.index, tcx) - } - - fn custom_coerce_unsized_kind(&self, def: DefId) - -> Option - { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_custom_coerce_unsized_kind(def.index) - } - fn impl_parent(&self, impl_def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(impl_def)); self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index) @@ -192,7 +190,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index) } - fn associated_item(&self, def: DefId) -> Option + fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).get_associated_item(def.index) @@ -425,10 +423,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { }) } - fn maybe_get_item_body<'a>(&'tcx self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Option<&'tcx hir::Body> + fn maybe_get_item_body<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Option<&'tcx hir::Body> { if let Some(cached) = tcx.hir.get_inlined_body(def_id) { return Some(cached); @@ -450,13 +448,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).const_is_rvalue_promotable_to_static(def.index) } - fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx> { - self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).maybe_get_item_mir(tcx, def.index).unwrap_or_else(|| { - bug!("get_item_mir: missing MIR for {}", tcx.item_path_str(def)) - }) - } - fn is_item_mir_available(&self, def: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).is_item_mir_available(def.index) @@ -504,10 +495,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.do_extern_mod_stmt_cnum(emod_id) } - fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - reexports: &def::ExportMap, - link_meta: &LinkMeta, - reachable: &NodeSet) -> Vec + fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + reexports: &def::ExportMap, + link_meta: &LinkMeta, + reachable: &NodeSet) -> Vec { encoder::encode_metadata(tcx, self, reexports, link_meta, reachable) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index aa18fbe2ba8cd..3f8873ddc2742 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -584,7 +584,7 @@ impl<'a, 'tcx> CrateMetadata { let adt = tcx.alloc_adt_def(did, kind, variants, repr); if let Some(ctor_index) = ctor_index { // Make adt definition available through constructor id as well. - tcx.maps.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt); + tcx.maps.adt_def.borrow_mut().insert(self.local_def_id(ctor_index), adt); } adt @@ -822,54 +822,35 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_associated_item(&self, id: DefIndex) -> Option { + pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem { let item = self.entry(id); - let parent_and_name = || { - let def_key = self.def_key(id); - (self.local_def_id(def_key.parent.unwrap()), - def_key.disambiguated_data.data.get_opt_name().unwrap()) - }; + let def_key = self.def_key(id); + let parent = self.local_def_id(def_key.parent.unwrap()); + let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); - Some(match item.kind { + let (kind, container, has_self) = match item.kind { EntryKind::AssociatedConst(container) => { - let (parent, name) = parent_and_name(); - ty::AssociatedItem { - name: name, - kind: ty::AssociatedKind::Const, - vis: item.visibility.decode(self), - defaultness: container.defaultness(), - def_id: self.local_def_id(id), - container: container.with_def_id(parent), - method_has_self_argument: false - } + (ty::AssociatedKind::Const, container, false) } EntryKind::Method(data) => { - let (parent, name) = parent_and_name(); let data = data.decode(self); - ty::AssociatedItem { - name: name, - kind: ty::AssociatedKind::Method, - vis: item.visibility.decode(self), - defaultness: data.container.defaultness(), - def_id: self.local_def_id(id), - container: data.container.with_def_id(parent), - method_has_self_argument: data.has_self - } + (ty::AssociatedKind::Method, data.container, data.has_self) } EntryKind::AssociatedType(container) => { - let (parent, name) = parent_and_name(); - ty::AssociatedItem { - name: name, - kind: ty::AssociatedKind::Type, - vis: item.visibility.decode(self), - defaultness: container.defaultness(), - def_id: self.local_def_id(id), - container: container.with_def_id(parent), - method_has_self_argument: false - } + (ty::AssociatedKind::Type, container, false) } - _ => return None, - }) + _ => bug!() + }; + + ty::AssociatedItem { + name: name, + kind: kind, + vis: item.visibility.decode(self), + defaultness: container.defaultness(), + def_id: self.local_def_id(id), + container: container.with_def_id(parent), + method_has_self_argument: has_self + } } pub fn get_item_variances(&self, id: DefIndex) -> Vec { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e6110172fc41f..e101dc8cb5892 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -711,7 +711,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ImplData { polarity: polarity, parent_impl: parent, - coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kinds + coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kind .borrow() .get(&def_id) .cloned(), @@ -1096,7 +1096,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.maps.closure_types.borrow()[&def_id]), + ty: self.lazy(&tcx.maps.closure_type.borrow()[&def_id]), }; Entry { diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 2fbdb8c0de676..0ce886ce9e9df 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -20,6 +20,7 @@ #![feature(box_patterns)] #![feature(conservative_impl_trait)] #![feature(core_intrinsics)] +#![cfg_attr(stage0, feature(field_init_shorthand))] #![feature(i128_type)] #![feature(proc_macro_internals)] #![feature(quote)] diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index ec02e9235beaf..89cff39c59e31 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -462,8 +462,8 @@ impl<'a> Resolver<'a> { self.define(module, ident, ns, (child.def, ty::Visibility::Public, DUMMY_SP, Mark::root())); - let has_self = self.session.cstore.associated_item(child.def.def_id()) - .map_or(false, |item| item.method_has_self_argument); + let has_self = self.session.cstore.associated_item_cloned(child.def.def_id()) + .method_has_self_argument; self.trait_item_map.insert((def_id, child.name, ns), (child.def, has_self)); } module.populated.set(true); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index c2f64b1bd7906..7b14684267173 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -208,9 +208,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // If we are also inferred the closure kind here, update the // main table and process any deferred resolutions. - let closure_def_id = self.fcx.tcx.hir.local_def_id(id); if let Some(&kind) = self.temp_closure_kinds.get(&id) { self.fcx.tables.borrow_mut().closure_kinds.insert(id, kind); + let closure_def_id = self.fcx.tcx.hir.local_def_id(id); debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); let mut deferred_call_resolutions = diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b3a4b83b6832c..650f32eb6b216 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -290,12 +290,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); let def_id = self.tcx().hir.local_def_id(id); - self.tcx().maps.closure_types.borrow_mut().insert(def_id, closure_ty); + self.tcx().maps.closure_type.borrow_mut().insert(def_id, closure_ty); } for (&id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { let def_id = self.tcx().hir.local_def_id(id); - self.tcx().maps.closure_kinds.borrow_mut().insert(def_id, closure_kind); + self.tcx().maps.closure_kind.borrow_mut().insert(def_id, closure_kind); } } @@ -361,7 +361,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } }); - gcx.maps.types.borrow_mut().insert(def_id, outside_ty); + gcx.maps.ty.borrow_mut().insert(def_id, outside_ty); } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index e15386b87ad97..bfe8abb201cae 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -341,7 +341,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id); if let Some(kind) = kind { - tcx.maps.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind); + tcx.maps.custom_coerce_unsized_kind.borrow_mut().insert(impl_did, kind); } }); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 1301f33d30b08..4aa0650e57f71 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -39,7 +39,7 @@ mod unsafety; struct CoherenceCollect<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - inherent_impls: RefMut<'a, DepTrackingMap>>, + inherent_impls: RefMut<'a, DepTrackingMap>>, } impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3851cd2bb442a..90d12b26c6a62 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -606,7 +606,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, { generics_of_def_id(ccx, ty_f.did); let tt = ccx.icx(ty_f.did).to_ty(&field.ty); - ccx.tcx.maps.types.borrow_mut().insert(ty_f.did, tt); + ccx.tcx.maps.ty.borrow_mut().insert(ty_f.did, tt); ccx.tcx.maps.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { parent: Some(ccx.tcx.hir.get_parent_did(field.id)), predicates: vec![] @@ -619,7 +619,7 @@ fn convert_method(ccx: &CrateCtxt, id: ast::NodeId, sig: &hir::MethodSig) { let fty = AstConv::ty_of_fn(&ccx.icx(def_id), sig.unsafety, sig.abi, &sig.decl); let substs = mk_item_substs(ccx, def_id); let fty = ccx.tcx.mk_fn_def(def_id, substs, fty); - ccx.tcx.maps.types.borrow_mut().insert(def_id, fty); + ccx.tcx.maps.ty.borrow_mut().insert(def_id, fty); ty_generic_predicates(ccx, def_id, &sig.generics); } @@ -635,7 +635,7 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; let def_id = ccx.tcx.hir.local_def_id(id); ccx.tcx.maps.predicates.borrow_mut().insert(def_id, predicates); - ccx.tcx.maps.types.borrow_mut().insert(def_id, ty); + ccx.tcx.maps.ty.borrow_mut().insert(def_id, ty); } fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -651,7 +651,7 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx.tcx.maps.predicates.borrow_mut().insert(def_id, predicates); if let Some(ty) = ty { - ccx.tcx.maps.types.borrow_mut().insert(def_id, ty); + ccx.tcx.maps.ty.borrow_mut().insert(def_id, ty); } } @@ -725,7 +725,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.record_trait_has_default_impl(trait_ref.def_id); - tcx.maps.impl_trait_refs.borrow_mut().insert(ccx.tcx.hir.local_def_id(it.id), + tcx.maps.impl_trait_ref.borrow_mut().insert(ccx.tcx.hir.local_def_id(it.id), Some(trait_ref)); } hir::ItemImpl(.., ref opt_trait_ref, _, _) => { @@ -735,7 +735,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) }); - tcx.maps.impl_trait_refs.borrow_mut().insert(def_id, trait_ref); + tcx.maps.impl_trait_ref.borrow_mut().insert(def_id, trait_ref); predicates_of_item(ccx, it); }, @@ -864,7 +864,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, })) } }; - tcx.maps.types.borrow_mut().insert(def_id, ctor_ty); + tcx.maps.ty.borrow_mut().insert(def_id, ctor_ty); tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { parent: Some(ccx.tcx.hir.get_parent_did(ctor_id)), predicates: vec![] @@ -966,10 +966,10 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ReprOptions::new(&ccx.tcx, did)); if let Some(ctor_id) = ctor_id { // Make adt definition available through constructor id as well. - ccx.tcx.maps.adt_defs.borrow_mut().insert(ctor_id, adt); + ccx.tcx.maps.adt_def.borrow_mut().insert(ctor_id, adt); } - ccx.tcx.maps.adt_defs.borrow_mut().insert(did, adt); + ccx.tcx.maps.adt_def.borrow_mut().insert(did, adt); adt } @@ -983,7 +983,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty::VariantDiscr::Relative(0), def)]; let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did)); - ccx.tcx.maps.adt_defs.borrow_mut().insert(did, adt); + ccx.tcx.maps.adt_def.borrow_mut().insert(did, adt); adt } @@ -1061,7 +1061,7 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let did = tcx.hir.local_def_id(it.id); let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did)); - tcx.maps.adt_defs.borrow_mut().insert(did, adt); + tcx.maps.adt_def.borrow_mut().insert(did, adt); adt } @@ -1150,7 +1150,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'t let tcx = ccx.tcx; let def_id = tcx.hir.local_def_id(it.id); - tcx.maps.trait_defs.memoize(def_id, || { + tcx.maps.trait_def.memoize(def_id, || { let unsafety = match it.node { hir::ItemTrait(unsafety, ..) => unsafety, _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"), @@ -1380,7 +1380,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { return ccx.tcx.item_type(def_id); }; - ccx.tcx.maps.types.memoize(def_id, || { + ccx.tcx.maps.ty.memoize(def_id, || { use rustc::hir::map::*; use rustc::hir::*; @@ -1389,7 +1389,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let icx = ccx.icx(def_id); - let ty = match ccx.tcx.hir.get(node_id) { + match ccx.tcx.hir.get(node_id) { NodeItem(item) => { match item.node { ItemStatic(ref t, ..) | ItemConst(ref t, _) | @@ -1455,9 +1455,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, x => { bug!("unexpected sort of node in type_of_def_id(): {:?}", x); } - }; - - ty + } }) } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index cee292f99153e..852c98eb2fd52 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -24,7 +24,7 @@ use clean::{AttributesExt, NestedAttributesExt}; /// specific rustdoc annotations into account (i.e. `doc(hidden)`) pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> { cx: &'a ::core::DocContext<'b, 'tcx>, - cstore: &'a CrateStore<'tcx>, + cstore: &'a CrateStore, // Accessibility levels for reachable nodes access_levels: RefMut<'a, AccessLevels>, // Previous accessibility level, None means unreachable From 374ea14412fbb35ca344b7d7cbe67405d63e0e42 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 8 Feb 2017 11:16:14 +0200 Subject: [PATCH 06/17] rustc_mir: expose MIR building through ty::maps::Provider. --- src/librustc_driver/driver.rs | 5 +- src/librustc_mir/mir_map.rs | 158 ++++++++++++++++++++++------------ 2 files changed, 104 insertions(+), 59 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 6dbdf55f1ca37..c1cfc0234e141 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -872,9 +872,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let index = stability::Index::new(&hir_map); - let local_providers = ty::maps::Providers::default(); - let mut extern_providers = ty::maps::Providers::default(); + let mut local_providers = ty::maps::Providers::default(); + mir::mir_map::provide(&mut local_providers); + let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); TyCtxt::create_and_enter(sess, diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 913b0d5fb8ae8..dedc55404496a 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -17,6 +17,7 @@ //! - `#[rustc_mir(pretty="file.mir")]` use build; +use rustc::hir::def_id::DefId; use rustc::dep_graph::DepNode; use rustc::mir::Mir; use rustc::mir::transform::MirSource; @@ -24,9 +25,9 @@ use rustc::mir::visit::MutVisitor; use pretty; use hair::cx::Cx; -use rustc::infer::InferCtxt; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::maps::Providers; use rustc::ty::subst::Substs; use rustc::hir; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; @@ -34,6 +35,7 @@ use syntax::abi::Abi; use syntax::ast; use syntax_pos::Span; +use std::cell::RefCell; use std::mem; pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -42,6 +44,103 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { }.as_deep_visitor()); } +pub fn provide(providers: &mut Providers) { + providers.mir = build_mir; +} + +fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> &'tcx RefCell> { + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let unsupported = || { + span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id); + }; + + // Figure out what primary body this item has. + let body_id = match tcx.hir.get(id) { + hir::map::NodeItem(item) => { + match item.node { + hir::ItemConst(_, body) | + hir::ItemStatic(_, _, body) | + hir::ItemFn(.., body) => body, + _ => unsupported() + } + } + hir::map::NodeTraitItem(item) => { + match item.node { + hir::TraitItemKind::Const(_, Some(body)) | + hir::TraitItemKind::Method(_, + hir::TraitMethod::Provided(body)) => body, + _ => unsupported() + } + } + hir::map::NodeImplItem(item) => { + match item.node { + hir::ImplItemKind::Const(_, body) | + hir::ImplItemKind::Method(_, body) => body, + _ => unsupported() + } + } + hir::map::NodeExpr(expr) => { + // FIXME(eddyb) Closures should have separate + // function definition IDs and expression IDs. + // Type-checking should not let closures get + // this far in a constant position. + // Assume that everything other than closures + // is a constant "initializer" expression. + match expr.node { + hir::ExprClosure(_, _, body, _) => body, + _ => hir::BodyId { node_id: expr.id } + } + } + _ => unsupported() + }; + + let src = MirSource::from_node(tcx, id); + tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + let cx = Cx::new(&infcx, src); + let mut mir = if let MirSource::Fn(id) = src { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + let fn_sig = cx.tables().liberated_fn_sigs[&id].clone(); + + let ty = tcx.item_type(tcx.hir.local_def_id(id)); + let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty { + (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None))) + } else { + (ty.fn_abi(), None) + }; + + let body = tcx.hir.body(body_id); + let explicit_arguments = + body.arguments + .iter() + .enumerate() + .map(|(index, arg)| { + (fn_sig.inputs()[index], Some(&*arg.pat)) + }); + + let arguments = implicit_argument.into_iter().chain(explicit_arguments); + build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body) + } else { + build::construct_const(cx, body_id) + }; + + // Convert the Mir to global types. + let mut globalizer = GlobalizeMir { + tcx: tcx, + span: mir.span + }; + globalizer.visit_mir(&mut mir); + let mir = unsafe { + mem::transmute::>(mir) + }; + + pretty::dump_mir(tcx, "mir_map", &0, src, &mir); + + tcx.alloc_mir(mir) + }) +} + /// A pass to lift all the types and substitutions in a Mir /// to the global tcx. Sadly, we don't have a "folder" that /// can change 'tcx so we have to transmute afterwards. @@ -79,68 +178,13 @@ struct BuildMir<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -fn build<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - body_id: hir::BodyId) - -> (Mir<'tcx>, MirSource) { - let tcx = infcx.tcx.global_tcx(); - - let item_id = tcx.hir.body_owner(body_id); - let src = MirSource::from_node(tcx, item_id); - let cx = Cx::new(infcx, src); - if let MirSource::Fn(id) = src { - // fetch the fully liberated fn signature (that is, all bound - // types/lifetimes replaced) - let fn_sig = cx.tables().liberated_fn_sigs[&id].clone(); - - let ty = tcx.item_type(tcx.hir.local_def_id(id)); - let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty { - (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None))) - } else { - (ty.fn_abi(), None) - }; - - let body = tcx.hir.body(body_id); - let explicit_arguments = - body.arguments - .iter() - .enumerate() - .map(|(index, arg)| { - (fn_sig.inputs()[index], Some(&*arg.pat)) - }); - - let arguments = implicit_argument.into_iter().chain(explicit_arguments); - (build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body), src) - } else { - (build::construct_const(cx, body_id), src) - } -} - impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } fn visit_nested_body(&mut self, body_id: hir::BodyId) { - self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { - let (mut mir, src) = build(&infcx, body_id); - - // Convert the Mir to global types. - let tcx = infcx.tcx.global_tcx(); - let mut globalizer = GlobalizeMir { - tcx: tcx, - span: mir.span - }; - globalizer.visit_mir(&mut mir); - let mir = unsafe { - mem::transmute::>(mir) - }; - - pretty::dump_mir(tcx, "mir_map", &0, src, &mir); - - let mir = tcx.alloc_mir(mir); - let def_id = tcx.hir.local_def_id(src.item_id()); - tcx.maps.mir.borrow_mut().insert(def_id, mir); - }); + self.tcx.item_mir(self.tcx.hir.body_owner_def_id(body_id)); let body = self.tcx.hir.body(body_id); self.visit_body(body); From 4649f7387ea334901c78dd48c1e1659ecf80cfcc Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 4 Oct 2016 02:19:40 +0300 Subject: [PATCH 07/17] rustc_typeck: lift CrateCtxt to TyCtxt. --- src/librustc/ty/context.rs | 17 + src/librustc/ty/maps.rs | 13 + src/librustc/ty/mod.rs | 9 +- src/librustc_driver/driver.rs | 18 +- src/librustc_driver/pretty.rs | 6 +- src/librustc_save_analysis/lib.rs | 6 +- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/callee.rs | 12 +- src/librustc_typeck/check/compare_method.rs | 37 +- src/librustc_typeck/check/dropck.rs | 21 +- src/librustc_typeck/check/intrinsic.rs | 130 +++-- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 36 +- src/librustc_typeck/check/mod.rs | 270 +++++----- src/librustc_typeck/check/regionck.rs | 19 +- src/librustc_typeck/check/wfcheck.rs | 85 ++- src/librustc_typeck/check/writeback.rs | 4 +- src/librustc_typeck/coherence/mod.rs | 15 +- src/librustc_typeck/collect.rs | 562 +++++++++----------- src/librustc_typeck/impl_wf_check.rs | 43 +- src/librustc_typeck/lib.rs | 86 +-- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/core.rs | 10 +- 24 files changed, 651 insertions(+), 757 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 62aa6522a7bdc..38af6c3d0da54 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -525,6 +525,20 @@ pub struct GlobalCtxt<'tcx> { stability_interner: RefCell>, layout_interner: RefCell>, + + /// 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>>, + + /// 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>>>, + + /// HIR Ty -> Ty lowering cache. + pub ast_ty_to_ty_cache: RefCell>>, } impl<'tcx> GlobalCtxt<'tcx> { @@ -720,6 +734,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { layout_depth: Cell::new(0), derive_macros: RefCell::new(NodeMap()), stability_interner: RefCell::new(FxHashSet()), + all_traits: RefCell::new(None), + deferred_obligations: RefCell::new(NodeMap()), + ast_ty_to_ty_cache: RefCell::new(NodeMap()), }, f) } } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 4a91cdd24fcaa..aeb7a207c447e 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -37,6 +37,7 @@ macro_rules! define_maps { pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => { pub struct Maps<$tcx> { providers: IndexVec>, + pub query_stack: RefCell>, $($(#[$attr])* pub $name: RefCell>>),* } @@ -46,11 +47,18 @@ macro_rules! define_maps { -> Self { Maps { providers, + query_stack: RefCell::new(vec![]), $($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 { use std::marker::PhantomData; @@ -119,6 +127,11 @@ define_maps! { <'tcx> /// additional acyclicity requirements). 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 adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef, pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dd3ed2d9c2cd8..97476489a8adb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -31,7 +31,7 @@ use ty::subst::{Subst, Substs}; use ty::util::IntTypeExt; use ty::walk::TypeWalker; use util::common::MemoizationMap; -use util::nodemap::{NodeSet, NodeMap, FxHashMap}; +use util::nodemap::{NodeSet, FxHashMap}; use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; @@ -104,13 +104,12 @@ mod sty; /// The complete set of all analyses described in this module. This is /// produced by the driver and fed to trans and later passes. #[derive(Clone)] -pub struct CrateAnalysis<'tcx> { +pub struct CrateAnalysis { pub export_map: ExportMap, pub access_levels: middle::privacy::AccessLevels, pub reachable: NodeSet, pub name: String, pub glob_map: Option, - pub hir_ty_to_ty: NodeMap>, } #[derive(Clone)] @@ -1383,7 +1382,7 @@ pub struct 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 attrs = tcx.lookup_repr_hints(did); for r in attrs.iter() { @@ -1400,7 +1399,7 @@ impl ReprOptions { } impl<'a, 'gcx, 'tcx> AdtDef { - fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + fn new(tcx: TyCtxt, did: DefId, kind: AdtKind, variants: Vec, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c1cfc0234e141..b80402a15f67d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -21,7 +21,7 @@ use rustc::middle::{self, dependency_format, stability, reachable}; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; 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_borrowck as borrowck; use rustc_incremental::{self, IncrementalHashesMap}; @@ -343,7 +343,7 @@ pub struct CompileState<'a, 'tcx: 'a> { pub hir_crate: Option<&'a hir::Crate>, pub hir_map: Option<&'a hir_map::Map<'tcx>>, pub resolutions: Option<&'a Resolutions>, - pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>, + pub analysis: Option<&'a ty::CrateAnalysis>, pub tcx: Option>, pub trans: Option<&'a trans::CrateTranslation>, } @@ -417,7 +417,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { arenas: &'tcx GlobalArenas<'tcx>, cstore: &'a CStore, hir_map: &'a hir_map::Map<'tcx>, - analysis: &'a ty::CrateAnalysis<'static>, + analysis: &'a ty::CrateAnalysis, resolutions: &'a Resolutions, krate: &'a ast::Crate, hir_crate: &'a hir::Crate, @@ -444,7 +444,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { out_file: &'a Option, krate: Option<&'a ast::Crate>, hir_crate: &'a hir::Crate, - analysis: &'a ty::CrateAnalysis<'tcx>, + analysis: &'a ty::CrateAnalysis, tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_name: &'a str) -> Self { @@ -534,7 +534,7 @@ fn count_nodes(krate: &ast::Crate) -> usize { pub struct ExpansionResult { pub expanded_crate: ast::Crate, pub defs: hir_map::Definitions, - pub analysis: ty::CrateAnalysis<'static>, + pub analysis: ty::CrateAnalysis, pub resolutions: Resolutions, pub hir_forest: hir_map::Forest, } @@ -797,7 +797,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, reachable: NodeSet(), name: crate_name.to_string(), glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, - hir_ty_to_ty: NodeMap(), }, resolutions: Resolutions { freevars: resolver.freevars, @@ -813,7 +812,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, /// structures carrying the results of the analysis. pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, hir_map: hir_map::Map<'tcx>, - mut analysis: ty::CrateAnalysis<'tcx>, + mut analysis: ty::CrateAnalysis, resolutions: Resolutions, arena: &'tcx DroplessArena, arenas: &'tcx GlobalArenas<'tcx>, @@ -821,7 +820,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, f: F) -> Result where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>, - ty::CrateAnalysis<'tcx>, + ty::CrateAnalysis, IncrementalHashesMap, 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)); // 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, "const checking", diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 429e4ffef0c2a..064c4982ef00e 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -201,7 +201,7 @@ impl PpSourceMode { fn call_with_pp_support_hir<'tcx, A, B, F>(&self, sess: &'tcx Session, hir_map: &hir_map::Map<'tcx>, - analysis: &ty::CrateAnalysis<'tcx>, + analysis: &ty::CrateAnalysis, resolutions: &Resolutions, arena: &'tcx DroplessArena, 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, hir_map: &hir_map::Map<'tcx>, - analysis: &ty::CrateAnalysis<'tcx>, + analysis: &ty::CrateAnalysis, resolutions: &Resolutions, input: &Input, 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. fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, hir_map: &hir_map::Map<'tcx>, - analysis: &ty::CrateAnalysis<'tcx>, + analysis: &ty::CrateAnalysis, resolutions: &Resolutions, crate_name: &str, arena: &'tcx DroplessArena, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index ddc60fe5f81d8..b1e435dcc751c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -85,7 +85,7 @@ pub mod recorder { pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, tables: &'l ty::TypeckTables<'tcx>, - analysis: &'l ty::CrateAnalysis<'tcx>, + analysis: &'l ty::CrateAnalysis, span_utils: SpanUtils<'tcx>, } @@ -550,7 +550,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { match *qpath { hir::QPath::Resolved(_, ref path) => path.def, 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 { for item in self.tcx.associated_items(proj.trait_ref.def_id) { if item.kind == ty::AssociatedKind::Type { @@ -854,7 +854,7 @@ impl Format { pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>, krate: &ast::Crate, - analysis: &'l ty::CrateAnalysis<'tcx>, + analysis: &'l ty::CrateAnalysis, cratename: &str, odir: Option<&Path>, format: Format) { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 11ad47eef7159..cf93ef21f5d4a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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 // bounds may affect Self type and have to be converted before it. 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 { tcx.impl_trait_ref(impl_def_id) }; diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 3a980c8e7642b..8f1135adbb454 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -10,11 +10,10 @@ use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag}; -use CrateCtxt; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; -use rustc::ty::{self, LvaluePreference, Ty}; +use rustc::ty::{self, TyCtxt, LvaluePreference, Ty}; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -23,12 +22,9 @@ use rustc::hir; /// Check that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific /// method that is called) -pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: DefId) { - if ccx.tcx.lang_items.drop_trait() == Some(trait_id) { - struct_span_err!(ccx.tcx.sess, - span, - E0040, - "explicit use of destructor method") +pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) { + if tcx.lang_items.drop_trait() == Some(trait_id) { + struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method") .span_label(span, &format!("explicit destructor calls not allowed")) .emit(); } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index bdeb716535655..2d4749331c08a 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -11,7 +11,7 @@ use rustc::hir::{self, ImplItemKind, TraitItemKind}; use rustc::infer::{self, InferOk}; use rustc::middle::free_region::FreeRegionMap; -use rustc::ty; +use rustc::ty::{self, TyCtxt}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{Subst, Substs}; @@ -20,7 +20,6 @@ use rustc::util::common::ErrorReported; use syntax::ast; use syntax_pos::Span; -use CrateCtxt; use super::assoc; use super::{Inherited, FnCtxt}; use astconv::ExplicitSelf; @@ -36,7 +35,7 @@ use astconv::ExplicitSelf; /// - trait_m: the method in the trait /// - 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_span: Span, 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={:?})", impl_trait_ref); - if let Err(ErrorReported) = compare_self_type(ccx, + if let Err(ErrorReported) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, @@ -55,7 +54,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } - if let Err(ErrorReported) = compare_number_of_generics(ccx, + if let Err(ErrorReported) = compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, @@ -63,7 +62,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, 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_span, trait_m, @@ -71,7 +70,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } - if let Err(ErrorReported) = compare_predicate_entailment(ccx, + if let Err(ErrorReported) = compare_predicate_entailment(tcx, impl_m, impl_m_span, 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_span: Span, 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>, old_broken_mode: bool) -> Result<(), ErrorReported> { - let tcx = ccx.tcx; - let trait_to_impl_substs = impl_trait_ref.substs; 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); // Check region bounds. - check_region_bounds_on_impl_method(ccx, + check_region_bounds_on_impl_method(tcx, impl_m_span, impl_m, &trait_m_generics, @@ -228,7 +225,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, normalize_cause.clone()); 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 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, impl_m: &ty::AssociatedItem, 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 // the moment, give a kind of vague error message. if trait_params.len() != impl_params.len() { - struct_span_err!(ccx.tcx.sess, + struct_span_err!(tcx.sess, span, E0195, "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_span: Span, trait_m: &ty::AssociatedItem, impl_trait_ref: ty::TraitRef<'tcx>) -> Result<(), ErrorReported> { - let tcx = ccx.tcx; // Try to give more informative error messages about self typing // mismatches. Note that any mismatch will also be detected // below, where we construct a canonical function type that @@ -583,13 +579,12 @@ fn compare_self_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, 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_span: Span, trait_m: &ty::AssociatedItem, trait_item_span: Option) -> Result<(), ErrorReported> { - let tcx = ccx.tcx; let impl_m_generics = tcx.item_generics(impl_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(); @@ -653,13 +648,12 @@ fn compare_number_of_generics<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, 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_span: Span, trait_m: &ty::AssociatedItem, trait_item_span: Option) -> Result<(), ErrorReported> { - let tcx = ccx.tcx; let m_fty = |method: &ty::AssociatedItem| { match tcx.item_type(method.def_id).sty { ty::TyFnDef(_, _, f) => f, @@ -739,14 +733,13 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, 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_span: Span, trait_c: &ty::AssociatedItem, impl_trait_ref: ty::TraitRef<'tcx>) { debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - let tcx = ccx.tcx; tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index f701bc3220848..385ea7d52e1ce 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use CrateCtxt; use check::regionck::RegionCtxt; use hir::def_id::DefId; @@ -40,17 +39,18 @@ use syntax_pos::Span; /// struct/enum definition for the nominal type itself (i.e. /// cannot do `struct S; impl Drop for S { ... }`). /// -pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> { - let dtor_self_type = ccx.tcx.item_type(drop_impl_did); - let dtor_predicates = ccx.tcx.item_predicates(drop_impl_did); +pub fn check_drop_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + drop_impl_did: DefId) -> Result<(), ()> { + let dtor_self_type = tcx.item_type(drop_impl_did); + let dtor_predicates = tcx.item_predicates(drop_impl_did); match dtor_self_type.sty { 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, dtor_self_type, adt_def.did)?; - ensure_drop_predicates_are_implied_by_item_defn(ccx, + ensure_drop_predicates_are_implied_by_item_defn(tcx, drop_impl_did, &dtor_predicates, 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 // 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, "should have been rejected by coherence check: {}", 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>( - ccx: &CrateCtxt<'a, 'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, drop_impl_did: DefId, drop_impl_ty: Ty<'tcx>, self_type_did: DefId) -> Result<(), ()> { - let tcx = ccx.tcx; 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(); @@ -126,7 +125,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( /// Confirms that every predicate imposed by dtor_predicates is /// implied by assuming the predicates attached to self_type_did. fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( - ccx: &CrateCtxt<'a, 'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, drop_impl_did: DefId, dtor_predicates: &ty::GenericPredicates<'tcx>, 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 // 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 drop_impl_span = tcx.def_span(drop_impl_did); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index cb4e85e842c2a..4d4e312dab37c 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -14,9 +14,9 @@ use intrinsics; use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, TyCtxt, Ty}; use rustc::util::nodemap::FxHashMap; -use {CrateCtxt, require_same_types}; +use require_same_types; use syntax::abi::Abi; use syntax::ast; @@ -27,13 +27,12 @@ use rustc::hir; 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, n_tps: usize, abi: Abi, inputs: Vec>, output: Ty<'tcx>) { - let tcx = ccx.tcx; let def_id = tcx.hir.local_def_id(it.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)) .emit(); } else { - require_same_types(ccx, + require_same_types(tcx, &ObligationCause::new(it.span, it.id, 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, /// and in libcore/intrinsics.rs -pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { - fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { - let name = Symbol::intern(&format!("P{}", n)); - ccx.tcx.mk_param(n, name) - } - - let tcx = ccx.tcx; +pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + it: &hir::ForeignItem) { + let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n))); let name = it.name.as_str(); let (n_tps, inputs, output) = if name.starts_with("atomic_") { 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 let (n_tps, inputs, output) = match split[1] { - "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), - param(ccx, 0), - param(ccx, 0)], - tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), - "load" => (1, vec![tcx.mk_imm_ptr(param(ccx, 0))], - param(ccx, 0)), - "store" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)], + "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(0)), + param(0), + param(0)], + tcx.intern_tup(&[param(0), tcx.types.bool], false)), + "load" => (1, vec![tcx.mk_imm_ptr(param(0))], + param(0)), + "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_nil()), "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax" | "umin" => { - (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)], - param(ccx, 0)) + (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], + param(0)) } "fence" | "singlethreadfence" => { (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[..] { "breakpoint" => (0, Vec::new(), tcx.mk_nil()), "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" => { (1, vec![ tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(0))), - param(ccx, 0)) - ], ccx.tcx.types.usize) + param(0)) + ], tcx.types.usize) } - "rustc_peek" => (1, vec![param(ccx, 0)], param(ccx, 0)), - "init" => (1, Vec::new(), param(ccx, 0)), - "uninit" => (1, Vec::new(), param(ccx, 0)), - "forget" => (1, vec![ param(ccx, 0) ], tcx.mk_nil()), - "transmute" => (2, vec![ param(ccx, 0) ], param(ccx, 1)), + "rustc_peek" => (1, vec![param(0)], param(0)), + "init" => (1, Vec::new(), param(0)), + "uninit" => (1, Vec::new(), param(0)), + "forget" => (1, vec![ param(0) ], tcx.mk_nil()), + "transmute" => (2, vec![ param(0) ], param(1)), "move_val_init" => { (1, vec![ - tcx.mk_mut_ptr(param(ccx, 0)), - param(ccx, 0) + tcx.mk_mut_ptr(param(0)), + param(0) ], tcx.mk_nil()) } "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_id" => (1, Vec::new(), ccx.tcx.types.u64), + "type_id" => (1, Vec::new(), tcx.types.u64), "offset" | "arith_offset" => { (1, vec![ tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutImmutable }), - ccx.tcx.types.isize + tcx.types.isize ], tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutImmutable })) } @@ -162,11 +157,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { (1, vec![ tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutImmutable }), tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutMutable }), tcx.types.usize, @@ -177,11 +172,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { (1, vec![ tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutMutable }), tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutImmutable }), tcx.types.usize, @@ -192,7 +187,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { (1, vec![ tcx.mk_ptr(ty::TypeAndMut { - ty: param(ccx, 0), + ty: param(0), mutbl: hir::MutMutable }), 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), "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" => - (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" => - (1, vec![param(ccx, 0), param(ccx, 0)], - tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), + (1, vec![param(0), param(0)], + tcx.intern_tup(&[param(0), tcx.types.bool], false)), "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" => - (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" => - (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()), "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![ tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(0))), - param(ccx, 0))], tcx.types.u64), + param(0))], tcx.types.u64), "try" => { 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) }; - 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. -pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, - it: &hir::ForeignItem) { +pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + it: &hir::ForeignItem) { let param = |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 i_n_tps = tcx.item_generics(def_id).types.len(); 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()); 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); } - match_intrinsic_type_to_type(ccx, "return value", it.span, + match_intrinsic_type_to_type(tcx, "return value", it.span, &mut structural_to_nomimal, &intr.output, sig.output()); 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) } // 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 // exactly the right element type -fn match_intrinsic_type_to_type<'tcx, 'a>( - ccx: &CrateCtxt<'a, 'tcx>, +fn match_intrinsic_type_to_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, position: &str, span: Span, 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::*; 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 {}", position, real, expected) }; @@ -453,7 +447,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( simple_error(&format!("`{}`", t), 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) } _ => 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"); return; } - let t_len = t.simd_size(ccx.tcx); + let t_len = t.simd_size(tcx); if len as usize != t_len { simple_error(&format!("vector with length {}", t_len), &format!("length {}", len)); 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 let previous = structural_to_nominal.entry(expected).or_insert(t); if *previous != t { // 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 \ was used for this vector type previously in this signature", position, @@ -485,7 +479,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( return; } } - match_intrinsic_type_to_type(ccx, + match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal, @@ -501,7 +495,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( return } 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) } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 2d90394025d21..917607aab6b5a 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -566,7 +566,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Disallow calls to the method `drop` defined in the `Drop` trait. match pick.item.container { 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(..) => {} } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 468a38cd2bace..b6071d01ff1cf 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -653,7 +653,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> { 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) { self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?; } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f6345e6e262db..6ce50d91124d4 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -11,11 +11,9 @@ //! Give useful errors and suggestions to users when an item can't be //! found or is otherwise invalid. -use CrateCtxt; - use check::FnCtxt; 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_id::{CRATE_DEF_INDEX, DefId}; 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 // implement, by finding ones that have the item name, and are // legal to implement. - let mut candidates = all_traits(self.ccx) + let mut candidates = all_traits(self.tcx) .filter(|info| { // we approximate the coherence rules to only suggest // 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; +pub type AllTraitsVec = Vec; #[derive(Copy, Clone)] pub struct TraitInfo { @@ -458,8 +456,8 @@ impl Ord for TraitInfo { } /// Retrieve all traits in this crate and any dependent crates. -pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { - if ccx.all_traits.borrow().is_none() { +pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> { + if tcx.all_traits.borrow().is_none() { use rustc::hir::itemlikevisit; let mut traits = vec![]; @@ -476,7 +474,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { match i.node { hir::ItemTrait(..) => { 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) { } } - ccx.tcx.hir.krate().visit_all_item_likes(&mut Visitor { - map: &ccx.tcx.hir, + tcx.hir.krate().visit_all_item_likes(&mut Visitor { + map: &tcx.hir, traits: &mut traits, }); // Cross-crate: let mut external_mods = FxHashSet(); - fn handle_external_def(ccx: &CrateCtxt, + fn handle_external_def(tcx: TyCtxt, traits: &mut AllTraitsVec, external_mods: &mut FxHashSet, def: Def) { let def_id = def.def_id(); match def { Def::Trait(..) => { - traits.push(TraitInfo::new(def_id)); + traits.push(def_id); } Def::Mod(..) => { if !external_mods.insert(def_id) { return; } - for child in ccx.tcx.sess.cstore.item_children(def_id) { - handle_external_def(ccx, traits, external_mods, child.def) + for child in tcx.sess.cstore.item_children(def_id) { + 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 { krate: cnum, 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()); AllTraits { borrow: borrow, @@ -547,7 +545,7 @@ impl<'a> Iterator for AllTraits<'a> { // ugh. borrow.as_ref().unwrap().get(*idx).map(|info| { *idx += 1; - *info + TraitInfo::new(*info) }) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6a003ef734020..d52516e0ae500 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -56,7 +56,7 @@ stored in `fcx.node_types` and `fcx.item_substs`. These types may contain unresolved type variables. After type checking is complete, the functions in the writeback module are used to take the 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()` 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 require_c_abi_if_variadic; use session::{Session, CompileResult}; -use CrateCtxt; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; @@ -154,8 +153,8 @@ mod op; /// `bar()` will each have their own `FnCtxt`, but they will /// share the inherited fields. pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - ccx: &'a CrateCtxt<'a, 'gcx>, infcx: InferCtxt<'a, 'gcx, 'tcx>, + locals: RefCell>>, fulfillment_cx: RefCell>, @@ -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: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>). pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - ccx: &'a CrateCtxt<'a, 'gcx>, infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx> } -impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> { - pub fn inherited(&'a self, id: ast::NodeId) - -> InheritedBuilder<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { + pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId) + -> InheritedBuilder<'a, 'gcx, 'tcx> { let tables = ty::TypeckTables::empty(); - let param_env = ParameterEnvironment::for_item(self.tcx, id); + let param_env = ParameterEnvironment::for_item(tcx, id); InheritedBuilder { - ccx: self, - infcx: self.tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable) + infcx: tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable) } } } @@ -498,17 +495,13 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> { fn enter(&'tcx mut self, f: F) -> R where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R { - let ccx = self.ccx; - self.infcx.enter(|infcx| f(Inherited::new(ccx, infcx))) + self.infcx.enter(|infcx| f(Inherited::new(infcx))) } } impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { - pub fn new(ccx: &'a CrateCtxt<'a, 'gcx>, - infcx: InferCtxt<'a, 'gcx, 'tcx>) - -> Self { + pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self { Inherited { - ccx: ccx, infcx: infcx, fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), 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 CheckItemBodiesVisitor<'a, 'tcx: 'a> { ccx: &'a CrateCtxt<'a, 'tcx> } +struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } +struct CheckItemBodiesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, '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) { - check_item_type(self.ccx, i); + check_item_type(self.tcx, i); intravisit::walk_item(self, i); } fn visit_ty(&mut self, t: &'tcx hir::Ty) { match t.node { 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) { match e.node { 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) { match item.node { 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) { match trait_item.node { 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)) => { - 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::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) { match impl_item.node { 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) => { - 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(_) => { // 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 { - ccx.tcx.sess.track_errors(|| { - let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx); - ccx.tcx.visit_all_item_likes_in_krate(DepNode::WfCheck, &mut visit.as_deep_visitor()); +pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { + tcx.sess.track_errors(|| { + let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); + tcx.visit_all_item_likes_in_krate(DepNode::WfCheck, &mut visit.as_deep_visitor()); }) } -pub fn check_item_types(ccx: &CrateCtxt) -> CompileResult { - ccx.tcx.sess.track_errors(|| { - let mut visit = CheckItemTypesVisitor { ccx: ccx }; - ccx.tcx.visit_all_item_likes_in_krate(DepNode::TypeckItemType, +pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { + tcx.sess.track_errors(|| { + let mut visit = CheckItemTypesVisitor { tcx: tcx }; + tcx.visit_all_item_likes_in_krate(DepNode::TypeckItemType, &mut visit.as_deep_visitor()); }) } -pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult { - ccx.tcx.sess.track_errors(|| { - let mut visit = CheckItemBodiesVisitor { ccx: ccx }; - ccx.tcx.visit_all_item_likes_in_krate(DepNode::TypeckTables, &mut visit); +pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { + tcx.sess.track_errors(|| { + let mut visit = CheckItemBodiesVisitor { tcx: tcx }; + tcx.visit_all_item_likes_in_krate(DepNode::TypeckTables, &mut visit); // Process deferred obligations, now that all functions // 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. - let def_id = ccx.tcx.hir.local_def_id(item_id); - let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeckTables(def_id)); + let def_id = tcx.hir.local_def_id(item_id); + let _task = tcx.dep_graph.in_task(DepNode::TypeckTables(def_id)); - let param_env = ParameterEnvironment::for_item(ccx.tcx, item_id); - ccx.tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { + let param_env = ParameterEnvironment::for_item(tcx, item_id); + tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); for obligation in obligations.iter().map(|o| o.to_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 { - ccx.tcx.sess.track_errors(|| { - let _task = ccx.tcx.dep_graph.in_task(DepNode::Dropck); - let drop_trait = match ccx.tcx.lang_items.drop_trait() { - Some(id) => ccx.tcx.lookup_trait_def(id), None => { return } +pub fn check_drop_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult { + tcx.sess.track_errors(|| { + let _task = tcx.dep_graph.in_task(DepNode::Dropck); + let drop_trait = match tcx.lang_items.drop_trait() { + Some(id) => tcx.lookup_trait_def(id), None => { return } }; - drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| { - let _task = ccx.tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did)); + drop_trait.for_each_impl(tcx, |drop_impl_did| { + let _task = tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did)); if drop_impl_did.is_local() { - match dropck::check_drop_impl(ccx, drop_impl_did) { + match dropck::check_drop_impl(tcx, drop_impl_did) { Ok(()) => {} 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, body_id: hir::BodyId, fn_id: ast::NodeId, 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 { ty::TyFnDef(.., f) => f, _ => 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. let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id); 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) { - if !ccx.tcx.sess.target.target.is_abi_supported(abi) { - struct_span_err!(ccx.tcx.sess, span, E0570, +fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { + if !tcx.sess.target.target.is_abi_supported(abi) { + struct_span_err!(tcx.sess, span, E0570, "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 } -fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { - let def_id = ccx.tcx.hir.local_def_id(id); - check_representable(ccx.tcx, span, def_id); +fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: ast::NodeId, + span: Span) { + let def_id = tcx.hir.local_def_id(id); + check_representable(tcx, span, def_id); - if ccx.tcx.lookup_simd(def_id) { - check_simd(ccx.tcx, span, def_id); + if tcx.lookup_simd(def_id) { + check_simd(tcx, span, def_id); } } -fn check_union(ccx: &CrateCtxt, id: ast::NodeId, span: Span) { - check_representable(ccx.tcx, span, ccx.tcx.hir.local_def_id(id)); +fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: ast::NodeId, + span: Span) { + check_representable(tcx, span, tcx.hir.local_def_id(id)); } -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={})", 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(); match it.node { // Consts can play a role in type-checking, so they are included here. 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, _) => { - check_enum_variants(ccx, + check_enum_variants(tcx, it.span, &enum_definition.variants, 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::ItemImpl(.., ref impl_item_refs) => { debug!("ItemImpl {} with id {}", it.name, it.id); - let impl_def_id = ccx.tcx.hir.local_def_id(it.id); - if let Some(impl_trait_ref) = ccx.tcx.impl_trait_ref(impl_def_id) { - check_impl_items_against_trait(ccx, + let impl_def_id = tcx.hir.local_def_id(it.id); + if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) { + check_impl_items_against_trait(tcx, it.span, impl_def_id, impl_trait_ref, impl_item_refs); 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(..) => { - let def_id = ccx.tcx.hir.local_def_id(it.id); - check_on_unimplemented(ccx, def_id, it); + let def_id = tcx.hir.local_def_id(it.id); + check_on_unimplemented(tcx, def_id, it); } hir::ItemStruct(..) => { - check_struct(ccx, it.id, it.span); + check_struct(tcx, it.id, it.span); } hir::ItemUnion(..) => { - check_union(ccx, it.id, it.span); + check_union(tcx, it.id, it.span); } hir::ItemTy(_, ref generics) => { - let def_id = ccx.tcx.hir.local_def_id(it.id); - let pty_ty = ccx.tcx.item_type(def_id); - check_bounds_are_used(ccx, generics, pty_ty); + let def_id = tcx.hir.local_def_id(it.id); + let pty_ty = tcx.item_type(def_id); + check_bounds_are_used(tcx, generics, pty_ty); } hir::ItemForeignMod(ref m) => { - check_abi(ccx, it.span, m.abi); + check_abi(tcx, it.span, m.abi); if m.abi == Abi::RustIntrinsic { for item in &m.items { - intrinsic::check_intrinsic_type(ccx, item); + intrinsic::check_intrinsic_type(tcx, item); } } else if m.abi == Abi::PlatformIntrinsic { for item in &m.items { - intrinsic::check_platform_intrinsic_type(ccx, item); + intrinsic::check_platform_intrinsic_type(tcx, item); } } else { 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() { - 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"); span_help!(&mut err, item.span, "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 { - 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, 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| { a.check_name("rustc_on_unimplemented") }) { @@ -950,8 +947,8 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) { Some(_) => (), None => { - let name = ccx.tcx.item_name(def_id); - span_err!(ccx.tcx.sess, attr.span, E0230, + let name = tcx.item_name(def_id); + span_err!(tcx.sess, attr.span, E0230, "there is no type parameter \ {} on trait {}", s, name); @@ -959,7 +956,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }, // `{:1}` and `{}` are not to be used Position::ArgumentIs(_) => { - span_err!(ccx.tcx.sess, attr.span, E0231, + span_err!(tcx.sess, attr.span, E0231, "only named substitution \ parameters are allowed"); } @@ -968,7 +965,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } else { struct_span_err!( - ccx.tcx.sess, attr.span, E0232, + tcx.sess, attr.span, E0232, "this attribute must have a value") .span_label(attr.span, &format!("attribute requires a value")) .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_id: DefId, 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; } // Locate trait definition and items - let tcx = ccx.tcx; let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id); 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 // and compatible with trait signature @@ -1056,7 +1052,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ImplItemKind::Const(..) => { // Find associated const definition. if ty_trait_item.kind == ty::AssociatedKind::Const { - compare_const_impl(ccx, + compare_const_impl(tcx, &ty_impl_item, impl_item.span, &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); if ty_trait_item.kind == ty::AssociatedKind::Method { let err_count = tcx.sess.err_count(); - compare_impl_method(ccx, + compare_impl_method(tcx, &ty_impl_item, impl_item.span, 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 if err_count == tcx.sess.err_count() { // old broken mode did not report an error. Try with the new mode. - compare_impl_method(ccx, + compare_impl_method(tcx, &ty_impl_item, impl_item.span, 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. -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, expected_type: Ty<'tcx>, id: ast::NodeId) { - let body = ccx.tcx.hir.body(body); - ccx.inherited(id).enter(|inh| { + let body = tcx.hir.body(body); + Inherited::build(tcx, id).enter(|inh| { let fcx = FnCtxt::new(&inh, None, body.value.id); 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, id: ast::NodeId) { - let decl_ty = ccx.tcx.item_type(ccx.tcx.hir.local_def_id(id)); - check_const_with_type(ccx, body, decl_ty, id); + let decl_ty = tcx.item_type(tcx.hir.local_def_id(id)); + check_const_with_type(tcx, body, decl_ty, id); } /// 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)] -pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - sp: Span, - vs: &'tcx [hir::Variant], - id: ast::NodeId) { - let def_id = ccx.tcx.hir.local_def_id(id); - let hint = *ccx.tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny); +pub fn check_enum_variants<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + sp: Span, + vs: &'tcx [hir::Variant], + id: ast::NodeId) { + let def_id = tcx.hir.local_def_id(id); + let hint = *tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny); if hint != attr::ReprAny && vs.is_empty() { struct_span_err!( - ccx.tcx.sess, sp, E0084, + tcx.sess, sp, E0084, "unsupported representation for zero-variant enum") .span_label(sp, &format!("unsupported enum representation")) .emit(); } - let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx); - if repr_type_ty == ccx.tcx.types.i128 || repr_type_ty == ccx.tcx.types.u128 { - if !ccx.tcx.sess.features.borrow().i128_type { - emit_feature_err(&ccx.tcx.sess.parse_sess, + let repr_type_ty = tcx.enum_repr_type(Some(&hint)).to_ty(tcx); + if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { + if !tcx.sess.features.borrow().i128_type { + emit_feature_err(&tcx.sess.parse_sess, "i128_type", sp, GateIssue::Language, "128-bit type is unstable"); } } for v in vs { 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 = 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 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 = ccx.tcx.hir.expect_variant(variant_i_node_id); + let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap(); + let variant_i = tcx.hir.expect_variant(variant_i_node_id); let i_span = match variant_i.node.disr_expr { - Some(expr) => ccx.tcx.hir.span(expr.node_id), - None => ccx.tcx.hir.span(variant_i_node_id) + Some(expr) => tcx.hir.span(expr.node_id), + None => tcx.hir.span(variant_i_node_id) }; 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 }; - struct_span_err!(ccx.tcx.sess, span, E0081, + struct_span_err!(tcx.sess, span, E0081, "discriminant value `{}` already exists", disr_vals[i]) .span_label(i_span, &format!("first use of `{}`", 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); } - 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> { @@ -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 { &self.tcx.sess } @@ -1754,10 +1746,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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) { 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; match container { 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(_) => {} } @@ -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, ty: Ty<'tcx>) { 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) { if !used { - struct_span_err!(ccx.tcx.sess, param.span, E0091, + struct_span_err!(tcx.sess, param.span, E0091, "type parameter `{}` is unused", param.name) .span_label(param.span, &format!("unused type parameter")) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index d84e9d3fd3731..a120e3c343155 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -102,8 +102,6 @@ use syntax_pos::Span; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::{self, PatKind}; -use self::SubjectNode::Subject; - // a variation on try that just returns unit macro_rules! ignore_err { ($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, // 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 enum SubjectNode { Subject(ast::NodeId), None } +pub struct Subject(ast::NodeId); impl<'a, 'gcx, 'tcx> RegionCtxt<'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, - subject: SubjectNode) -> RegionCtxt<'a, 'gcx, 'tcx> { - let RepeatingScope(initial_repeating_scope) = initial_repeating_scope; + Subject(subject): Subject) -> RegionCtxt<'a, 'gcx, 'tcx> { RegionCtxt { fcx: fcx, repeating_scope: initial_repeating_scope, @@ -416,13 +413,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } fn resolve_regions_and_report_errors(&self) { - let subject_node_id = match self.subject { - Subject(s) => s, - SubjectNode::None => { - bug!("cannot resolve_regions_and_report_errors \ - without subject node"); - } - }; + let subject_node_id = self.subject; self.fcx.resolve_regions_and_report_errors(&self.free_region_map, subject_node_id); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index cef6a75e58dc9..533223546ad56 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -9,9 +9,8 @@ // except according to those terms. use astconv::ExplicitSelf; -use check::FnCtxt; +use check::{Inherited, FnCtxt}; use constrained_type_params::{identify_constrained_type_params, Parameter}; -use CrateCtxt; use hir::def_id::DefId; use middle::region::{CodeExtent}; @@ -27,8 +26,8 @@ use errors::DiagnosticBuilder; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; -pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> { - ccx: &'ccx CrateCtxt<'ccx, 'tcx>, +pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, code: ObligationCauseCode<'tcx>, } @@ -51,9 +50,9 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { let id = self.id; let span = self.span; 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 { - ccx: fcx.ccx, + tcx: fcx.tcx.global_tcx(), code: code }); fcx.select_all_obligations_or_error(); @@ -62,19 +61,15 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { } } -impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { - pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'gcx>) - -> CheckTypeWellFormedVisitor<'ccx, 'gcx> { +impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) + -> CheckTypeWellFormedVisitor<'a, 'gcx> { CheckTypeWellFormedVisitor { - ccx: ccx, + tcx: tcx, 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 /// well-formed, meaning that they do not require any constraints not declared in the struct /// 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 /// the types first. 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={})", 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 { /// 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(_), ..) => { // 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(); - if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) { - error_192(ccx, item.span); + let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap(); + if !tcx.trait_has_default_impl(trait_ref.def_id) { + error_192(tcx, item.span); } } hir::ItemFn(.., body_id) => { @@ -211,14 +206,14 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } fn for_item<'tcx>(&self, item: &hir::Item) - -> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> { + -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { self.for_id(item.id, item.span) } fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) - -> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> { + -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { CheckWfFcxBuilder { - inherited: self.ccx.inherited(id), + inherited: Inherited::build(self.tcx, id), code: self.code.clone(), id: id, span: span @@ -270,7 +265,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { // // 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 // 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 // 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 // an associated type inside the trait. let mut err = None; - if !self.tcx().associated_item_def_ids(trait_def_id).is_empty() { - error_380(self.ccx, span); + if !self.tcx.associated_item_def_ids(trait_def_id).is_empty() { + error_380(self.tcx, span); } 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 \ Trait for ..`) can not have type parameters")); } 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 \ Trait for ..`) cannot have predicates")); } @@ -321,9 +316,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } 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); } @@ -514,15 +509,15 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { item: &hir::Item, ast_generics: &hir::Generics) { - let item_def_id = self.tcx().hir.local_def_id(item.id); - let ty = self.tcx().item_type(item_def_id); - if self.tcx().has_error_field(ty) { + let item_def_id = self.tcx.hir.local_def_id(item.id); + let ty = self.tcx.item_type(item_def_id); + if self.tcx.has_error_field(ty) { 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); - let variances = self.tcx().item_variances(item_def_id); + let variances = self.tcx.item_variances(item_def_id); let mut constrained_parameters: FxHashSet<_> = variances.iter().enumerate() @@ -555,15 +550,15 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { span: Span, 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 { Some(def_id) => { err.help( &format!("consider removing `{}` or using a marker such as `{}`", param_name, - self.tcx().item_path_str(def_id))); + self.tcx.item_path_str(def_id))); } None => { // 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> { NestedVisitorMap::None } @@ -681,21 +676,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } -fn error_192(ccx: &CrateCtxt, span: Span) { - span_err!(ccx.tcx.sess, span, E0192, +fn error_192(tcx: TyCtxt, span: Span) { + span_err!(tcx.sess, span, E0192, "negative impls are only allowed for traits with \ default impls (e.g., `Send` and `Sync`)") } -fn error_380(ccx: &CrateCtxt, span: Span) { - span_err!(ccx.tcx.sess, span, E0380, +fn error_380(tcx: TyCtxt, span: Span) { + span_err!(tcx.sess, span, E0380, "traits with default impls (`e.g. impl \ 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> { - 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); err.span_label(span, &format!("unused type parameter")); err diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 650f32eb6b216..f7f004fbaef12 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -491,7 +491,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { }).collect(); 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()); } } @@ -499,7 +499,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_type_nodes(&self) { for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() { 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); } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 4aa0650e57f71..ed5ca79a70661 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -24,7 +24,6 @@ use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple}; use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use rustc::ty::{TyUint, TyClosure, TyFnDef, TyFnPtr}; use rustc::ty::{TyProjection, TyAnon}; -use CrateCtxt; use syntax_pos::Span; use rustc::dep_graph::DepNode; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -176,12 +175,12 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def err.emit(); } -pub fn check_coherence(ccx: &CrateCtxt) { - CoherenceCollect::check(ccx.tcx); +pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + CoherenceCollect::check(tcx); - let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); - unsafety::check(ccx.tcx); - orphan::check(ccx.tcx); - overlap::check(ccx.tcx); - builtin::check(ccx.tcx); + let _task = tcx.dep_graph.in_task(DepNode::Coherence); + unsafety::check(tcx); + orphan::check(tcx); + overlap::check(tcx); + builtin::check(tcx); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 90d12b26c6a62..95fd123b7df4c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -72,7 +72,6 @@ use rustc::ty::util::IntTypeExt; use rustc::dep_graph::DepNode; use util::common::{ErrorReported, MemoizationMap}; use util::nodemap::{NodeMap, FxHashMap}; -use CrateCtxt; use rustc_const_math::ConstInt; @@ -91,9 +90,9 @@ use rustc::hir::def_id::DefId; /////////////////////////////////////////////////////////////////////////// // Main entry point -pub fn collect_item_types(ccx: &CrateCtxt) { - let mut visitor = CollectItemTypesVisitor { ccx: ccx }; - ccx.tcx.visit_all_item_likes_in_krate(DepNode::CollectItem, &mut visitor.as_deep_visitor()); +pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let mut visitor = CollectItemTypesVisitor { tcx: tcx }; + tcx.visit_all_item_likes_in_krate(DepNode::CollectItem, &mut visitor.as_deep_visitor()); } /////////////////////////////////////////////////////////////////////////// @@ -108,21 +107,14 @@ pub fn collect_item_types(ccx: &CrateCtxt) { /// `get_type_parameter_bounds` requests, drawing the information from /// the AST (`hir::Generics`), recursively. struct ItemCtxt<'a,'tcx:'a> { - ccx: &'a CrateCtxt<'a,'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId, } -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum AstConvRequest { - GetItemType(DefId), - EnsureSuperPredicates(DefId), - GetTypeParameterBounds(ast::NodeId), -} - /////////////////////////////////////////////////////////////////////////// struct CollectItemTypesVisitor<'a, 'tcx: 'a> { - ccx: &'a CrateCtxt<'a, 'tcx> + tcx: TyCtxt<'a, 'tcx, 'tcx> } impl<'a, 'tcx> CollectItemTypesVisitor<'a, 'tcx> { @@ -166,9 +158,9 @@ impl<'a, 'tcx> CollectItemTypesVisitor<'a, 'tcx> { fn with_collect_item_sig(&self, id: ast::NodeId, op: OP) where OP: FnOnce() { - let def_id = self.ccx.tcx.hir.local_def_id(id); - self.ccx.tcx.dep_graph.with_task(DepNode::CollectItemSig(def_id), || { - self.ccx.tcx.hir.read(id); + let def_id = self.tcx.hir.local_def_id(id); + self.tcx.dep_graph.with_task(DepNode::CollectItemSig(def_id), || { + self.tcx.hir.read(id); op(); }); } @@ -176,19 +168,19 @@ impl<'a, 'tcx> CollectItemTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, '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, item: &'tcx hir::Item) { - self.with_collect_item_sig(item.id, || convert_item(self.ccx, item)); + self.with_collect_item_sig(item.id, || convert_item(self.tcx, item)); intravisit::walk_item(self, item); } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { for param in &generics.ty_params { if param.default.is_some() { - let def_id = self.ccx.tcx.hir.local_def_id(param.id); - type_of_def_id(self.ccx, def_id); + let def_id = self.tcx.hir.local_def_id(param.id); + type_of_def_id(self.tcx, def_id); } } intravisit::walk_generics(self, generics); @@ -196,31 +188,31 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if let hir::ExprClosure(..) = expr.node { - let def_id = self.ccx.tcx.hir.local_def_id(expr.id); - generics_of_def_id(self.ccx, def_id); - type_of_def_id(self.ccx, def_id); + let def_id = self.tcx.hir.local_def_id(expr.id); + generics_of_def_id(self.tcx, def_id); + type_of_def_id(self.tcx, def_id); } intravisit::walk_expr(self, expr); } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { if let hir::TyImplTrait(..) = ty.node { - let def_id = self.ccx.tcx.hir.local_def_id(ty.id); - generics_of_def_id(self.ccx, def_id); + let def_id = self.tcx.hir.local_def_id(ty.id); + generics_of_def_id(self.tcx, def_id); } intravisit::walk_ty(self, ty); } fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { self.with_collect_item_sig(trait_item.id, || { - convert_trait_item(self.ccx, trait_item) + convert_trait_item(self.tcx, trait_item) }); intravisit::walk_trait_item(self, trait_item); } fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { self.with_collect_item_sig(impl_item.id, || { - convert_impl_item(self.ccx, impl_item) + convert_impl_item(self.tcx, impl_item) }); intravisit::walk_impl_item(self, impl_item); } @@ -229,127 +221,100 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // Utility types and common code for the above passes. -impl<'a,'tcx> CrateCtxt<'a,'tcx> { - fn icx(&'a self, item_def_id: DefId) -> ItemCtxt<'a,'tcx> { +impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { + fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) + -> ItemCtxt<'a,'tcx> { ItemCtxt { - ccx: self, + tcx: tcx, item_def_id: item_def_id, } } +} - fn cycle_check(&self, + fn cycle_check(tcx: TyCtxt, span: Span, - request: AstConvRequest, + query: ty::maps::Query, code: F) -> Result where F: FnOnce() -> Result { { - let mut stack = self.stack.borrow_mut(); - if let Some((i, _)) = stack.iter().enumerate().rev().find(|&(_, r)| *r == request) { + let mut stack = tcx.maps.query_stack.borrow_mut(); + if let Some((i, _)) = stack.iter().enumerate().rev().find(|&(_, q)| *q == query) { let cycle = &stack[i..]; - self.report_cycle(span, cycle); + report_cycle(tcx, span, cycle); return Err(ErrorReported); } - stack.push(request); + stack.push(query); } let result = code(); - self.stack.borrow_mut().pop(); + tcx.maps.query_stack.borrow_mut().pop(); result } - fn report_cycle(&self, + fn report_cycle(tcx: TyCtxt, span: Span, - cycle: &[AstConvRequest]) + cycle: &[ty::maps::Query]) { assert!(!cycle.is_empty()); - let tcx = self.tcx; let mut err = struct_span_err!(tcx.sess, span, E0391, "unsupported cyclic reference between types/traits detected"); err.span_label(span, &format!("cyclic reference")); - match cycle[0] { - AstConvRequest::GetItemType(def_id) => { - err.note( - &format!("the cycle begins when processing `{}`...", - tcx.item_path_str(def_id))); - } - AstConvRequest::EnsureSuperPredicates(def_id) => { - err.note( - &format!("the cycle begins when computing the supertraits of `{}`...", - tcx.item_path_str(def_id))); - } - AstConvRequest::GetTypeParameterBounds(id) => { - err.note( - &format!("the cycle begins when computing the bounds \ - for type parameter `{}`...", - ::ty_param_name(tcx, id))); - } - } - - for request in &cycle[1..] { - match *request { - AstConvRequest::GetItemType(def_id) => { - err.note( - &format!("...which then requires processing `{}`...", - tcx.item_path_str(def_id))); + let describe = |query: ty::maps::Query| { + match query { + ty::maps::Query::ty(def_id) => { + format!("processing `{}`", tcx.item_path_str(def_id)) } - AstConvRequest::EnsureSuperPredicates(def_id) => { - err.note( - &format!("...which then requires computing the supertraits of `{}`...", - tcx.item_path_str(def_id))); + ty::maps::Query::super_predicates(def_id) => { + format!("computing the supertraits of `{}`", + tcx.item_path_str(def_id)) } - AstConvRequest::GetTypeParameterBounds(id) => { - err.note( - &format!("...which then requires computing the bounds \ - for type parameter `{}`...", - ::ty_param_name(tcx, id))); + ty::maps::Query::type_param_predicates(def_id) => { + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + format!("the cycle begins when computing the bounds \ + for type parameter `{}`", + ::ty_param_name(tcx, id)) } + query => span_bug!(span, "unexpected `{:?}`", query) } - } + }; - match cycle[0] { - AstConvRequest::GetItemType(def_id) => { - err.note( - &format!("...which then again requires processing `{}`, completing the cycle.", - tcx.item_path_str(def_id))); - } - AstConvRequest::EnsureSuperPredicates(def_id) => { - err.note( - &format!("...which then again requires computing the supertraits of `{}`, \ - completing the cycle.", - tcx.item_path_str(def_id))); - } - AstConvRequest::GetTypeParameterBounds(id) => { - err.note( - &format!("...which then again requires computing the bounds \ - for type parameter `{}`, completing the cycle.", - ::ty_param_name(tcx, id))); - } + err.note(&format!("the cycle begins when {}...", + describe(cycle[0]))); + + for &query in &cycle[1..] { + err.note(&format!("...which then requires {}...", + describe(query))); } + + err.note(&format!("...which then again requires {}, completing the cycle.", + describe(cycle[0]))); + err.emit(); } /// Ensure that the (transitive) super predicates for /// `trait_def_id` are available. This will report a cycle error /// if a trait `X` (transitively) extends itself in some form. - fn ensure_super_predicates(&self, span: Span, trait_def_id: DefId) - -> Result<(), ErrorReported> + fn ensure_super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + span: Span, + trait_def_id: DefId) + -> Result<(), ErrorReported> { - self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || { - let def_ids = ensure_super_predicates_step(self, trait_def_id); + cycle_check(tcx, span, ty::maps::Query::super_predicates(trait_def_id), || { + let def_ids = ensure_super_predicates_step(tcx, trait_def_id); for def_id in def_ids { - self.ensure_super_predicates(span, def_id)?; + ensure_super_predicates(tcx, span, def_id)?; } Ok(()) }) } -} impl<'a,'tcx> ItemCtxt<'a,'tcx> { fn to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { @@ -358,27 +323,27 @@ impl<'a,'tcx> ItemCtxt<'a,'tcx> { } impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.ccx.tcx } + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx } fn ast_ty_to_ty_cache(&self) -> &RefCell>> { - &self.ccx.ast_ty_to_ty_cache + &self.tcx.ast_ty_to_ty_cache } fn get_generics(&self, id: DefId) -> &'tcx ty::Generics { - generics_of_def_id(self.ccx, id) + generics_of_def_id(self.tcx, id) } fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx> { - self.ccx.cycle_check(span, AstConvRequest::GetItemType(id), || { - Ok(type_of_def_id(self.ccx, id)) - }).unwrap_or(self.ccx.tcx.types.err) + cycle_check(self.tcx, span, ty::maps::Query::ty(id), || { + Ok(type_of_def_id(self.tcx, id)) + }).unwrap_or(self.tcx.types.err) } fn get_trait_def(&self, def_id: DefId) -> &'tcx ty::TraitDef { - let tcx = self.ccx.tcx; + let tcx = self.tcx; if let Some(trait_id) = tcx.hir.as_local_node_id(def_id) { - trait_def_of_item(self.ccx, tcx.hir.expect_item(trait_id)) + trait_def_of_item(self.tcx, tcx.hir.expect_item(trait_id)) } else { tcx.lookup_trait_def(def_id) } @@ -392,7 +357,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { debug!("ensure_super_predicates(trait_def_id={:?})", trait_def_id); - self.ccx.ensure_super_predicates(span, trait_def_id) + ensure_super_predicates(self.tcx, span, trait_def_id) } fn get_type_parameter_bounds(&self, @@ -400,8 +365,9 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { node_id: ast::NodeId) -> Result>, ErrorReported> { - self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || { - let v = self.ccx.get_type_parameter_bounds(self.item_def_id, node_id) + let def_id = self.tcx.hir.local_def_id(node_id); + cycle_check(self.tcx, span, ty::maps::Query::type_param_predicates(def_id), || { + let v = get_type_parameter_bounds(self.tcx, self.item_def_id, node_id) .into_iter() .filter_map(|p| p.to_opt_poly_trait_ref()) .collect(); @@ -460,11 +426,10 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } } -impl<'a, 'tcx> CrateCtxt<'a, 'tcx> { - fn get_type_parameter_bounds(&self, - item_def_id: DefId, - param_id: ast::NodeId) - -> Vec> + fn get_type_parameter_bounds<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_def_id: DefId, + param_id: ast::NodeId) + -> Vec> { use rustc::hir::map::*; use rustc::hir::*; @@ -473,9 +438,8 @@ impl<'a, 'tcx> CrateCtxt<'a, 'tcx> { // written inline like `` or in a where clause like // `where T:Foo`. - let tcx = self.tcx; let param_owner_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, param_id)); - let generics = generics_of_def_id(self, param_owner_def_id); + let generics = generics_of_def_id(tcx, param_owner_def_id); let index = generics.type_param_to_index[&tcx.hir.local_def_id(param_id).index]; let ty = tcx.mk_param(index, ::ty_param_name(tcx, param_id)); @@ -483,11 +447,11 @@ impl<'a, 'tcx> CrateCtxt<'a, 'tcx> { let parent = if item_def_id == param_owner_def_id { None } else { - generics_of_def_id(self, item_def_id).parent + generics_of_def_id(tcx, item_def_id).parent }; let mut results = parent.map_or(vec![], |def_id| { - self.get_type_parameter_bounds(def_id, param_id) + get_type_parameter_bounds(tcx, def_id, param_id) }); let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); @@ -519,7 +483,7 @@ impl<'a, 'tcx> CrateCtxt<'a, 'tcx> { if param_id == item_node_id { results.push(ty::TraitRef { def_id: item_def_id, - substs: mk_item_substs(self, item_def_id) + substs: mk_item_substs(tcx, item_def_id) }.to_predicate()); } generics @@ -538,11 +502,10 @@ impl<'a, 'tcx> CrateCtxt<'a, 'tcx> { _ => return results }; - let icx = self.icx(item_def_id); + let icx = ItemCtxt::new(tcx, item_def_id); results.extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); results } -} impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { /// Find bounds from hir::Generics. This requires scanning through the @@ -570,7 +533,7 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { hir::WherePredicate::BoundPredicate(ref bp) => Some(bp), _ => None }) - .filter(|bp| is_param(self.ccx.tcx, &bp.bounded_ty, param_id)) + .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id)) .flat_map(|bp| bp.bounds.iter()) .flat_map(|b| predicates_from_bound(self, ty, b)); @@ -600,31 +563,33 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_field<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, field: &hir::StructField, ty_f: &'tcx ty::FieldDef) { - generics_of_def_id(ccx, ty_f.did); - let tt = ccx.icx(ty_f.did).to_ty(&field.ty); - ccx.tcx.maps.ty.borrow_mut().insert(ty_f.did, tt); - ccx.tcx.maps.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { - parent: Some(ccx.tcx.hir.get_parent_did(field.id)), + generics_of_def_id(tcx, ty_f.did); + let tt = ItemCtxt::new(tcx, ty_f.did).to_ty(&field.ty); + tcx.maps.ty.borrow_mut().insert(ty_f.did, tt); + tcx.maps.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { + parent: Some(tcx.hir.get_parent_did(field.id)), predicates: vec![] }); } -fn convert_method(ccx: &CrateCtxt, id: ast::NodeId, sig: &hir::MethodSig) { - let def_id = ccx.tcx.hir.local_def_id(id); +fn convert_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: ast::NodeId, + sig: &hir::MethodSig) { + let def_id = tcx.hir.local_def_id(id); - let fty = AstConv::ty_of_fn(&ccx.icx(def_id), sig.unsafety, sig.abi, &sig.decl); - let substs = mk_item_substs(ccx, def_id); - let fty = ccx.tcx.mk_fn_def(def_id, substs, fty); - ccx.tcx.maps.ty.borrow_mut().insert(def_id, fty); + let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), sig.unsafety, sig.abi, &sig.decl); + let substs = mk_item_substs(tcx, def_id); + let fty = tcx.mk_fn_def(def_id, substs, fty); + tcx.maps.ty.borrow_mut().insert(def_id, fty); - ty_generic_predicates(ccx, def_id, &sig.generics); + ty_generic_predicates(tcx, def_id, &sig.generics); } -fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, container: AssociatedItemContainer, id: ast::NodeId, ty: ty::Ty<'tcx>) @@ -633,12 +598,12 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, parent: Some(container.id()), predicates: vec![] }; - let def_id = ccx.tcx.hir.local_def_id(id); - ccx.tcx.maps.predicates.borrow_mut().insert(def_id, predicates); - ccx.tcx.maps.ty.borrow_mut().insert(def_id, ty); + let def_id = tcx.hir.local_def_id(id); + tcx.maps.predicates.borrow_mut().insert(def_id, predicates); + tcx.maps.ty.borrow_mut().insert(def_id, ty); } -fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_associated_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, container: AssociatedItemContainer, id: ast::NodeId, ty: Option>) @@ -647,18 +612,18 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, parent: Some(container.id()), predicates: vec![] }; - let def_id = ccx.tcx.hir.local_def_id(id); - ccx.tcx.maps.predicates.borrow_mut().insert(def_id, predicates); + let def_id = tcx.hir.local_def_id(id); + tcx.maps.predicates.borrow_mut().insert(def_id, predicates); if let Some(ty) = ty { - ccx.tcx.maps.ty.borrow_mut().insert(def_id, ty); + tcx.maps.ty.borrow_mut().insert(def_id, ty); } } -fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, - span: Span, - generics: &hir::Generics, - thing: &'static str) { +fn ensure_no_ty_param_bounds(tcx: TyCtxt, + span: Span, + generics: &hir::Generics, + thing: &'static str) { let mut warn = false; for ty_param in generics.ty_params.iter() { @@ -687,33 +652,32 @@ fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, // eventually accept these, but it will not be // part of this PR. Still, convert to warning to // make bootstrapping easier. - span_warn!(ccx.tcx.sess, span, E0122, + span_warn!(tcx.sess, span, E0122, "trait bounds are not (yet) enforced \ in {} definitions", thing); } } -fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { - let tcx = ccx.tcx; +fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { debug!("convert: item {} with id {}", it.name, it.id); - let def_id = ccx.tcx.hir.local_def_id(it.id); - let icx = ccx.icx(def_id); + let def_id = tcx.hir.local_def_id(it.id); + let icx = ItemCtxt::new(tcx, def_id); match it.node { // These don't define types. hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => { } hir::ItemForeignMod(ref foreign_mod) => { for item in &foreign_mod.items { - convert_foreign_item(ccx, item); + convert_foreign_item(tcx, item); } } hir::ItemEnum(ref enum_definition, _) => { - generics_of_def_id(ccx, def_id); - predicates_of_item(ccx, it); - let ty = type_of_def_id(ccx, def_id); - convert_enum_variant_types(ccx, - tcx.lookup_adt_def(ccx.tcx.hir.local_def_id(it.id)), + generics_of_def_id(tcx, def_id); + predicates_of_item(tcx, it); + let ty = type_of_def_id(tcx, def_id); + convert_enum_variant_types(tcx, + tcx.lookup_adt_def(tcx.hir.local_def_id(it.id)), ty, &enum_definition.variants); }, @@ -725,157 +689,151 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.record_trait_has_default_impl(trait_ref.def_id); - tcx.maps.impl_trait_ref.borrow_mut().insert(ccx.tcx.hir.local_def_id(it.id), + tcx.maps.impl_trait_ref.borrow_mut().insert(tcx.hir.local_def_id(it.id), Some(trait_ref)); } hir::ItemImpl(.., ref opt_trait_ref, _, _) => { - generics_of_def_id(ccx, def_id); - let selfty = type_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); + let selfty = type_of_def_id(tcx, def_id); let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) }); tcx.maps.impl_trait_ref.borrow_mut().insert(def_id, trait_ref); - predicates_of_item(ccx, it); + predicates_of_item(tcx, it); }, hir::ItemTrait(..) => { - generics_of_def_id(ccx, def_id); - trait_def_of_item(ccx, it); + generics_of_def_id(tcx, def_id); + trait_def_of_item(tcx, it); let _: Result<(), ErrorReported> = // any error is already reported, can ignore - ccx.ensure_super_predicates(it.span, def_id); - predicates_of_item(ccx, it); + ensure_super_predicates(tcx, it.span, def_id); + predicates_of_item(tcx, it); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { - generics_of_def_id(ccx, def_id); - predicates_of_item(ccx, it); - let ty = type_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); + predicates_of_item(tcx, it); + let ty = type_of_def_id(tcx, def_id); let variant = tcx.lookup_adt_def(def_id).struct_variant(); for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) { - convert_field(ccx, f, ty_f) + convert_field(tcx, f, ty_f) } if !struct_def.is_struct() { - convert_variant_ctor(ccx, struct_def.id(), variant, ty); + convert_variant_ctor(tcx, struct_def.id(), variant, ty); } }, hir::ItemTy(_, ref generics) => { - ensure_no_ty_param_bounds(ccx, it.span, generics, "type"); - generics_of_def_id(ccx, def_id); - predicates_of_item(ccx, it); - type_of_def_id(ccx, def_id); + ensure_no_ty_param_bounds(tcx, it.span, generics, "type"); + generics_of_def_id(tcx, def_id); + predicates_of_item(tcx, it); + type_of_def_id(tcx, def_id); }, _ => { - generics_of_def_id(ccx, def_id); - predicates_of_item(ccx, it); - type_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); + predicates_of_item(tcx, it); + type_of_def_id(tcx, def_id); }, } } -fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) { - let tcx = ccx.tcx; - +fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item: &hir::TraitItem) { // we can lookup details about the trait because items are visited // before trait-items let trait_def_id = tcx.hir.get_parent_did(trait_item.id); - let def_id = ccx.tcx.hir.local_def_id(trait_item.id); + let def_id = tcx.hir.local_def_id(trait_item.id); match trait_item.node { hir::TraitItemKind::Const(ref ty, _) => { - generics_of_def_id(ccx, def_id); - let ty = ccx.icx(def_id).to_ty(&ty); - convert_associated_const(ccx, + generics_of_def_id(tcx, def_id); + let ty = ItemCtxt::new(tcx, def_id).to_ty(&ty); + convert_associated_const(tcx, TraitContainer(trait_def_id), trait_item.id, ty); } hir::TraitItemKind::Type(_, ref opt_ty) => { - generics_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); - let typ = opt_ty.as_ref().map(|ty| ccx.icx(def_id).to_ty(&ty)); + let typ = opt_ty.as_ref().map(|ty| ItemCtxt::new(tcx, def_id).to_ty(&ty)); - convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ); + convert_associated_type(tcx, TraitContainer(trait_def_id), trait_item.id, typ); } hir::TraitItemKind::Method(ref sig, _) => { - convert_method(ccx, trait_item.id, sig); + convert_method(tcx, trait_item.id, sig); } } } -fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { - let tcx = ccx.tcx; - +fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::ImplItem) { // we can lookup details about the impl because items are visited // before impl-items let impl_def_id = tcx.hir.get_parent_did(impl_item.id); - let def_id = ccx.tcx.hir.local_def_id(impl_item.id); + let def_id = tcx.hir.local_def_id(impl_item.id); match impl_item.node { hir::ImplItemKind::Const(ref ty, _) => { - generics_of_def_id(ccx, def_id); - let ty = ccx.icx(def_id).to_ty(&ty); - convert_associated_const(ccx, + generics_of_def_id(tcx, def_id); + let ty = ItemCtxt::new(tcx, def_id).to_ty(&ty); + convert_associated_const(tcx, ImplContainer(impl_def_id), impl_item.id, ty); } hir::ImplItemKind::Type(ref ty) => { - generics_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); if tcx.impl_trait_ref(impl_def_id).is_none() { span_err!(tcx.sess, impl_item.span, E0202, "associated types are not allowed in inherent impls"); } - let typ = ccx.icx(def_id).to_ty(ty); + let typ = ItemCtxt::new(tcx, def_id).to_ty(ty); - convert_associated_type(ccx, ImplContainer(impl_def_id), impl_item.id, Some(typ)); + convert_associated_type(tcx, ImplContainer(impl_def_id), impl_item.id, Some(typ)); } hir::ImplItemKind::Method(ref sig, _) => { - convert_method(ccx, impl_item.id, sig); + convert_method(tcx, impl_item.id, sig); } } } -fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor_id: ast::NodeId, variant: &'tcx ty::VariantDef, ty: Ty<'tcx>) { - let tcx = ccx.tcx; let def_id = tcx.hir.local_def_id(ctor_id); - generics_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); let ctor_ty = match variant.ctor_kind { CtorKind::Fictive | CtorKind::Const => ty, CtorKind::Fn => { let inputs = variant.fields.iter().map(|field| tcx.item_type(field.did)); - let substs = mk_item_substs(ccx, def_id); + let substs = mk_item_substs(tcx, def_id); tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: abi::Abi::Rust, - sig: ty::Binder(ccx.tcx.mk_fn_sig(inputs, ty, false)) + sig: ty::Binder(tcx.mk_fn_sig(inputs, ty, false)) })) } }; tcx.maps.ty.borrow_mut().insert(def_id, ctor_ty); tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { - parent: Some(ccx.tcx.hir.get_parent_did(ctor_id)), + parent: Some(tcx.hir.get_parent_did(ctor_id)), predicates: vec![] }); } -fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def: &'tcx ty::AdtDef, ty: Ty<'tcx>, variants: &[hir::Variant]) { - let tcx = ccx.tcx; let repr_hints = tcx.lookup_repr_hints(def.did); let repr_type = tcx.enum_repr_type(repr_hints.get(0)); let initial = repr_type.initial_discriminant(tcx); @@ -885,7 +843,7 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) { let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr()); prev_discr = Some(if let Some(e) = variant.node.disr_expr { - let result = evaluate_disr_expr(ccx, repr_type, e); + let result = evaluate_disr_expr(tcx, repr_type, e); let expr_did = tcx.hir.local_def_id(e.node_id); tcx.maps.monomorphic_const_eval.borrow_mut() @@ -906,28 +864,28 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }.unwrap_or(wrapped_discr)); for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) { - convert_field(ccx, f, ty_f) + convert_field(tcx, f, ty_f) } // Convert the ctor, if any. This also registers the variant as // an item. - convert_variant_ctor(ccx, variant.node.data.id(), ty_variant, ty); + convert_variant_ctor(tcx, variant.node.data.id(), ty_variant, ty); } } -fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, name: ast::Name, discr: ty::VariantDiscr, def: &hir::VariantData) -> ty::VariantDef { let mut seen_fields: FxHashMap = FxHashMap(); - let node_id = ccx.tcx.hir.as_local_node_id(did).unwrap(); + let node_id = tcx.hir.as_local_node_id(did).unwrap(); let fields = def.fields().iter().map(|f| { - let fid = ccx.tcx.hir.local_def_id(f.id); + let fid = tcx.hir.local_def_id(f.id); let dup_span = seen_fields.get(&f.name).cloned(); if let Some(prev_span) = dup_span { - struct_span_err!(ccx.tcx.sess, f.span, E0124, + struct_span_err!(tcx.sess, f.span, E0124, "field `{}` is already declared", f.name) .span_label(f.span, &"field already declared") @@ -940,7 +898,7 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty::FieldDef { did: fid, name: f.name, - vis: ty::Visibility::from_hir(&f.vis, node_id, ccx.tcx) + vis: ty::Visibility::from_hir(&f.vis, node_id, tcx) } }).collect(); ty::VariantDef { @@ -952,56 +910,58 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } -fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_struct_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item, def: &hir::VariantData) -> &'tcx ty::AdtDef { - let did = ccx.tcx.hir.local_def_id(it.id); + let did = tcx.hir.local_def_id(it.id); // Use separate constructor id for unit/tuple structs and reuse did for braced structs. - let ctor_id = if !def.is_struct() { Some(ccx.tcx.hir.local_def_id(def.id())) } else { None }; - let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name, + let ctor_id = if !def.is_struct() { Some(tcx.hir.local_def_id(def.id())) } else { None }; + let variants = vec![convert_struct_variant(tcx, ctor_id.unwrap_or(did), it.name, ty::VariantDiscr::Relative(0), def)]; - let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants, - ReprOptions::new(&ccx.tcx, did)); + let adt = tcx.alloc_adt_def(did, AdtKind::Struct, variants, + ReprOptions::new(tcx, did)); if let Some(ctor_id) = ctor_id { // Make adt definition available through constructor id as well. - ccx.tcx.maps.adt_def.borrow_mut().insert(ctor_id, adt); + tcx.maps.adt_def.borrow_mut().insert(ctor_id, adt); } - ccx.tcx.maps.adt_def.borrow_mut().insert(did, adt); + tcx.maps.adt_def.borrow_mut().insert(did, adt); adt } -fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_union_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item, def: &hir::VariantData) -> &'tcx ty::AdtDef { - let did = ccx.tcx.hir.local_def_id(it.id); - let variants = vec![convert_struct_variant(ccx, did, it.name, + let did = tcx.hir.local_def_id(it.id); + let variants = vec![convert_struct_variant(tcx, did, it.name, ty::VariantDiscr::Relative(0), def)]; - let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did)); - ccx.tcx.maps.adt_def.borrow_mut().insert(did, adt); + let adt = tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(tcx, did)); + tcx.maps.adt_def.borrow_mut().insert(did, adt); adt } -fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId) +fn evaluate_disr_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + repr_ty: attr::IntType, + body: hir::BodyId) -> Result { - let e = &ccx.tcx.hir.body(body).value; - debug!("disr expr, checking {}", ccx.tcx.hir.node_to_pretty_string(e.id)); + let e = &tcx.hir.body(body).value; + debug!("disr expr, checking {}", tcx.hir.node_to_pretty_string(e.id)); - let ty_hint = repr_ty.to_ty(ccx.tcx); + let ty_hint = repr_ty.to_ty(tcx); let print_err = |cv: ConstVal| { - struct_span_err!(ccx.tcx.sess, e.span, E0079, "mismatched types") + struct_span_err!(tcx.sess, e.span, E0079, "mismatched types") .note_expected_found(&"type", &ty_hint, &format!("{}", cv.description())) .span_label(e.span, &format!("expected '{}' type", ty_hint)) .emit(); }; let hint = UncheckedExprHint(ty_hint); - match ConstContext::new(ccx.tcx, body).eval(e, hint) { + match ConstContext::new(tcx, body).eval(e, hint) { Ok(ConstVal::Integral(i)) => { // FIXME: eval should return an error if the hint does not match the type of the body. // i.e. eventually the match below would not exist. @@ -1032,19 +992,18 @@ fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId // so we need to report the real error Err(err) => { let mut diag = report_const_eval_err( - ccx.tcx, &err, e.span, "enum discriminant"); + tcx, &err, e.span, "enum discriminant"); diag.emit(); Err(()) } } } -fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_enum_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item, def: &hir::EnumDef) -> &'tcx ty::AdtDef { - let tcx = ccx.tcx; let mut distance_from_explicit = 0; let variants = def.variants.iter().map(|v| { let did = tcx.hir.local_def_id(v.node.data.id()); @@ -1056,11 +1015,11 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; distance_from_explicit += 1; - convert_struct_variant(ccx, did, v.node.name, discr, &v.node.data) + convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data) }).collect(); let did = tcx.hir.local_def_id(it.id); - let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did)); + let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(tcx, did)); tcx.maps.adt_def.borrow_mut().insert(did, adt); adt } @@ -1072,12 +1031,10 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /// above. Returns a list of trait def-ids that must be ensured as /// well to guarantee that the transitive superpredicates are /// converted. -fn ensure_super_predicates_step(ccx: &CrateCtxt, - trait_def_id: DefId) - -> Vec +fn ensure_super_predicates_step<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_def_id: DefId) + -> Vec { - let tcx = ccx.tcx; - debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id); let trait_node_id = if let Some(n) = tcx.hir.as_local_node_id(trait_def_id) { @@ -1093,7 +1050,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, let superpredicates = tcx.maps.super_predicates.borrow().get(&trait_def_id).cloned(); let superpredicates = superpredicates.unwrap_or_else(|| { - let item = match ccx.tcx.hir.get(trait_node_id) { + let item = match tcx.hir.get(trait_node_id) { hir_map::NodeItem(item) => item, _ => bug!("trait_node_id {} is not an item", trait_node_id) }; @@ -1104,7 +1061,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, "ensure_super_predicates_step invoked on non-trait"), }; - let icx = ccx.icx(trait_def_id); + let icx = ItemCtxt::new(tcx, trait_def_id); // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. let self_param_ty = tcx.mk_self_type(); @@ -1146,8 +1103,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, def_ids } -fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef { - let tcx = ccx.tcx; +fn trait_def_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef { let def_id = tcx.hir.local_def_id(it.id); tcx.maps.trait_def.memoize(def_id, || { @@ -1173,10 +1129,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'t }) } -fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn generics_of_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Generics { - let tcx = ccx.tcx; let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { id } else { @@ -1284,7 +1239,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut parent_has_self = false; let mut own_start = has_self as u32; let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| { - let generics = generics_of_def_id(ccx, def_id); + let generics = generics_of_def_id(tcx, def_id); assert_eq!(has_self, false); parent_has_self = generics.has_self; own_start = generics.count() as u32; @@ -1294,7 +1249,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); let regions = early_lifetimes.enumerate().map(|(i, l)| { - let issue_32330 = ccx.tcx.named_region_map.issue_32330 + let issue_32330 = tcx.named_region_map.issue_32330 .get(&l.lifetime.id) .cloned(); ty::RegionParameterDef { @@ -1372,24 +1327,24 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) } -fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn type_of_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { - let node_id = if let Some(id) = ccx.tcx.hir.as_local_node_id(def_id) { + let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { id } else { - return ccx.tcx.item_type(def_id); + return tcx.item_type(def_id); }; - ccx.tcx.maps.ty.memoize(def_id, || { + tcx.maps.ty.memoize(def_id, || { use rustc::hir::map::*; use rustc::hir::*; // Alway bring in generics, as computing the type needs them. - generics_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); - let icx = ccx.icx(def_id); + let icx = ItemCtxt::new(tcx, def_id); - match ccx.tcx.hir.get(node_id) { + match tcx.hir.get(node_id) { NodeItem(item) => { match item.node { ItemStatic(ref t, ..) | ItemConst(ref t, _) | @@ -1398,23 +1353,23 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } ItemFn(ref decl, unsafety, _, abi, _, _) => { let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); - let substs = mk_item_substs(ccx, def_id); - ccx.tcx.mk_fn_def(def_id, substs, tofd) + let substs = mk_item_substs(tcx, def_id); + tcx.mk_fn_def(def_id, substs, tofd) } ItemEnum(ref ei, _) => { - let def = convert_enum_def(ccx, item, ei); - let substs = mk_item_substs(ccx, def_id); - ccx.tcx.mk_adt(def, substs) + let def = convert_enum_def(tcx, item, ei); + let substs = mk_item_substs(tcx, def_id); + tcx.mk_adt(def, substs) } ItemStruct(ref si, _) => { - let def = convert_struct_def(ccx, item, si); - let substs = mk_item_substs(ccx, def_id); - ccx.tcx.mk_adt(def, substs) + let def = convert_struct_def(tcx, item, si); + let substs = mk_item_substs(tcx, def_id); + tcx.mk_adt(def, substs) } ItemUnion(ref un, _) => { - let def = convert_union_def(ccx, item, un); - let substs = mk_item_substs(ccx, def_id); - ccx.tcx.mk_adt(def, substs) + let def = convert_union_def(tcx, item, un); + let substs = mk_item_substs(tcx, def_id); + tcx.mk_adt(def, substs) } ItemDefaultImpl(..) | ItemTrait(..) | @@ -1430,23 +1385,23 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } NodeForeignItem(foreign_item) => { - let abi = ccx.tcx.hir.get_foreign_abi(node_id); + let abi = tcx.hir.get_foreign_abi(node_id); match foreign_item.node { ForeignItemFn(ref fn_decl, _, _) => { - compute_type_of_foreign_fn_decl(ccx, def_id, fn_decl, abi) + compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } ForeignItemStatic(ref t, _) => icx.to_ty(t) } } NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { - ccx.tcx.mk_closure(def_id, Substs::for_item( - ccx.tcx, def_id, + tcx.mk_closure(def_id, Substs::for_item( + tcx, def_id, |def, _| { let region = def.to_early_bound_region_data(); - ccx.tcx.mk_region(ty::ReEarlyBound(region)) + tcx.mk_region(ty::ReEarlyBound(region)) }, - |def, _| ccx.tcx.mk_param_from_def(def) + |def, _| tcx.mk_param_from_def(def) )) } NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { @@ -1459,8 +1414,8 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) } -fn predicates_of_item(ccx: &CrateCtxt, it: &hir::Item) { - let def_id = ccx.tcx.hir.local_def_id(it.id); +fn predicates_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { + let def_id = tcx.hir.local_def_id(it.id); let no_generics = hir::Generics::empty(); let generics = match it.node { @@ -1474,19 +1429,19 @@ fn predicates_of_item(ccx: &CrateCtxt, it: &hir::Item) { _ => &no_generics }; - ty_generic_predicates(ccx, def_id, generics); + ty_generic_predicates(tcx, def_id, generics); } -fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn convert_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { // For reasons I cannot fully articulate, I do so hate the AST // map, and I regard each time that I use it as a personal and // moral failing, but at the moment it seems like the only // convenient way to extract the ABI. - ndm - let def_id = ccx.tcx.hir.local_def_id(it.id); - generics_of_def_id(ccx, def_id); - type_of_def_id(ccx, def_id); + let def_id = tcx.hir.local_def_id(it.id); + generics_of_def_id(tcx, def_id); + type_of_def_id(tcx, def_id); let no_generics = hir::Generics::empty(); let generics = match it.node { @@ -1494,7 +1449,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ForeignItemStatic(..) => &no_generics }; - ty_generic_predicates(ccx, def_id, generics); + ty_generic_predicates(tcx, def_id, generics); } // Is it marked with ?Sized @@ -1557,10 +1512,11 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( .filter(move |l| !tcx.named_region_map.late_bound.contains(&l.lifetime.id)) } -fn ty_generic_predicates(ccx: &CrateCtxt, def_id: DefId, ast_generics: &hir::Generics) { - let tcx = ccx.tcx; - let icx = ccx.icx(def_id); - let generics = generics_of_def_id(ccx, def_id); +fn ty_generic_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + ast_generics: &hir::Generics) { + let icx = ItemCtxt::new(tcx, def_id); + let generics = generics_of_def_id(tcx, def_id); let parent_count = generics.parent_count() as u32; let has_own_self = generics.has_self && parent_count == 0; @@ -1573,11 +1529,11 @@ fn ty_generic_predicates(ccx: &CrateCtxt, def_id: DefId, ast_generics: &hir::Gen hir::ItemTrait(.., ref items) => { (Some((ty::TraitRef { def_id: def_id, - substs: mk_item_substs(ccx, def_id) + substs: mk_item_substs(tcx, def_id) }, items)), None) } hir::ItemImpl(..) => { - let self_ty = type_of_def_id(ccx, def_id); + let self_ty = type_of_def_id(tcx, def_id); let trait_ref = tcx.impl_trait_ref(def_id); (None, Some((self_ty, trait_ref))) } @@ -1695,7 +1651,7 @@ fn ty_generic_predicates(ccx: &CrateCtxt, def_id: DefId, ast_generics: &hir::Gen let assoc_ty = tcx.mk_projection(self_trait_ref, trait_item.name); - let bounds = compute_bounds(&ccx.icx(def_id), + let bounds = compute_bounds(&ItemCtxt::new(tcx, def_id), assoc_ty, bounds, SizedByDefault::Yes, @@ -1809,24 +1765,24 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } fn compute_type_of_foreign_fn_decl<'a, 'tcx>( - ccx: &CrateCtxt<'a, 'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, decl: &hir::FnDecl, abi: abi::Abi) -> Ty<'tcx> { - let fty = AstConv::ty_of_fn(&ccx.icx(def_id), hir::Unsafety::Unsafe, abi, decl); + let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl); // feature gate SIMD types in FFI, since I (huonw) am not sure the // ABIs are handled at all correctly. if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic - && !ccx.tcx.sess.features.borrow().simd_ffi { + && !tcx.sess.features.borrow().simd_ffi { let check = |ast_ty: &hir::Ty, ty: ty::Ty| { if ty.is_simd() { - ccx.tcx.sess.struct_span_err(ast_ty.span, + tcx.sess.struct_span_err(ast_ty.span, &format!("use of SIMD type `{}` in FFI is highly experimental and \ may result in invalid code", - ccx.tcx.hir.node_to_pretty_string(ast_ty.id))) + tcx.hir.node_to_pretty_string(ast_ty.id))) .help("add #![feature(simd_ffi)] to the crate attributes to enable") .emit(); } @@ -1839,15 +1795,15 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = mk_item_substs(ccx, def_id); - ccx.tcx.mk_fn_def(def_id, substs, fty) + let substs = mk_item_substs(tcx, def_id); + tcx.mk_fn_def(def_id, substs, fty) } -fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn mk_item_substs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Substs<'tcx> { // FIXME(eddyb) Do this request from Substs::for_item in librustc. - generics_of_def_id(ccx, def_id); + generics_of_def_id(tcx, def_id); - Substs::identity_for_item(ccx.tcx, def_id) + Substs::identity_for_item(tcx, def_id) } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 3a19b3579d559..3df25825a71f6 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -23,14 +23,12 @@ use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::def_id::DefId; -use rustc::ty; +use rustc::ty::{self, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax_pos::Span; -use CrateCtxt; - /// Checks that all the type/lifetime parameters on an impl also /// appear in the trait ref or self-type (or are constrained by a /// where-clause). These rules are needed to ensure that, given a @@ -61,27 +59,27 @@ use CrateCtxt; /// impl<'a> Trait for Bar { type X = &'a i32; } /// ^ '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, // but it's one that we must perform earlier than the rest of // 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> { - ccx: &'a CrateCtxt<'a, 'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, } impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { hir::ItemImpl(.., ref generics, _, _, ref impl_item_refs) => { - let impl_def_id = self.ccx.tcx.hir.local_def_id(item.id); - enforce_impl_params_are_constrained(self.ccx, + let impl_def_id = self.tcx.hir.local_def_id(item.id); + enforce_impl_params_are_constrained(self.tcx, generics, impl_def_id, 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 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_def_id: DefId, impl_item_refs: &[hir::ImplItemRef]) { // Every lifetime used in an associated type must be constrained. - let impl_self_ty = ccx.tcx.item_type(impl_def_id); - let impl_generics = ccx.tcx.item_generics(impl_def_id); - let impl_predicates = ccx.tcx.item_predicates(impl_def_id); - let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id); + let impl_self_ty = tcx.item_type(impl_def_id); + let impl_generics = tcx.item_generics(impl_def_id); + let impl_predicates = tcx.item_predicates(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); 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) { let param_ty = ty::ParamTy::for_def(ty_param); if !input_parameters.contains(&ctp::Parameter::from(param_ty)) { - report_unused_parameter(ccx, param.span, "type", ¶m_ty.to_string()); + report_unused_parameter(tcx, param.span, "type", ¶m_ty.to_string()); } } // Disallow unconstrained lifetimes, but only if they appear in assoc types. 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| { - let item = ccx.tcx.associated_item(def_id); + let item = tcx.associated_item(def_id); item.kind == ty::AssociatedKind::Type && item.defaultness.has_value() }) .flat_map(|def_id| { - ctp::parameters_for(&ccx.tcx.item_type(def_id), true) + ctp::parameters_for(&tcx.item_type(def_id), true) }).collect(); for (ty_lifetime, lifetime) in impl_generics.regions.iter() .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(¶m) && // (*) !input_parameters.contains(¶m) { - report_unused_parameter(ccx, lifetime.lifetime.span, + report_unused_parameter(tcx, lifetime.lifetime.span, "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. } -fn report_unused_parameter(ccx: &CrateCtxt, +fn report_unused_parameter(tcx: TyCtxt, span: Span, kind: &str, name: &str) { struct_span_err!( - ccx.tcx.sess, span, E0207, + tcx.sess, span, E0207, "the {} parameter `{}` is not constrained by the \ impl trait, self type, or predicates", 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. -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]) { - let tcx = ccx.tcx; let mut seen_type_items = FxHashMap(); let mut seen_value_items = FxHashMap(); for impl_item_ref in impl_item_refs { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 03175782c38fd..ddd8d9259cc99 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -110,7 +110,7 @@ use hir::map as hir_map; use rustc::infer::InferOk; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; +use rustc::traits::{ObligationCause, ObligationCauseCode, Reveal}; use session::config; use util::common::time; @@ -120,9 +120,6 @@ use syntax::symbol::keywords; use syntax_pos::Span; use std::iter; -use std::cell::RefCell; -use util::nodemap::NodeMap; - // NB: This module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; @@ -141,27 +138,6 @@ pub struct TypeAndSubsts<'tcx> { pub ty: Ty<'tcx>, } -pub struct CrateCtxt<'a, 'tcx: 'a> { - ast_ty_to_ty_cache: RefCell>>, - - /// 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>, - - /// This stack is used to identify cycles in the user's source. - /// Note that these cycles can cross multiple items. - pub stack: RefCell>, - - 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>>>, -} - fn require_c_abi_if_variadic(tcx: TyCtxt, decl: &hir::FnDecl, 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>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - ccx.tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { match infcx.eq_types(false, &cause, expected, actual) { Ok(InferOk { 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, - main_id: ast::NodeId, - main_span: Span) { - let tcx = ccx.tcx; +fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + main_id: ast::NodeId, + main_span: Span) { let main_def_id = tcx.hir.local_def_id(main_id); let main_t = tcx.item_type(main_def_id); match main_t.sty { @@ -231,7 +206,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, match it.node { hir::ItemFn(.., ref generics, _) => { 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") .span_label(generics.span, &format!("main cannot have type parameters")) @@ -253,7 +228,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, })); require_same_types( - ccx, + tcx, &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, main_t); @@ -266,11 +241,10 @@ fn check_main_fn_ty(ccx: &CrateCtxt, } } -fn check_start_fn_ty(ccx: &CrateCtxt, - start_id: ast::NodeId, - start_span: Span) { - let tcx = ccx.tcx; - let start_def_id = ccx.tcx.hir.local_def_id(start_id); +fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + start_id: ast::NodeId, + start_span: Span) { + let start_def_id = tcx.hir.local_def_id(start_id); let start_t = tcx.item_type(start_def_id); match start_t.sty { ty::TyFnDef(..) => { @@ -308,7 +282,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, })); require_same_types( - ccx, + tcx, &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), se_ty, start_t); @@ -321,13 +295,12 @@ fn check_start_fn_ty(ccx: &CrateCtxt, } } -fn check_for_entry_fn(ccx: &CrateCtxt) { - let tcx = ccx.tcx; +fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let _task = tcx.dep_graph.in_task(DepNode::CheckEntryFn); if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() { match tcx.sess.entry_type.get() { - Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp), - Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp), + Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp), + Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp), Some(config::EntryNone) => {} 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>) - -> Result>, usize> { + -> Result<(), usize> { 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 // have valid types and not error tcx.sess.track_errors(|| { 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(|| { time(time_passes, "impl wf inference", || - impl_wf_check::impl_wf_check(&ccx)); + impl_wf_check::impl_wf_check(tcx)); })?; tcx.sess.track_errors(|| { 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_for_entry_fn(&ccx); + check_for_entry_fn(tcx); let err_count = tcx.sess.err_count(); if err_count == 0 { - Ok(ccx.ast_ty_to_ty_cache.into_inner()) + Ok(()) } else { Err(err_count) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index dc09fc2b8d3cc..cd94e3fd14a50 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1772,7 +1772,7 @@ impl Clean for hir::Ty { } TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => { 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 { def = Def::Trait(proj.trait_ref.def_id); } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5393e395bbe43..0a9db2c26464c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -15,10 +15,10 @@ use rustc::session::{self, config}; use rustc::hir::def_id::DefId; use rustc::hir::def::{Def, ExportMap}; 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::lint; -use rustc::util::nodemap::{FxHashMap, NodeMap}; +use rustc::util::nodemap::FxHashMap; use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; @@ -65,9 +65,6 @@ pub struct DocContext<'a, 'tcx: 'a> { /// Table node id of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell>, pub export_map: ExportMap, - - /// Table from HIR Ty nodes to their resolved Ty. - pub hir_ty_to_ty: NodeMap>, } impl<'a, 'tcx> DocContext<'a, 'tcx> { @@ -183,7 +180,7 @@ pub fn run_core(search_paths: SearchPaths, 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 // to the map from defid -> nodeid @@ -202,7 +199,6 @@ pub fn run_core(search_paths: SearchPaths, ty_substs: Default::default(), lt_substs: Default::default(), export_map: export_map, - hir_ty_to_ty: hir_ty_to_ty, }; debug!("crate: {:?}", tcx.hir.krate()); From 28f1cf4262074dfdb5f83a24cf81dbabf37a1d94 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 11 Feb 2017 19:26:13 +0200 Subject: [PATCH 08/17] rustc_typeck: don't use Result for get_type_parameter_bounds and ensure_super_predicates. --- src/librustc/dep_graph/dep_node.rs | 4 + src/librustc/diagnostics.rs | 17 ++ src/librustc/hir/map/mod.rs | 24 ++ src/librustc/lib.rs | 1 + src/librustc/ty/maps.rs | 97 ++++++- src/librustc/ty/mod.rs | 2 +- src/librustc_typeck/astconv.rs | 56 ++-- src/librustc_typeck/check/mod.rs | 43 +-- src/librustc_typeck/collect.rs | 257 ++++++------------ src/librustc_typeck/diagnostics.rs | 17 -- src/librustc_typeck/lib.rs | 25 -- .../cycle-projection-based-on-where-clause.rs | 1 + .../cycle-trait-supertrait-indirect.rs | 6 +- src/test/compile-fail/issue-12511.rs | 7 +- src/test/compile-fail/issue-20772.rs | 1 + src/test/compile-fail/issue-21177.rs | 3 +- 16 files changed, 266 insertions(+), 295 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 8da032f59353a..769c08a81efa6 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -109,6 +109,7 @@ pub enum DepNode { // predicates for an item wind up in `ItemSignature`). AssociatedItems(D), ItemSignature(D), + TypeParamPredicates((D, D)), SizedConstraint(D), AssociatedItemDefIds(D), InherentImpls(D), @@ -259,6 +260,9 @@ impl DepNode { TransInlinedItem(ref d) => op(d).map(TransInlinedItem), AssociatedItems(ref d) => op(d).map(AssociatedItems), ItemSignature(ref d) => op(d).map(ItemSignature), + TypeParamPredicates((ref item, ref param)) => { + Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param))))) + } SizedConstraint(ref d) => op(d).map(SizedConstraint), AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index cf51dad5142ee..458a774c95645 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1390,6 +1390,23 @@ error. To resolve it, add an `else` block having the same type as the `if` block. "##, +E0391: r##" +This error indicates that some types or traits depend on each other +and therefore cannot be constructed. + +The following example contains a circular dependency between two traits: + +```compile_fail,E0391 +trait FirstTrait : SecondTrait { + +} + +trait SecondTrait : FirstTrait { + +} +``` +"##, + E0398: r##" In Rust 1.3, the default object lifetime bounds are expected to change, as described in RFC #1156 [1]. You are getting a warning because the compiler diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 9f31b5b456b9f..13b786541c502 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -437,6 +437,30 @@ impl<'hir> Map<'hir> { self.local_def_id(self.body_owner(id)) } + pub fn ty_param_owner(&self, id: NodeId) -> NodeId { + match self.get(id) { + NodeItem(&Item { node: ItemTrait(..), .. }) => id, + NodeTyParam(_) => self.get_parent_node(id), + _ => { + bug!("ty_param_owner: {} not a type parameter", + self.node_to_string(id)) + } + } + } + + pub fn ty_param_name(&self, id: NodeId) -> Name { + match self.get(id) { + NodeItem(&Item { node: ItemTrait(..), .. }) => { + keywords::SelfType.name() + } + NodeTyParam(tp) => tp.name, + _ => { + bug!("ty_param_name: {} not a type parameter", + self.node_to_string(id)) + } + } + } + /// Get the attributes on the krate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d144f7575a2e2..60d03ccfe240d 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -39,6 +39,7 @@ #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(slice_patterns)] +#![feature(specialization)] #![feature(staged_api)] #![feature(unboxed_closures)] diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index aeb7a207c447e..dc87bb43c265d 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -20,6 +20,7 @@ use rustc_data_structures::indexed_vec::IndexVec; use std::cell::RefCell; use std::rc::Rc; use syntax::attr; +use syntax_pos::Span; trait Key { fn map_crate(&self) -> CrateNum; @@ -31,13 +32,105 @@ impl Key for DefId { } } +impl Key for (DefId, DefId) { + fn map_crate(&self) -> CrateNum { + self.0.krate + } +} + +trait Value<'tcx>: Sized { + fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self; +} + +impl<'tcx, T> Value<'tcx> for T { + default fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> T { + tcx.sess.abort_if_errors(); + bug!("Value::from_cycle_error called without errors"); + } +} + +impl<'tcx, T: Default> Value<'tcx> for T { + default fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> T { + T::default() + } +} + +impl<'tcx> Value<'tcx> for Ty<'tcx> { + fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { + tcx.types.err + } +} + +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + fn report_cycle(self, span: Span, cycle: &[(Span, Query)]) { + assert!(!cycle.is_empty()); + + let mut err = struct_span_err!(self.sess, span, E0391, + "unsupported cyclic reference between types/traits detected"); + err.span_label(span, &format!("cyclic reference")); + + err.span_note(cycle[0].0, &format!("the cycle begins when {}...", + cycle[0].1.describe(self))); + + for &(span, ref query) in &cycle[1..] { + err.span_note(span, &format!("...which then requires {}...", + query.describe(self))); + } + + err.note(&format!("...which then again requires {}, completing the cycle.", + cycle[0].1.describe(self))); + + err.emit(); + } + + pub fn cycle_check(self, span: Span, query: Query, compute: F) -> R + where F: FnOnce() -> R + { + { + let mut stack = self.maps.query_stack.borrow_mut(); + if let Some((i, _)) = stack.iter().enumerate().rev() + .find(|&(_, &(_, ref q))| *q == query) { + let cycle = &stack[i..]; + self.report_cycle(span, cycle); + return R::from_cycle_error(self.global_tcx()); + } + stack.push((span, query)); + } + + let result = compute(); + + self.maps.query_stack.borrow_mut().pop(); + result + } +} + +impl Query { + fn describe(&self, tcx: TyCtxt) -> String { + match *self { + Query::ty(def_id) => { + format!("processing `{}`", tcx.item_path_str(def_id)) + } + Query::super_predicates(def_id) => { + format!("computing the supertraits of `{}`", + tcx.item_path_str(def_id)) + } + Query::type_param_predicates((_, def_id)) => { + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + format!("computing the bounds for type parameter `{}`", + tcx.hir.ty_param_name(id)) + } + _ => bug!("unexpected `{:?}`", self) + } + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => { pub struct Maps<$tcx> { providers: IndexVec>, - pub query_stack: RefCell>, + pub query_stack: RefCell>, $($(#[$attr])* pub $name: RefCell>>),* } @@ -129,7 +222,7 @@ define_maps! { <'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) + pub type_param_predicates: TypeParamPredicates((DefId, DefId)) -> ty::GenericPredicates<'tcx>, pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 97476489a8adb..9d4e17138a042 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -669,7 +669,7 @@ impl Generics { } /// Bounds on generics. -#[derive(Clone)] +#[derive(Clone, Default)] pub struct GenericPredicates<'tcx> { pub parent: Option, pub predicates: Vec>, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cf93ef21f5d4a..ef0dcd4c774dd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -64,13 +64,12 @@ pub trait AstConv<'gcx, 'tcx> { /// Ensure that the super-predicates for the trait with the given /// id are available and also for the transitive set of /// super-predicates. - fn ensure_super_predicates(&self, span: Span, id: DefId) - -> Result<(), ErrorReported>; + fn ensure_super_predicates(&self, span: Span, id: DefId); /// Returns the set of bounds in scope for the type parameter with /// the given id. - fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId) - -> Result>, ErrorReported>; + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) + -> Vec>; /// Return an (optional) substitution to convert bound type parameters that /// are in scope into free ones. This function should only return Some @@ -599,7 +598,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Otherwise, we have to walk through the supertraits to find // those that do. - self.ensure_super_predicates(binding.span, trait_ref.def_id())?; + self.ensure_super_predicates(binding.span, trait_ref.def_id()); let candidates = traits::supertraits(tcx, trait_ref.clone()) @@ -685,10 +684,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }) }); - // ensure the super predicates and stop if we encountered an error - if self.ensure_super_predicates(span, principal.def_id()).is_err() { - return tcx.types.err; - } + // ensure the super predicates + self.ensure_super_predicates(span, principal.def_id()); // check that there are no gross object safety violations, // most importantly, that the supertraits don't contain Self, @@ -774,29 +771,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } // Search for a bound on a type parameter which includes the associated item - // given by assoc_name. ty_param_node_id is the node id for the type parameter - // (which might be `Self`, but only if it is the `Self` of a trait, not an - // impl). This function will fail if there are no suitable bounds or there is + // given by `assoc_name`. `ty_param_def_id` is the `DefId` for the type parameter + // This function will fail if there are no suitable bounds or there is // any ambiguity. fn find_bound_for_assoc_item(&self, - ty_param_node_id: ast::NodeId, - ty_param_name: ast::Name, + ty_param_def_id: DefId, assoc_name: ast::Name, span: Span) -> Result, ErrorReported> { let tcx = self.tcx(); - let bounds = match self.get_type_parameter_bounds(span, ty_param_node_id) { - Ok(v) => v, - Err(ErrorReported) => { - return Err(ErrorReported); - } - }; + let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id) + .into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect(); - // Ensure the super predicates and stop if we encountered an error. - if bounds.iter().any(|b| self.ensure_super_predicates(span, b.def_id()).is_err()) { - return Err(ErrorReported); + // Ensure the super predicates. + for b in &bounds { + self.ensure_super_predicates(span, b.def_id()); } // Check that there is exactly one way to find an associated type with the @@ -805,8 +796,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { traits::transitive_bounds(tcx, &bounds) .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name)); + let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap(); + let param_name = tcx.hir.ty_param_name(param_node_id); self.one_bound_for_assoc_type(suitable_bounds, - &ty_param_name.as_str(), + ¶m_name.as_str(), &assoc_name.as_str(), span) } @@ -914,9 +907,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_ref }; - if self.ensure_super_predicates(span, trait_ref.def_id).is_err() { - return (tcx.types.err, Def::Err); - } + self.ensure_super_predicates(span, trait_ref.def_id); let candidates = traits::supertraits(tcx, ty::Binder(trait_ref)) @@ -933,12 +924,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } (&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) | (&ty::TyParam(_), Def::TyParam(param_did)) => { - let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap(); - let param_name = ::ty_param_name(tcx, param_node_id); - match self.find_bound_for_assoc_item(param_node_id, - param_name, - assoc_name, - span) { + match self.find_bound_for_assoc_item(param_did, assoc_name, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } @@ -1375,9 +1361,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { existential_predicates); if let Some(principal) = existential_predicates.principal() { - if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) { - return Some(tcx.mk_region(ty::ReStatic)); - } + self.ensure_super_predicates(span, principal.def_id()); } // No explicit region bound specified. Therefore, examine trait diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d52516e0ae500..d2cd766fdf009 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,7 +91,7 @@ use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; -use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPolyTraitRef}; +use rustc::ty::{self, Ty, TyCtxt, Visibility}; use rustc::ty::{MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; @@ -1366,44 +1366,31 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { self.tcx().lookup_trait_def(id) } - fn ensure_super_predicates(&self, _: Span, _: DefId) -> Result<(), ErrorReported> { + fn ensure_super_predicates(&self, _: Span, _: DefId) { // all super predicates are ensured during collect pass - Ok(()) } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { Some(&self.parameter_environment.free_substs) } - fn get_type_parameter_bounds(&self, - _: Span, - node_id: ast::NodeId) - -> Result>, ErrorReported> + fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) + -> Vec> { let tcx = self.tcx; - let item_id = ::ty_param_owner(tcx, node_id); + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item_id = tcx.hir.ty_param_owner(node_id); let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.item_generics(item_def_id); - let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; - let r = self.parameter_environment - .caller_bounds - .iter() - .filter_map(|predicate| { - match *predicate { - ty::Predicate::Trait(ref data) => { - if data.0.self_ty().is_param(index) { - Some(data.to_poly_trait_ref()) - } else { - None - } - } - _ => { - None - } - } - }) - .collect(); - Ok(r) + let index = generics.type_param_to_index[&def_id.index]; + self.parameter_environment.caller_bounds.iter().filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref data) => { + data.0.self_ty().is_param(index) + } + _ => false + } + }).cloned().collect() } fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 95fd123b7df4c..ff9c1cc7d3656 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -70,7 +70,7 @@ use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContai use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; use rustc::dep_graph::DepNode; -use util::common::{ErrorReported, MemoizationMap}; +use util::common::MemoizationMap; use util::nodemap::{NodeMap, FxHashMap}; use rustc_const_math::ConstInt; @@ -80,7 +80,7 @@ use std::collections::BTreeMap; use syntax::{abi, ast, attr}; use syntax::symbol::{Symbol, keywords}; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::{self, map as hir_map}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -231,91 +231,6 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { } } - fn cycle_check(tcx: TyCtxt, - span: Span, - query: ty::maps::Query, - code: F) - -> Result - where F: FnOnce() -> Result - { - { - let mut stack = tcx.maps.query_stack.borrow_mut(); - if let Some((i, _)) = stack.iter().enumerate().rev().find(|&(_, q)| *q == query) { - let cycle = &stack[i..]; - report_cycle(tcx, span, cycle); - return Err(ErrorReported); - } - stack.push(query); - } - - let result = code(); - - tcx.maps.query_stack.borrow_mut().pop(); - result - } - - fn report_cycle(tcx: TyCtxt, - span: Span, - cycle: &[ty::maps::Query]) - { - assert!(!cycle.is_empty()); - - let mut err = struct_span_err!(tcx.sess, span, E0391, - "unsupported cyclic reference between types/traits detected"); - err.span_label(span, &format!("cyclic reference")); - - let describe = |query: ty::maps::Query| { - match query { - ty::maps::Query::ty(def_id) => { - format!("processing `{}`", tcx.item_path_str(def_id)) - } - ty::maps::Query::super_predicates(def_id) => { - format!("computing the supertraits of `{}`", - tcx.item_path_str(def_id)) - } - ty::maps::Query::type_param_predicates(def_id) => { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - format!("the cycle begins when computing the bounds \ - for type parameter `{}`", - ::ty_param_name(tcx, id)) - } - query => span_bug!(span, "unexpected `{:?}`", query) - } - }; - - err.note(&format!("the cycle begins when {}...", - describe(cycle[0]))); - - for &query in &cycle[1..] { - err.note(&format!("...which then requires {}...", - describe(query))); - } - - err.note(&format!("...which then again requires {}, completing the cycle.", - describe(cycle[0]))); - - err.emit(); - } - - /// Ensure that the (transitive) super predicates for - /// `trait_def_id` are available. This will report a cycle error - /// if a trait `X` (transitively) extends itself in some form. - fn ensure_super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - span: Span, - trait_def_id: DefId) - -> Result<(), ErrorReported> - { - cycle_check(tcx, span, ty::maps::Query::super_predicates(trait_def_id), || { - let def_ids = ensure_super_predicates_step(tcx, trait_def_id); - - for def_id in def_ids { - ensure_super_predicates(tcx, span, def_id)?; - } - - Ok(()) - }) - } - impl<'a,'tcx> ItemCtxt<'a,'tcx> { fn to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { AstConv::ast_ty_to_ty(self, ast_ty) @@ -334,9 +249,9 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx> { - cycle_check(self.tcx, span, ty::maps::Query::ty(id), || { - Ok(type_of_def_id(self.tcx, id)) - }).unwrap_or(self.tcx.types.err) + self.tcx.cycle_check(span, ty::maps::Query::ty(id), || { + type_of_def_id(self.tcx, id) + }) } fn get_trait_def(&self, def_id: DefId) -> &'tcx ty::TraitDef { @@ -349,30 +264,36 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } } + /// Ensure that the (transitive) super predicates for + /// `trait_def_id` are available. This will report a cycle error + /// if a trait `X` (transitively) extends itself in some form. fn ensure_super_predicates(&self, span: Span, - trait_def_id: DefId) - -> Result<(), ErrorReported> - { - debug!("ensure_super_predicates(trait_def_id={:?})", - trait_def_id); + trait_def_id: DefId) { + if !trait_def_id.is_local() { + // If this trait comes from an external crate, then all of the + // supertraits it may depend on also must come from external + // crates, and hence all of them already have their + // super-predicates "converted" (and available from crate + // meta-data), so there is no need to transitively test them. + return; + } - ensure_super_predicates(self.tcx, span, trait_def_id) + self.tcx.maps.super_predicates.memoize(trait_def_id, || { + self.tcx.cycle_check(span, ty::maps::Query::super_predicates(trait_def_id), || { + super_predicates(self.tcx, trait_def_id) + }) + }); } fn get_type_parameter_bounds(&self, span: Span, - node_id: ast::NodeId) - -> Result>, ErrorReported> + def_id: DefId) + -> Vec> { - let def_id = self.tcx.hir.local_def_id(node_id); - cycle_check(self.tcx, span, ty::maps::Query::type_param_predicates(def_id), || { - let v = get_type_parameter_bounds(self.tcx, self.item_def_id, node_id) - .into_iter() - .filter_map(|p| p.to_opt_poly_trait_ref()) - .collect(); - Ok(v) - }) + self.tcx.cycle_check(span, + ty::maps::Query::type_param_predicates((self.item_def_id, def_id)), + || get_type_parameter_bounds(self.tcx, self.item_def_id, def_id)) } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { @@ -428,7 +349,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn get_type_parameter_bounds<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId, - param_id: ast::NodeId) + def_id: DefId) -> Vec> { use rustc::hir::map::*; @@ -438,10 +359,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { // written inline like `` or in a where clause like // `where T:Foo`. - let param_owner_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, param_id)); + let param_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let param_owner = tcx.hir.ty_param_owner(param_id); + let param_owner_def_id = tcx.hir.local_def_id(param_owner); let generics = generics_of_def_id(tcx, param_owner_def_id); - let index = generics.type_param_to_index[&tcx.hir.local_def_id(param_id).index]; - let ty = tcx.mk_param(index, ::ty_param_name(tcx, param_id)); + let index = generics.type_param_to_index[&def_id.index]; + let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id)); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner_def_id { @@ -450,8 +373,9 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { generics_of_def_id(tcx, item_def_id).parent }; - let mut results = parent.map_or(vec![], |def_id| { - get_type_parameter_bounds(tcx, def_id, param_id) + let mut results = parent.map_or(vec![], |parent| { + let icx = ItemCtxt::new(tcx, parent); + icx.get_type_parameter_bounds(DUMMY_SP, def_id) }); let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); @@ -706,8 +630,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { hir::ItemTrait(..) => { generics_of_def_id(tcx, def_id); trait_def_of_item(tcx, it); - let _: Result<(), ErrorReported> = // any error is already reported, can ignore - ensure_super_predicates(tcx, it.span, def_id); + icx.ensure_super_predicates(it.span, def_id); predicates_of_item(tcx, it); }, hir::ItemStruct(ref struct_def, _) | @@ -1025,82 +948,54 @@ fn convert_enum_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } /// Ensures that the super-predicates of the trait with def-id -/// trait_def_id are converted and stored. This does NOT ensure that -/// the transitive super-predicates are converted; that is the job of -/// the `ensure_super_predicates()` method in the `AstConv` impl -/// above. Returns a list of trait def-ids that must be ensured as -/// well to guarantee that the transitive superpredicates are -/// converted. -fn ensure_super_predicates_step<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trait_def_id: DefId) - -> Vec -{ - debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id); - - let trait_node_id = if let Some(n) = tcx.hir.as_local_node_id(trait_def_id) { - n - } else { - // If this trait comes from an external crate, then all of the - // supertraits it may depend on also must come from external - // crates, and hence all of them already have their - // super-predicates "converted" (and available from crate - // meta-data), so there is no need to transitively test them. - return Vec::new(); +/// trait_def_id are converted and stored. This also ensures that +/// the transitive super-predicates are converted; +fn super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_def_id: DefId) + -> ty::GenericPredicates<'tcx> { + debug!("super_predicates(trait_def_id={:?})", trait_def_id); + let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap(); + + let item = match tcx.hir.get(trait_node_id) { + hir_map::NodeItem(item) => item, + _ => bug!("trait_node_id {} is not an item", trait_node_id) }; - let superpredicates = tcx.maps.super_predicates.borrow().get(&trait_def_id).cloned(); - let superpredicates = superpredicates.unwrap_or_else(|| { - let item = match tcx.hir.get(trait_node_id) { - hir_map::NodeItem(item) => item, - _ => bug!("trait_node_id {} is not an item", trait_node_id) - }; - - let (generics, bounds) = match item.node { - hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits), - _ => span_bug!(item.span, - "ensure_super_predicates_step invoked on non-trait"), - }; - - let icx = ItemCtxt::new(tcx, trait_def_id); - - // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. - let self_param_ty = tcx.mk_self_type(); - let superbounds1 = compute_bounds(&icx, - self_param_ty, - bounds, - SizedByDefault::No, - item.span); - - let superbounds1 = superbounds1.predicates(tcx, self_param_ty); + let (generics, bounds) = match item.node { + hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits), + _ => span_bug!(item.span, + "super_predicates invoked on non-trait"), + }; - // Convert any explicit superbounds in the where clause, - // e.g. `trait Foo where Self : Bar`: - let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty); + let icx = ItemCtxt::new(tcx, trait_def_id); - // Combine the two lists to form the complete set of superbounds: - let superbounds = superbounds1.into_iter().chain(superbounds2).collect(); - let superpredicates = ty::GenericPredicates { - parent: None, - predicates: superbounds - }; - debug!("superpredicates for trait {:?} = {:?}", - tcx.hir.local_def_id(item.id), - superpredicates); + // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. + let self_param_ty = tcx.mk_self_type(); + let superbounds1 = compute_bounds(&icx, + self_param_ty, + bounds, + SizedByDefault::No, + item.span); - tcx.maps.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone()); + let superbounds1 = superbounds1.predicates(tcx, self_param_ty); - superpredicates - }); + // Convert any explicit superbounds in the where clause, + // e.g. `trait Foo where Self : Bar`: + let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty); - let def_ids: Vec<_> = superpredicates.predicates - .iter() - .filter_map(|p| p.to_opt_poly_trait_ref()) - .map(|tr| tr.def_id()) - .collect(); + // Combine the two lists to form the complete set of superbounds: + let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect(); - debug!("ensure_super_predicates_step: def_ids={:?}", def_ids); + // Now require that immediate supertraits are converted, + // which will, in turn, reach indirect supertraits. + for bound in superbounds.iter().filter_map(|p| p.to_opt_poly_trait_ref()) { + icx.ensure_super_predicates(item.span, bound.def_id()); + } - def_ids + ty::GenericPredicates { + parent: None, + predicates: superbounds + } } fn trait_def_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 1ff6944d98dd3..e8cb25cec4f25 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -3417,23 +3417,6 @@ impl Bar for *mut Foo { ``` "##, -E0391: r##" -This error indicates that some types or traits depend on each other -and therefore cannot be constructed. - -The following example contains a circular dependency between two traits: - -```compile_fail,E0391 -trait FirstTrait : SecondTrait { - -} - -trait SecondTrait : FirstTrait { - -} -``` -"##, - E0392: r##" This error indicates that a type or lifetime parameter has been declared but not actually used. Here is an example that demonstrates the error: diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ddd8d9259cc99..c3c1952415b90 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -116,7 +116,6 @@ use util::common::time; use syntax::ast; use syntax::abi::Abi; -use syntax::symbol::keywords; use syntax_pos::Span; use std::iter; @@ -170,30 +169,6 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) } -fn ty_param_owner(tcx: TyCtxt, id: ast::NodeId) -> ast::NodeId { - match tcx.hir.get(id) { - hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => id, - hir::map::NodeTyParam(_) => tcx.hir.get_parent_node(id), - _ => { - bug!("ty_param_owner: {} not a type parameter", - tcx.hir.node_to_string(id)) - } - } -} - -fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name { - match tcx.hir.get(id) { - hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => { - keywords::SelfType.name() - } - hir::map::NodeTyParam(tp) => tp.name, - _ => { - bug!("ty_param_name: {} not a type parameter", - tcx.hir.node_to_string(id)) - } - } -} - fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_id: ast::NodeId, main_span: Span) { diff --git a/src/test/compile-fail/cycle-projection-based-on-where-clause.rs b/src/test/compile-fail/cycle-projection-based-on-where-clause.rs index 5ca0700ce6eda..7af2f11bd2815 100644 --- a/src/test/compile-fail/cycle-projection-based-on-where-clause.rs +++ b/src/test/compile-fail/cycle-projection-based-on-where-clause.rs @@ -26,6 +26,7 @@ struct A where T : Trait, T : Add //~^ ERROR unsupported cyclic reference between types/traits detected + //~| ERROR associated type `Item` not found for `T` { data: T } diff --git a/src/test/compile-fail/cycle-trait-supertrait-indirect.rs b/src/test/compile-fail/cycle-trait-supertrait-indirect.rs index c9bfde3f4ed12..905d546e99a06 100644 --- a/src/test/compile-fail/cycle-trait-supertrait-indirect.rs +++ b/src/test/compile-fail/cycle-trait-supertrait-indirect.rs @@ -12,14 +12,16 @@ // a direct participant in the cycle. trait A: B { - //~^ ERROR unsupported cyclic reference + //~^ NOTE the cycle begins when computing the supertraits of `B`... } trait B: C { - //~^ ERROR unsupported cyclic reference + //~^ NOTE ...which then requires computing the supertraits of `C`... } trait C: B { } //~^ ERROR unsupported cyclic reference + //~| cyclic reference + //~| NOTE ...which then again requires computing the supertraits of `B`, completing the cycle fn main() { } diff --git a/src/test/compile-fail/issue-12511.rs b/src/test/compile-fail/issue-12511.rs index 35697e687341f..0c3073a770141 100644 --- a/src/test/compile-fail/issue-12511.rs +++ b/src/test/compile-fail/issue-12511.rs @@ -9,11 +9,14 @@ // except according to those terms. trait t1 : t2 { -//~^ ERROR: unsupported cyclic reference between types/traits detected +//~^ NOTE the cycle begins when computing the supertraits of `t1`... +//~| NOTE ...which then requires computing the supertraits of `t2`... } trait t2 : t1 { -//~^ ERROR: unsupported cyclic reference between types/traits detected +//~^ ERROR unsupported cyclic reference between types/traits detected +//~| cyclic reference +//~| NOTE ...which then again requires computing the supertraits of `t1`, completing the cycle } fn main() { } diff --git a/src/test/compile-fail/issue-20772.rs b/src/test/compile-fail/issue-20772.rs index 44c92f946f03d..7ae4250d4203b 100644 --- a/src/test/compile-fail/issue-20772.rs +++ b/src/test/compile-fail/issue-20772.rs @@ -10,6 +10,7 @@ trait T : Iterator //~^ ERROR unsupported cyclic reference between types/traits detected +//~| ERROR associated type `Item` not found for `Self` {} fn main() {} diff --git a/src/test/compile-fail/issue-21177.rs b/src/test/compile-fail/issue-21177.rs index 5ad9a12362d60..f49b71953835b 100644 --- a/src/test/compile-fail/issue-21177.rs +++ b/src/test/compile-fail/issue-21177.rs @@ -14,6 +14,7 @@ trait Trait { } fn foo>() { } -//~^ ERROR: unsupported cyclic reference between types/traits detected +//~^ ERROR unsupported cyclic reference between types/traits detected +//~| ERROR associated type `B` not found for `T` fn main() { } From 91374f8fe482e5938a8f08353aa48ef9c7873637 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 13 Feb 2017 10:51:06 +0200 Subject: [PATCH 09/17] rustc: combine BareFnTy and ClosureTy into FnSig. --- src/librustc/infer/mod.rs | 4 +- src/librustc/middle/effect.rs | 4 +- src/librustc/middle/intrinsicck.rs | 8 +- src/librustc/middle/liveness.rs | 2 +- src/librustc/traits/project.rs | 4 +- src/librustc/traits/select.rs | 16 ++-- src/librustc/traits/util.rs | 2 +- src/librustc/ty/context.rs | 56 ++++--------- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 10 +-- src/librustc/ty/fold.rs | 13 --- src/librustc/ty/maps.rs | 2 +- src/librustc/ty/mod.rs | 6 +- src/librustc/ty/relate.rs | 24 ++---- src/librustc/ty/structural_impls.rs | 54 +----------- src/librustc/ty/sty.rs | 52 ++++-------- src/librustc/ty/util.rs | 8 +- src/librustc/ty/walk.rs | 10 +-- src/librustc/util/ppaux.rs | 37 +++----- .../borrowck/mir/dataflow/sanity_check.rs | 3 +- src/librustc_driver/test.rs | 12 +-- src/librustc_lint/builtin.rs | 8 +- src/librustc_lint/types.rs | 6 +- src/librustc_metadata/decoder.rs | 8 +- src/librustc_metadata/schema.rs | 2 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 7 +- src/librustc_mir/mir_map.rs | 10 ++- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/type_check.rs | 6 +- src/librustc_trans/abi.rs | 20 ++--- src/librustc_trans/base.rs | 12 ++- src/librustc_trans/callee.rs | 84 +++++++------------ src/librustc_trans/collector.rs | 10 +-- src/librustc_trans/common.rs | 22 ++--- src/librustc_trans/context.rs | 16 ++-- src/librustc_trans/debuginfo/metadata.rs | 8 +- src/librustc_trans/debuginfo/mod.rs | 12 ++- src/librustc_trans/debuginfo/type_names.rs | 9 +- src/librustc_trans/declare.rs | 8 +- src/librustc_trans/intrinsic.rs | 34 ++++---- src/librustc_trans/mir/block.rs | 13 +-- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/mod.rs | 8 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_trans/trans_item.rs | 19 +++-- src/librustc_trans/type_of.rs | 6 +- src/librustc_typeck/astconv.rs | 36 ++++---- src/librustc_typeck/check/callee.rs | 21 +++-- src/librustc_typeck/check/closure.rs | 44 +++++----- src/librustc_typeck/check/coercion.rs | 27 +++--- src/librustc_typeck/check/compare_method.rs | 24 ++---- src/librustc_typeck/check/demand.rs | 4 +- src/librustc_typeck/check/intrinsic.rs | 26 +++--- src/librustc_typeck/check/method/confirm.rs | 17 +--- src/librustc_typeck/check/method/mod.rs | 13 +-- src/librustc_typeck/check/mod.rs | 37 ++++---- src/librustc_typeck/check/regionck.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 22 ++--- src/librustc_typeck/collect.rs | 16 ++-- src/librustc_typeck/lib.rs | 24 +++--- src/librustc_typeck/variance/constraints.rs | 6 +- src/librustdoc/clean/inline.rs | 12 +-- src/librustdoc/clean/mod.rs | 29 +++---- 64 files changed, 420 insertions(+), 605 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 64256247bb50c..c9abcd38b95ad 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -600,7 +600,7 @@ impl_trans_normalize!('gcx, Ty<'gcx>, &'gcx Substs<'gcx>, ty::FnSig<'gcx>, - &'gcx ty::BareFnTy<'gcx>, + ty::PolyFnSig<'gcx>, ty::ClosureSubsts<'gcx>, ty::PolyTraitRef<'gcx>, ty::ExistentialTraitRef<'gcx> @@ -1652,7 +1652,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn closure_type(&self, def_id: DefId, substs: ty::ClosureSubsts<'tcx>) - -> ty::ClosureTy<'tcx> + -> ty::PolyFnSig<'tcx> { if let InferTables::InProgress(tables) = self.tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index ab33c3843aae5..5af8e7e52d888 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -44,8 +44,8 @@ enum RootUnsafeContext { fn type_is_unsafe_function(ty: Ty) -> bool { match ty.sty { - ty::TyFnDef(.., ref f) | - ty::TyFnPtr(ref f) => f.unsafety == hir::Unsafety::Unsafe, + ty::TyFnDef(.., f) | + ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe, _ => false, } } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 05be35df95991..cdbf92e93a4cb 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -40,7 +40,7 @@ struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { let intrinsic = match self.infcx.tcx.item_type(def_id).sty { - ty::TyFnDef(.., ref bfty) => bfty.abi == RustIntrinsic, + ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic, _ => return false }; intrinsic && self.infcx.tcx.item_name(def_id) == "transmute" @@ -137,9 +137,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> { let typ = self.infcx.tables.borrow().node_id_to_type(expr.id); let typ = self.infcx.tcx.lift_to_global(&typ).unwrap(); match typ.sty { - ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { - let from = bare_fn_ty.sig.skip_binder().inputs()[0]; - let to = bare_fn_ty.sig.skip_binder().output(); + ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => { + let from = sig.inputs().skip_binder()[0]; + let to = *sig.output().skip_binder(); self.check_transmute(expr.span, from, to, expr.id); } _ => { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b7f7c49d7b0e3..28f9a23d4593c 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1434,7 +1434,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let fn_ty = self.ir.tcx.item_type(self.ir.tcx.hir.local_def_id(id)); let fn_ret = match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => - self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), + self.ir.tcx.closure_type(closure_def_id, substs).output(), _ => fn_ty.fn_ret() }; diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 6f645b5f94d00..0d498ce1aa3f3 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1224,7 +1224,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( confirm_callable_candidate(selcx, obligation, - &closure_type.sig, + closure_type, util::TupleArgumentsFlag::No) .with_addl_obligations(vtable.nested) .with_addl_obligations(obligations) @@ -1233,7 +1233,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - fn_sig: &ty::PolyFnSig<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, flag: util::TupleArgumentsFlag) -> Progress<'tcx> { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 40c62762c3cf3..98f814a54f848 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1405,16 +1405,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // provide an impl, but only for suitable `fn` pointers - ty::TyFnDef(.., &ty::BareFnTy { + ty::TyFnDef(.., ty::Binder(ty::FnSig { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - ref sig, - }) | - ty::TyFnPtr(&ty::BareFnTy { + variadic: false, + .. + })) | + ty::TyFnPtr(ty::Binder(ty::FnSig { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, - ref sig - }) if !sig.variadic() => { + variadic: false, + .. + })) => { candidates.vec.push(FnPointerCandidate); } @@ -2781,7 +2783,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let ty::Binder((trait_ref, _)) = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), obligation.predicate.0.self_ty(), // (1) - &closure_type.sig, + closure_type, util::TupleArgumentsFlag::No); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 7b2882bb64f2c..602f27a64d4d8 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -482,7 +482,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn closure_trait_ref_and_return_type(self, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, - sig: &ty::PolyFnSig<'tcx>, + sig: ty::PolyFnSig<'tcx>, tuple_arguments: TupleArgumentsFlag) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 38af6c3d0da54..f1945fd57ef64 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -32,7 +32,7 @@ use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; -use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; +use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; @@ -53,6 +53,7 @@ use std::ops::Deref; use std::rc::Rc; use std::iter; use std::cmp::Ordering; +use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::symbol::{Symbol, keywords}; @@ -94,7 +95,6 @@ pub struct CtxtInterners<'tcx> { type_: RefCell>>>, type_list: RefCell>>>>, substs: RefCell>>>, - bare_fn: RefCell>>>, region: RefCell>>, existential_predicates: RefCell>>>>, } @@ -106,7 +106,6 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { type_: RefCell::new(FxHashSet()), type_list: RefCell::new(FxHashSet()), substs: RefCell::new(FxHashSet()), - bare_fn: RefCell::new(FxHashSet()), region: RefCell::new(FxHashSet()), existential_predicates: RefCell::new(FxHashSet()), } @@ -219,7 +218,7 @@ pub struct TypeckTables<'tcx> { pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, /// Records the type of each closure. - pub closure_tys: NodeMap>, + pub closure_tys: NodeMap>, /// Records the kind of each closure. pub closure_kinds: NodeMap, @@ -859,23 +858,6 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } -impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> { - type Lifted = &'tcx BareFnTy<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) - -> Option<&'tcx BareFnTy<'tcx>> { - if tcx.interners.arena.in_arena(*self as *const _) { - return Some(unsafe { mem::transmute(*self) }); - } - // Also try in the global tcx if we're not that. - if !tcx.is_global() { - self.lift_to_tcx(tcx.global_tcx()) - } else { - None - } - } -} - - pub mod tls { use super::{CtxtInterners, GlobalCtxt, TyCtxt}; @@ -1028,7 +1010,6 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); println!("Substs interner: #{}", self.interners.substs.borrow().len()); - println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len()); println!("Region interner: #{}", self.interners.region.borrow().len()); println!("Stability interner: #{}", self.stability_interner.borrow().len()); println!("Layout interner: #{}", self.layout_interner.borrow().len()); @@ -1087,12 +1068,6 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, Substs<'tcx>> { } } -impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, BareFnTy<'tcx>> { - fn borrow<'a>(&'a self) -> &'a BareFnTy<'lcx> { - self.0 - } -} - impl<'tcx> Borrow for Interned<'tcx, Region> { fn borrow<'a>(&'a self) -> &'a Region { self.0 @@ -1181,9 +1156,6 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { } direct_interners!('tcx, - bare_fn: mk_bare_fn(|fty: &BareFnTy| { - keep_local(&fty.sig) - }) -> BareFnTy<'tcx>, region: mk_region(|r| { match r { &ty::ReVar(_) | &ty::ReSkolemized(..) => true, @@ -1209,12 +1181,11 @@ slice_interners!( impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Create an unsafe fn ty based on a safe fn ty. - pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { - assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal); - self.mk_fn_ptr(self.mk_bare_fn(ty::BareFnTy { + pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { + assert_eq!(sig.unsafety(), hir::Unsafety::Normal); + self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, - abi: bare_fn.abi, - sig: bare_fn.sig.clone() + ..sig })) } @@ -1341,11 +1312,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_fn_def(self, def_id: DefId, substs: &'tcx Substs<'tcx>, - fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { + fty: PolyFnSig<'tcx>) -> Ty<'tcx> { self.mk_ty(TyFnDef(def_id, substs, fty)) } - pub fn mk_fn_ptr(self, fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { + pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { self.mk_ty(TyFnPtr(fty)) } @@ -1439,14 +1410,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn mk_fn_sig(self, inputs: I, output: I::Item, variadic: bool) + pub fn mk_fn_sig(self, + inputs: I, + output: I::Item, + variadic: bool, + unsafety: hir::Unsafety, + abi: abi::Abi) -> , ty::FnSig<'tcx>>>::Output where I: Iterator, I::Item: InternIteratorElement, ty::FnSig<'tcx>> { inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig { inputs_and_output: self.intern_type_list(xs), - variadic: variadic + variadic, unsafety, abi }) } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 981cf0897a034..3d2cc4c598a22 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -76,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, Some(TupleSimplifiedType(tys.len())) } ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { - Some(FunctionSimplifiedType(f.sig.skip_binder().inputs().len())) + Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } ty::TyProjection(_) | ty::TyParam(_) => { if can_simplify_params { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 2012917f93a87..384f99ceb4e83 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -155,13 +155,13 @@ impl FlagComputation { self.add_tys(&ts[..]); } - &ty::TyFnDef(_, substs, ref f) => { + &ty::TyFnDef(_, substs, f) => { self.add_substs(substs); - self.add_fn_sig(&f.sig); + self.add_fn_sig(f); } - &ty::TyFnPtr(ref f) => { - self.add_fn_sig(&f.sig); + &ty::TyFnPtr(f) => { + self.add_fn_sig(f); } } } @@ -177,7 +177,7 @@ impl FlagComputation { } } - fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) { + fn add_fn_sig(&mut self, fn_sig: ty::PolyFnSig) { let mut computation = FlagComputation::new(); computation.add_tys(fn_sig.skip_binder().inputs()); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 10754825a8c18..e29653c9e88a0 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -159,19 +159,6 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { sig.super_fold_with(self) } - fn fold_bare_fn_ty(&mut self, - fty: &'tcx ty::BareFnTy<'tcx>) - -> &'tcx ty::BareFnTy<'tcx> - { - fty.super_fold_with(self) - } - - fn fold_closure_ty(&mut self, - fty: &ty::ClosureTy<'tcx>) - -> ty::ClosureTy<'tcx> { - fty.super_fold_with(self) - } - fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region { r.super_fold_with(self) } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index dc87bb43c265d..6958df093d0e8 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -264,7 +264,7 @@ define_maps! { <'tcx> /// Records the type of each closure. The def ID is the ID of the /// expression defining the closure. - pub closure_type: ItemSignature(DefId) -> ty::ClosureTy<'tcx>, + pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>, /// Caches CoerceUnsized kinds for impls on custom types. pub custom_coerce_unsized_kind: ItemSignature(DefId) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9d4e17138a042..c1f372a1c2970 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -55,8 +55,8 @@ use hir; use hir::itemlikevisit::ItemLikeVisitor; pub use self::sty::{Binder, DebruijnIndex}; -pub use self::sty::{BareFnTy, FnSig, PolyFnSig}; -pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; +pub use self::sty::{FnSig, PolyFnSig}; +pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, TypeAndMut}; pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; @@ -2470,7 +2470,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn closure_type(self, def_id: DefId, substs: ClosureSubsts<'tcx>) - -> ty::ClosureTy<'tcx> + -> ty::PolyFnSig<'tcx> { if let Some(ty) = self.maps.closure_type.borrow().get(&def_id) { return ty.subst(self, substs.substs); diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2e3009b4ed6db..cef24d44d6875 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -157,24 +157,6 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_substs(params)?) } -impl<'tcx> Relate<'tcx> for &'tcx ty::BareFnTy<'tcx> { - fn relate<'a, 'gcx, R>(relation: &mut R, - a: &&'tcx ty::BareFnTy<'tcx>, - b: &&'tcx ty::BareFnTy<'tcx>) - -> RelateResult<'tcx, &'tcx ty::BareFnTy<'tcx>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a - { - let unsafety = relation.relate(&a.unsafety, &b.unsafety)?; - let abi = relation.relate(&a.abi, &b.abi)?; - let sig = relation.relate(&a.sig, &b.sig)?; - Ok(relation.tcx().mk_bare_fn(ty::BareFnTy { - unsafety: unsafety, - abi: abi, - sig: sig - })) - } -} - impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::FnSig<'tcx>, @@ -186,6 +168,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { return Err(TypeError::VariadicMismatch( expected_found(relation, &a.variadic, &b.variadic))); } + let unsafety = relation.relate(&a.unsafety, &b.unsafety)?; + let abi = relation.relate(&a.abi, &b.abi)?; if a.inputs().len() != b.inputs().len() { return Err(TypeError::ArgCount); @@ -204,7 +188,9 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { }).collect::, _>>()?; Ok(ty::FnSig { inputs_and_output: relation.tcx().intern_type_list(&inputs_and_output), - variadic: a.variadic + variadic: a.variadic, + unsafety: unsafety, + abi: abi }) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index a1bf58a12eb09..48f6fcd11b8ac 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -235,20 +235,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::FnSig<'a> { tcx.lift(&self.inputs_and_output).map(|x| { ty::FnSig { inputs_and_output: x, - variadic: self.variadic - } - }) - } -} - -impl<'a, 'tcx> Lift<'tcx> for ty::ClosureTy<'a> { - type Lifted = ty::ClosureTy<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - tcx.lift(&self.sig).map(|sig| { - ty::ClosureTy { - sig: sig, + variadic: self.variadic, unsafety: self.unsafety, - abi: self.abi + abi: self.abi, } }) } @@ -531,43 +520,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::BareFnTy<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let fty = ty::BareFnTy { - sig: self.sig.fold_with(folder), - abi: self.abi, - unsafety: self.unsafety - }; - folder.tcx().mk_bare_fn(fty) - } - - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_bare_fn_ty(self) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.sig.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for ty::ClosureTy<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::ClosureTy { - sig: self.sig.fold_with(folder), - unsafety: self.unsafety, - abi: self.abi, - } - } - - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_closure_ty(self) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.sig.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TypeAndMut { ty: self.ty.fold_with(folder), mutbl: self.mutbl } @@ -588,6 +540,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { ty::FnSig { inputs_and_output: folder.tcx().intern_type_list(&inputs_and_output), variadic: self.variadic, + unsafety: self.unsafety, + abi: self.abi, } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 862bc15c05260..3d6c1da8830a7 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -128,12 +128,12 @@ pub enum TypeVariants<'tcx> { /// The anonymous type of a function declaration/definition. Each /// function has a unique type. - TyFnDef(DefId, &'tcx Substs<'tcx>, &'tcx BareFnTy<'tcx>), + TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>), /// A pointer to a function. Written as `fn() -> i32`. /// FIXME: This is currently also used to represent the callee of a method; /// see ty::MethodCallee etc. - TyFnPtr(&'tcx BareFnTy<'tcx>), + TyFnPtr(PolyFnSig<'tcx>), /// A trait, defined with `trait`. TyDynamic(Binder<&'tcx Slice>>, &'tcx ty::Region), @@ -531,38 +531,22 @@ pub struct ProjectionTy<'tcx> { /// The name `N` of the associated type. pub item_name: Name, } - -#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct BareFnTy<'tcx> { - pub unsafety: hir::Unsafety, - pub abi: abi::Abi, - /// Signature (inputs and output) of this function type. - pub sig: PolyFnSig<'tcx>, -} - -impl<'tcx> serialize::UseSpecializedDecodable for &'tcx BareFnTy<'tcx> {} - -#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct ClosureTy<'tcx> { - pub unsafety: hir::Unsafety, - pub abi: abi::Abi, - pub sig: PolyFnSig<'tcx>, -} - /// Signature of a function type, which I have arbitrarily /// decided to use to refer to the input/output types. /// /// - `inputs` is the list of arguments and their modes. /// - `output` is the return type. /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) -#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct FnSig<'tcx> { pub inputs_and_output: &'tcx Slice>, - pub variadic: bool + pub variadic: bool, + pub unsafety: hir::Unsafety, + pub abi: abi::Abi, } impl<'tcx> FnSig<'tcx> { - pub fn inputs(&self) -> &[Ty<'tcx>] { + pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { &self.inputs_and_output[..self.inputs_and_output.len() - 1] } @@ -574,7 +558,7 @@ impl<'tcx> FnSig<'tcx> { pub type PolyFnSig<'tcx> = Binder>; impl<'tcx> PolyFnSig<'tcx> { - pub fn inputs(&self) -> Binder<&[Ty<'tcx>]> { + pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { Binder(self.skip_binder().inputs()) } pub fn input(&self, index: usize) -> ty::Binder> { @@ -586,6 +570,12 @@ impl<'tcx> PolyFnSig<'tcx> { pub fn variadic(&self) -> bool { self.skip_binder().variadic } + pub fn unsafety(&self) -> hir::Unsafety { + self.skip_binder().unsafety + } + pub fn abi(&self) -> abi::Abi { + self.skip_binder().abi + } } #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] @@ -1280,23 +1270,15 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> { + pub fn fn_sig(&self) -> PolyFnSig<'tcx> { match self.sty { - TyFnDef(.., ref f) | TyFnPtr(ref f) => &f.sig, + TyFnDef(.., f) | TyFnPtr(f) => f, _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } - /// Returns the ABI of the given function. - pub fn fn_abi(&self) -> abi::Abi { - match self.sty { - TyFnDef(.., ref f) | TyFnPtr(ref f) => f.abi, - _ => bug!("Ty::fn_abi() called on non-fn type"), - } - } - // Type accessors for substructures of types - pub fn fn_args(&self) -> ty::Binder<&[Ty<'tcx>]> { + pub fn fn_args(&self) -> ty::Binder<&'tcx [Ty<'tcx>]> { self.fn_sig().inputs() } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index af25990978793..bda76550f341c 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -456,10 +456,10 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> TyFnDef(def_id, ..) => self.def_id(def_id), TyAdt(d, _) => self.def_id(d.did), TyFnPtr(f) => { - self.hash(f.unsafety); - self.hash(f.abi); - self.hash(f.sig.variadic()); - self.hash(f.sig.skip_binder().inputs().len()); + self.hash(f.unsafety()); + self.hash(f.abi()); + self.hash(f.variadic()); + self.hash(f.inputs().skip_binder().len()); } TyDynamic(ref data, ..) => { if let Some(p) = data.principal() { diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 01f31e5024c0d..d7954953aba85 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -115,17 +115,17 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } - ty::TyFnDef(_, substs, ref ft) => { + ty::TyFnDef(_, substs, ft) => { stack.extend(substs.types().rev()); - push_sig_subtypes(stack, &ft.sig); + push_sig_subtypes(stack, ft); } - ty::TyFnPtr(ref ft) => { - push_sig_subtypes(stack, &ft.sig); + ty::TyFnPtr(ft) => { + push_sig_subtypes(stack, ft); } } } -fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: &ty::PolyFnSig<'tcx>) { +fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: ty::PolyFnSig<'tcx>) { stack.push(sig.skip_binder().output()); stack.extend(sig.skip_binder().inputs().iter().cloned().rev()); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3981c8a7c4f52..d0c0654b0383b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -495,15 +495,6 @@ impl fmt::Debug for ty::Region { } } -impl<'tcx> fmt::Debug for ty::ClosureTy<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ClosureTy({},{:?},{})", - self.unsafety, - self.sig, - self.abi) - } -} - impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ClosureUpvar({:?},{:?})", @@ -585,6 +576,14 @@ impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> { impl<'tcx> fmt::Display for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.unsafety == hir::Unsafety::Unsafe { + write!(f, "unsafe ")?; + } + + if self.abi != Abi::Rust { + write!(f, "extern {} ", self.abi)?; + } + write!(f, "fn")?; fn_sig(f, self.inputs(), self.variadic, self.output()) } @@ -741,28 +740,12 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, ")") } TyFnDef(def_id, substs, ref bare_fn) => { - if bare_fn.unsafety == hir::Unsafety::Unsafe { - write!(f, "unsafe ")?; - } - - if bare_fn.abi != Abi::Rust { - write!(f, "extern {} ", bare_fn.abi)?; - } - - write!(f, "{} {{", bare_fn.sig.0)?; + write!(f, "{} {{", bare_fn.0)?; parameterized(f, substs, def_id, &[])?; write!(f, "}}") } TyFnPtr(ref bare_fn) => { - if bare_fn.unsafety == hir::Unsafety::Unsafe { - write!(f, "unsafe ")?; - } - - if bare_fn.abi != Abi::Rust { - write!(f, "extern {} ", bare_fn.abi)?; - } - - write!(f, "{}", bare_fn.sig.0) + write!(f, "{}", bare_fn.0) } TyInfer(infer_ty) => write!(f, "{}", infer_ty), TyError => write!(f, "[type error]"), diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index 940dd5433a0d9..44e3b38ea3857 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -164,8 +164,9 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { if let mir::Operand::Constant(ref func) = *oper { - if let ty::TyFnDef(def_id, _, &ty::BareFnTy { abi, .. }) = func.ty.sty + if let ty::TyFnDef(def_id, _, sig) = func.ty.sty { + let abi = sig.abi(); let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { if name == "rustc_peek" { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2aa1b9981b3cd..36ba1e7f95bd8 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -270,11 +270,13 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.tcx.mk_fn_ptr(self.infcx.tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - sig: ty::Binder(self.infcx.tcx.mk_fn_sig(input_tys.iter().cloned(), output_ty, false)), - })) + self.infcx.tcx.mk_fn_ptr(ty::Binder(self.infcx.tcx.mk_fn_sig( + input_tys.iter().cloned(), + output_ty, + false, + hir::Unsafety::Normal, + Abi::Rust + ))) } pub fn t_nil(&self) -> Ty<'tcx> { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 1592d17817641..75269f58ed62d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1082,9 +1082,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { } let typ = cx.tables.node_id_to_type(expr.id); match typ.sty { - ty::TyFnDef(.., ref bare_fn) if bare_fn.abi == RustIntrinsic => { - let from = bare_fn.sig.skip_binder().inputs()[0]; - let to = bare_fn.sig.skip_binder().output(); + ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => { + let from = bare_fn.inputs().skip_binder()[0]; + let to = *bare_fn.output().skip_binder(); return Some((&from.sty, &to.sty)); } _ => (), @@ -1095,7 +1095,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { match cx.tcx.item_type(def_id).sty { - ty::TyFnDef(.., ref bfty) if bfty.abi == RustIntrinsic => (), + ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (), _ => return false, } cx.tcx.item_name(def_id) == "transmute" diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 8feb07953db81..dd7f751338dcc 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -568,8 +568,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::TyArray(ty, _) => self.check_type_for_ffi(cache, ty), - ty::TyFnPtr(bare_fn) => { - match bare_fn.abi { + ty::TyFnPtr(sig) => { + match sig.abi() { Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => { return FfiUnsafe("found function pointer with Rust calling convention in \ foreign module; consider using an `extern` function \ @@ -578,7 +578,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { _ => {} } - let sig = cx.erase_late_bound_regions(&bare_fn.sig); + let sig = cx.erase_late_bound_regions(&sig); if !sig.output().is_nil() { let r = self.check_type_for_ffi(cache, sig.output()); match r { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 3f8873ddc2742..0e92c492e4b0d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -363,12 +363,6 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> for DecodeContext<' } } -impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::BareFnTy<'tcx>> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result<&'tcx ty::BareFnTy<'tcx>, Self::Error> { - Ok(self.tcx().mk_bare_fn(Decodable::decode(self)?)) - } -} - impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::AdtDef> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> { let def_id = DefId::decode(self)?; @@ -1054,7 +1048,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn closure_ty(&self, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::ClosureTy<'tcx> { + -> ty::PolyFnSig<'tcx> { match self.entry(closure_id).kind { EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)), _ => bug!(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 6307d4eda308e..fa39b687355bf 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -337,5 +337,5 @@ pub struct MethodData { #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub kind: ty::ClosureKind, - pub ty: Lazy>, + pub ty: Lazy>, } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index d9f71e36e2118..ae51951b519bd 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -202,7 +202,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let diverges = match ty.sty { ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => { // FIXME(canndrew): This is_never should probably be an is_uninhabited - f.sig.skip_binder().output().is_never() + f.output().skip_binder().is_never() } _ => false }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index dd45b1b489607..2cb26eed1fff1 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -267,13 +267,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let method = method_callee(cx, expr, ty::MethodCall::expr(expr.id)); - let sig = match method.ty.sty { - ty::TyFnDef(.., fn_ty) => &fn_ty.sig, - _ => span_bug!(expr.span, "type of method is not an fn"), - }; + let sig = method.ty.fn_sig(); let sig = cx.tcx - .no_late_bound_regions(sig) + .no_late_bound_regions(&sig) .unwrap_or_else(|| span_bug!(expr.span, "method call has late-bound regions")); assert_eq!(sig.inputs().len(), 2); diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index dedc55404496a..34b701a3a9dd5 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -104,10 +104,14 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let fn_sig = cx.tables().liberated_fn_sigs[&id].clone(); let ty = tcx.item_type(tcx.hir.local_def_id(id)); - let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty { - (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None))) + let mut abi = fn_sig.abi; + let implicit_argument = if let ty::TyClosure(..) = ty.sty { + // HACK(eddyb) Avoid having RustCall on closures, + // as it adds unnecessary (and wrong) auto-tupling. + abi = Abi::Rust; + Some((closure_self_ty(tcx, id, body_id), None)) } else { - (ty.fn_abi(), None) + None }; let body = tcx.hir.body(body_id); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 04e809ef9d839..4f80e21af64e4 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -788,7 +788,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let fn_ty = func.ty(self.mir, self.tcx); let (is_shuffle, is_const_fn) = match fn_ty.sty { ty::TyFnDef(def_id, _, f) => { - (f.abi == Abi::PlatformIntrinsic && + (f.abi() == Abi::PlatformIntrinsic && self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"), is_const_fn(self.tcx, def_id)) } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 8d108815e0f3c..40485e4b66d77 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -440,14 +440,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { TerminatorKind::Call { ref func, ref args, ref destination, .. } => { let func_ty = func.ty(mir, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); - let func_ty = match func_ty.sty { - ty::TyFnDef(.., func_ty) | ty::TyFnPtr(func_ty) => func_ty, + let sig = match func_ty.sty { + ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig, _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); return; } }; - let sig = tcx.erase_late_bound_regions(&func_ty.sig); + let sig = tcx.erase_late_bound_regions(&sig); let sig = self.normalize(&sig); self.check_call_dest(mir, term, &sig, destination); diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index f742cca5b980a..b44cd20e4402e 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -327,20 +327,18 @@ pub struct FnType { impl FnType { pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - abi: Abi, - sig: &ty::FnSig<'tcx>, + sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType { - let mut fn_ty = FnType::unadjusted(ccx, abi, sig, extra_args); - fn_ty.adjust_for_abi(ccx, abi, sig); + let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args); + fn_ty.adjust_for_abi(ccx, sig); fn_ty } pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - abi: Abi, - sig: &ty::FnSig<'tcx>, + sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType { use self::Abi::*; - let cconv = match ccx.sess().target.target.adjust_abi(abi) { + let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => llvm::CCallConv, @@ -363,7 +361,7 @@ impl FnType { }; let mut inputs = sig.inputs(); - let extra_args = if abi == RustCall { + let extra_args = if sig.abi == RustCall { assert!(!sig.variadic && extra_args.is_empty()); match sig.inputs().last().unwrap().sty { @@ -388,7 +386,7 @@ impl FnType { let linux_s390x = target.target_os == "linux" && target.arch == "s390x" && target.target_env == "gnu"; - let rust_abi = match abi { + let rust_abi = match sig.abi { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true, _ => false }; @@ -535,8 +533,8 @@ impl FnType { pub fn adjust_for_abi<'a, 'tcx>(&mut self, ccx: &CrateContext<'a, 'tcx>, - abi: Abi, - sig: &ty::FnSig<'tcx>) { + sig: ty::FnSig<'tcx>) { + let abi = sig.abi; if abi == Abi::Unadjusted { return } if abi == Abi::Rust || abi == Abi::RustCall || diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index ca746c58e7f6a..8125f432ff5ae 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -47,7 +47,7 @@ use rustc::util::common::time; use session::config::{self, NoDebugInfo}; use rustc_incremental::IncrementalHashesMap; use session::{self, DataTypeKind, Session}; -use abi::{self, Abi, FnType}; +use abi::{self, FnType}; use mir::lvalue::LvalueRef; use adt; use attributes; @@ -600,8 +600,8 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance let fn_ty = ccx.tcx().erase_regions(&fn_ty); let fn_ty = monomorphize::apply_param_substs(ccx.shared(), instance.substs, &fn_ty); - let ty::BareFnTy { abi, ref sig, .. } = *common::ty_fn_ty(ccx, fn_ty); - let sig = ccx.tcx().erase_late_bound_regions_and_normalize(sig); + let sig = common::ty_fn_sig(ccx, fn_ty); + let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig); let lldecl = match ccx.instances().borrow().get(&instance) { Some(&val) => val, @@ -614,10 +614,8 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance attributes::emit_uwtable(lldecl, true); } - let fn_ty = FnType::new(ccx, abi, &sig, &[]); - let mir = ccx.tcx().item_mir(instance.def); - mir::trans_mir(ccx, lldecl, fn_ty, &mir, instance, &sig, abi); + mir::trans_mir(ccx, lldecl, &mir, instance, sig); } pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, @@ -632,7 +630,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let ctor_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &ctor_ty); let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig()); - let fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]); + let fn_ty = FnType::new(ccx, sig, &[]); let bcx = Builder::new_block(ccx, llfn, "entry-block"); if !fn_ty.ret.is_ignore() { diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 9a06820115f63..6a9531547c023 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -83,7 +83,7 @@ impl<'tcx> Callee<'tcx> { let fn_ty = def_ty(ccx.shared(), def_id, substs); if let ty::TyFnDef(.., f) = fn_ty.sty { - if f.abi == Abi::RustIntrinsic || f.abi == Abi::PlatformIntrinsic { + if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { return Callee { data: Intrinsic, ty: fn_ty @@ -169,14 +169,13 @@ impl<'tcx> Callee<'tcx> { /// The extra argument types are for variadic (extern "C") functions. pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>, extra_args: &[Ty<'tcx>]) -> FnType { - let abi = self.ty.fn_abi(); - let sig = ccx.tcx().erase_late_bound_regions_and_normalize(self.ty.fn_sig()); - let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args); + let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&self.ty.fn_sig()); + let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args); if let Virtual(_) = self.data { // Don't pass the vtable, it's not an argument of the virtual fn. fn_ty.args[1].ignore(); } - fn_ty.adjust_for_abi(ccx, abi, &sig); + fn_ty.adjust_for_abi(ccx, sig); fn_ty } @@ -307,38 +306,32 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty); // Make a version with the type of by-ref closure. - let ty::ClosureTy { unsafety, abi, mut sig } = tcx.closure_type(def_id, substs); - sig.0 = tcx.mk_fn_sig( - iter::once(ref_closure_ty).chain(sig.0.inputs().iter().cloned()), - sig.0.output(), - sig.0.variadic - ); - let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: unsafety, - abi: abi, - sig: sig.clone() - })); + let sig = tcx.closure_type(def_id, substs); + let sig = tcx.erase_late_bound_regions_and_normalize(&sig); + assert_eq!(sig.abi, Abi::RustCall); + let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + iter::once(ref_closure_ty).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.variadic, + sig.unsafety, + Abi::RustCall + ))); debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}", llref_fn_ty); // Make a version of the closure type with the same arguments, but // with argument #0 being by value. - assert_eq!(abi, Abi::RustCall); - sig.0 = tcx.mk_fn_sig( - iter::once(closure_ty).chain(sig.0.inputs().iter().skip(1).cloned()), - sig.0.output(), - sig.0.variadic + let sig = tcx.mk_fn_sig( + iter::once(closure_ty).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.variadic, + sig.unsafety, + Abi::RustCall ); - let sig = tcx.erase_late_bound_regions_and_normalize(&sig); - let fn_ty = FnType::new(ccx, abi, &sig, &[]); - - let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: unsafety, - abi: abi, - sig: ty::Binder(sig) - })); + let fn_ty = FnType::new(ccx, sig, &[]); + let llonce_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig)); // Create the by-value helper. let function_name = method_instance.symbol_name(ccx.shared()); @@ -470,33 +463,20 @@ fn trans_fn_pointer_shim<'a, 'tcx>( // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`, // which is the fn pointer, and `args`, which is the arguments tuple. - let sig = match bare_fn_ty.sty { - ty::TyFnDef(.., - &ty::BareFnTy { unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - ref sig }) | - ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - ref sig }) => sig, - - _ => { - bug!("trans_fn_pointer_shim invoked on invalid type: {}", - bare_fn_ty); - } - }; - let sig = tcx.erase_late_bound_regions_and_normalize(sig); + let sig = bare_fn_ty.fn_sig(); + let sig = tcx.erase_late_bound_regions_and_normalize(&sig); + assert_eq!(sig.unsafety, hir::Unsafety::Normal); + assert_eq!(sig.abi, Abi::Rust); let tuple_input_ty = tcx.intern_tup(sig.inputs(), false); let sig = tcx.mk_fn_sig( [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(), sig.output(), - false + false, + hir::Unsafety::Normal, + Abi::RustCall ); - let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]); - let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: Abi::RustCall, - sig: ty::Binder(sig) - })); + let fn_ty = FnType::new(ccx, sig, &[]); + let tuple_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig)); debug!("tuple_fn_ty: {:?}", tuple_fn_ty); // @@ -600,7 +580,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // other weird situations. Annoying. // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(common::ty_fn_ty(ccx, fn_ty).into_owned())); + let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty)); let llptrty = type_of::type_of(ccx, fn_ptr_ty); let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) { diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 83a38a529d006..14ef48a902703 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -682,10 +682,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - bare_fn_ty: &ty::BareFnTy<'tcx>) + bare_fn_ty: ty::PolyFnSig<'tcx>) -> bool { - (bare_fn_ty.abi == Abi::RustIntrinsic || - bare_fn_ty.abi == Abi::PlatformIntrinsic) && + (bare_fn_ty.abi() == Abi::RustIntrinsic || + bare_fn_ty.abi() == Abi::PlatformIntrinsic) && tcx.item_name(def_id) == "drop_in_place" } } @@ -697,8 +697,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { - if let ty::TyFnDef(_, _, f) = tcx.item_type(def_id).sty { - if let Some(adt_def) = f.sig.output().skip_binder().ty_adt_def() { + if let ty::TyFnDef(_, _, sig) = tcx.item_type(def_id).sty { + if let Some(adt_def) = sig.output().skip_binder().ty_adt_def() { if adt_def.variants.iter().any(|v| def_id == v.did) { // HACK: ADT constructors are translated in-place and // do not have a trans-item. diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 64100ed4191cc..5e858ce0e0cd3 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -33,7 +33,6 @@ use rustc::traits::{self, SelectionContext, Reveal}; use rustc::hir; use libc::{c_uint, c_char}; -use std::borrow::Cow; use std::iter; use syntax::ast; @@ -570,17 +569,17 @@ pub fn shift_mask_val<'a, 'tcx>( } } -pub fn ty_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - ty: Ty<'tcx>) - -> Cow<'tcx, ty::BareFnTy<'tcx>> +pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + ty: Ty<'tcx>) + -> ty::PolyFnSig<'tcx> { match ty.sty { - ty::TyFnDef(_, _, fty) => Cow::Borrowed(fty), + ty::TyFnDef(_, _, sig) => sig, // Shims currently have type TyFnPtr. Not sure this should remain. - ty::TyFnPtr(fty) => Cow::Borrowed(fty), + ty::TyFnPtr(sig) => sig, ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); - let ty::ClosureTy { unsafety, abi, sig } = tcx.closure_type(def_id, substs); + let sig = tcx.closure_type(def_id, substs); let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); let env_ty = match tcx.closure_kind(def_id) { @@ -589,12 +588,13 @@ pub fn ty_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::ClosureKind::FnOnce => ty, }; - let sig = sig.map_bound(|sig| tcx.mk_fn_sig( + sig.map_bound(|sig| tcx.mk_fn_sig( iter::once(env_ty).chain(sig.inputs().iter().cloned()), sig.output(), - sig.variadic - )); - Cow::Owned(ty::BareFnTy { unsafety: unsafety, abi: abi, sig: sig }) + sig.variadic, + sig.unsafety, + sig.abi + )) } _ => bug!("unexpected type {:?} to ty_fn_sig", ty) } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 799f502aadbfa..d5f7549ece07b 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -959,15 +959,13 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { return llfn; } - let ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Unsafe, - abi: Abi::C, - sig: ty::Binder(tcx.mk_fn_sig( - iter::once(tcx.mk_mut_ptr(tcx.types.u8)), - tcx.types.never, - false - )), - })); + let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + iter::once(tcx.mk_mut_ptr(tcx.types.u8)), + tcx.types.never, + false, + hir::Unsafety::Unsafe, + Abi::C + ))); let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty); attributes::unwind(llfn, true); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 2b584344ed1c7..f6cdd883850cc 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -373,11 +373,11 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, unique_type_id: UniqueTypeId, - signature: &ty::PolyFnSig<'tcx>, + signature: ty::PolyFnSig<'tcx>, span: Span) -> MetadataCreationResult { - let signature = cx.tcx().erase_late_bound_regions(signature); + let signature = cx.tcx().erase_late_bound_regions(&signature); let mut signature_metadata: Vec = Vec::with_capacity(signature.inputs().len() + 1); @@ -558,10 +558,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Err(metadata) => return metadata, } } - ty::TyFnDef(.., ref barefnty) | ty::TyFnPtr(ref barefnty) => { + ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => { let fn_metadata = subroutine_type_metadata(cx, unique_type_id, - &barefnty.sig, + sig, usage_site_span).metadata; match debug_context(cx).type_map .borrow() diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 4a8b0ff45522f..d5f04542d0255 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -198,8 +198,7 @@ pub fn finalize(cx: &CrateContext) { /// for the function. pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>, - sig: &ty::FnSig<'tcx>, - abi: Abi, + sig: ty::FnSig<'tcx>, llfn: ValueRef, mir: &mir::Mir) -> FunctionDebugContext { if cx.sess().opts.debuginfo == NoDebugInfo { @@ -225,7 +224,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path); let function_type_metadata = unsafe { - let fn_signature = get_function_signature(cx, sig, abi); + let fn_signature = get_function_signature(cx, sig); llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature) }; @@ -295,8 +294,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, return FunctionDebugContext::RegularContext(fn_debug_context); fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - sig: &ty::FnSig<'tcx>, - abi: Abi) -> DIArray { + sig: ty::FnSig<'tcx>) -> DIArray { if cx.sess().opts.debuginfo == LimitedDebugInfo { return create_DIArray(DIB(cx), &[]); } @@ -309,7 +307,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) }); - let inputs = if abi == Abi::RustCall { + let inputs = if sig.abi == Abi::RustCall { &sig.inputs()[..sig.inputs().len() - 1] } else { sig.inputs() @@ -320,7 +318,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); } - if abi == Abi::RustCall && !sig.inputs().is_empty() { + if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty { for &argument_type in args { signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 018bbb6e97d34..13ff6646e6662 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -96,12 +96,13 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_type_params(cx, principal.substs, output); } }, - ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | - ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { - if unsafety == hir::Unsafety::Unsafe { + ty::TyFnDef(.., sig) | + ty::TyFnPtr(sig) => { + if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } + let abi = sig.abi(); if abi != ::abi::Abi::Rust { output.push_str("extern \""); output.push_str(abi.name()); @@ -110,7 +111,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push_str("fn("); - let sig = cx.tcx().erase_late_bound_regions_and_normalize(sig); + let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(cx, parameter_type, true, output); diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index 7ac482459ee39..2787812f9622c 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -132,11 +132,11 @@ pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef { pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, fn_type: ty::Ty<'tcx>) -> ValueRef { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); - let ty::BareFnTy { abi, ref sig, .. } = *common::ty_fn_ty(ccx, fn_type); - let sig = ccx.tcx().erase_late_bound_regions_and_normalize(sig); + let sig = common::ty_fn_sig(ccx, fn_type); + let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig); debug!("declare_rust_fn (after region erasure) sig={:?}", sig); - let fty = FnType::new(ccx, abi, &sig, &[]); + let fty = FnType::new(ccx, sig, &[]); let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx)); // FIXME(canndrew): This is_never should really be an is_uninhabited @@ -144,7 +144,7 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, llvm::Attribute::NoReturn.apply_llfn(Function, llfn); } - if abi != Abi::Rust && abi != Abi::RustCall { + if sig.abi != Abi::Rust && sig.abi != Abi::RustCall { attributes::unwind(llfn, false); } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 333a0802ee6ff..b7aedb742db02 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -97,12 +97,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let ccx = bcx.ccx; let tcx = ccx.tcx(); - let (def_id, substs, fty) = match callee_ty.sty { - ty::TyFnDef(def_id, substs, ref fty) => (def_id, substs, fty), + let (def_id, substs, sig) = match callee_ty.sty { + ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig), _ => bug!("expected fn item type, found {}", callee_ty) }; - let sig = tcx.erase_late_bound_regions_and_normalize(&fty.sig); + let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = &*tcx.item_name(def_id).as_str(); @@ -878,13 +878,13 @@ fn gen_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, output: Ty<'tcx>, trans: &mut for<'b> FnMut(Builder<'b, 'tcx>)) -> ValueRef { - let sig = ccx.tcx().mk_fn_sig(inputs.into_iter(), output, false); - - let rust_fn_ty = ccx.tcx().mk_fn_ptr(ccx.tcx().mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Unsafe, - abi: Abi::Rust, - sig: ty::Binder(sig) - })); + let rust_fn_ty = ccx.tcx().mk_fn_ptr(ty::Binder(ccx.tcx().mk_fn_sig( + inputs.into_iter(), + output, + false, + hir::Unsafety::Unsafe, + Abi::Rust + ))); let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty); let bcx = Builder::new_block(ccx, llfn, "entry-block"); trans(bcx); @@ -905,11 +905,13 @@ fn get_rust_try_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Define the type up front for the signature of the rust_try function. let tcx = ccx.tcx(); let i8p = tcx.mk_mut_ptr(tcx.types.i8); - let fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Unsafe, - abi: Abi::Rust, - sig: ty::Binder(tcx.mk_fn_sig(iter::once(i8p), tcx.mk_nil(), false)), - })); + let fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( + iter::once(i8p), + tcx.mk_nil(), + false, + hir::Unsafety::Unsafe, + Abi::Rust + ))); let output = tcx.types.i32; let rust_try = gen_fn(ccx, "__rust_try", vec![fn_ty, i8p, i8p], output, trans); ccx.rust_try_fn().set(Some(rust_try)); @@ -959,7 +961,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( let tcx = bcx.tcx(); - let sig = tcx.erase_late_bound_regions_and_normalize(callee_ty.fn_sig()); + let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig()); let arg_tys = sig.inputs(); // every intrinsic takes a SIMD vector as its first argument diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 651d0066b12dd..d34b1aa206044 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -365,20 +365,21 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.trans_operand(&bcx, func); - let (mut callee, abi, sig) = match callee.ty.sty { - ty::TyFnDef(def_id, substs, f) => { - (Callee::def(bcx.ccx, def_id, substs), f.abi, &f.sig) + let (mut callee, sig) = match callee.ty.sty { + ty::TyFnDef(def_id, substs, sig) => { + (Callee::def(bcx.ccx, def_id, substs), sig) } - ty::TyFnPtr(f) => { + ty::TyFnPtr(sig) => { (Callee { data: Fn(callee.immediate()), ty: callee.ty - }, f.abi, &f.sig) + }, sig) } _ => bug!("{} is not callable", callee.ty) }; - let sig = bcx.tcx().erase_late_bound_regions_and_normalize(sig); + let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig); + let abi = sig.abi; // Handle intrinsics old trans wants Expr's for, ourselves. let intrinsic = match (&callee.ty.sty, &callee.data) { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 6a0e05803c355..a4e74f72a10eb 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -588,7 +588,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = tcx.closure_type(def_id, substs).sig.input(0); + let input = tcx.closure_type(def_id, substs).input(0); let substs = tcx.mk_substs([operand.ty, input.skip_binder()] .iter().cloned().map(Kind::from)); Callee::def(self.ccx, call_once, substs) diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 9714fc4e4bdf0..6419f41f86b6d 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -28,7 +28,6 @@ use type_of; use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos, Span}; use syntax::symbol::keywords; -use syntax::abi::Abi; use std::iter; @@ -205,15 +204,14 @@ impl<'tcx> LocalRef<'tcx> { pub fn trans_mir<'a, 'tcx: 'a>( ccx: &'a CrateContext<'a, 'tcx>, llfn: ValueRef, - fn_ty: FnType, mir: &'a Mir<'tcx>, instance: Instance<'tcx>, - sig: &ty::FnSig<'tcx>, - abi: Abi, + sig: ty::FnSig<'tcx>, ) { + let fn_ty = FnType::new(ccx, sig, &[]); debug!("fn_ty: {:?}", fn_ty); let debug_context = - debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfn, mir); + debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir); let bcx = Builder::new_block(ccx, llfn, "entry-block"); let cleanup_kinds = analyze::cleanup_kinds(&mir); diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index c3dffd476e133..4036d5152bb91 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = bcx.tcx().closure_type(def_id, substs).sig.input(0); + let input = bcx.tcx().closure_type(def_id, substs).input(0); let substs = bcx.tcx().mk_substs([operand.ty, input.skip_binder()] .iter().cloned().map(Kind::from)); OperandValue::Immediate( diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 04a6cb27501b3..d691fa6aadf2e 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -199,11 +199,17 @@ impl<'a, 'tcx> TransItem<'tcx> { assert_eq!(dg.ty(), glue::get_drop_glue_type(ccx.shared(), dg.ty())); let t = dg.ty(); - let sig = tcx.mk_fn_sig(iter::once(tcx.mk_mut_ptr(t)), tcx.mk_nil(), false); + let sig = tcx.mk_fn_sig( + iter::once(tcx.mk_mut_ptr(t)), + tcx.mk_nil(), + false, + hir::Unsafety::Normal, + Abi::Rust + ); debug!("predefine_drop_glue: sig={}", sig); - let fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]); + let fn_ty = FnType::new(ccx, sig, &[]); let llfnty = fn_ty.llvm_type(ccx); assert!(declare::get_defined_value(ccx, symbol_name).is_none()); @@ -457,12 +463,13 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output); } }, - ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | - ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { - if unsafety == hir::Unsafety::Unsafe { + ty::TyFnDef(.., sig) | + ty::TyFnPtr(sig) => { + if sig.unsafety() == hir::Unsafety::Unsafe { output.push_str("unsafe "); } + let abi = sig.abi(); if abi != ::abi::Abi::Rust { output.push_str("extern \""); output.push_str(abi.name()); @@ -471,7 +478,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push_str("fn("); - let sig = self.tcx.erase_late_bound_regions_and_normalize(sig); + let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig); if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 87af3b6c5e153..a5722e6e520d0 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -272,9 +272,9 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> ty::TyStr | ty::TyDynamic(..) => Type::i8(cx), ty::TyFnDef(..) => Type::nil(cx), - ty::TyFnPtr(f) => { - let sig = cx.tcx().erase_late_bound_regions_and_normalize(&f.sig); - FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to() + ty::TyFnPtr(sig) => { + let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig); + FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to() } ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx), ty::TyTuple(..) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ef0dcd4c774dd..8dc532894f355 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1116,10 +1116,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // warning then. (Once we fix #32330, the regions we are // checking for here would be considered early bound // anyway.) - let inputs = bare_fn_ty.sig.inputs(); + let inputs = bare_fn_ty.inputs(); let late_bound_in_args = tcx.collect_constrained_late_bound_regions( &inputs.map_bound(|i| i.to_owned())); - let output = bare_fn_ty.sig.output(); + let output = bare_fn_ty.output(); let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output); for br in late_bound_in_ret.difference(&late_bound_in_args) { let br_name = match *br { @@ -1272,7 +1272,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl) - -> &'tcx ty::BareFnTy<'tcx> { + -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); let input_tys: Vec = @@ -1285,15 +1285,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("ty_of_fn: output_ty={:?}", output_ty); - self.tcx().mk_bare_fn(ty::BareFnTy { - unsafety: unsafety, - abi: abi, - sig: ty::Binder(self.tcx().mk_fn_sig( - input_tys.into_iter(), - output_ty, - decl.variadic - )), - }) + ty::Binder(self.tcx().mk_fn_sig( + input_tys.into_iter(), + output_ty, + decl.variadic, + unsafety, + abi + )) } pub fn ty_of_closure(&self, @@ -1301,7 +1299,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { decl: &hir::FnDecl, abi: abi::Abi, expected_sig: Option>) - -> ty::ClosureTy<'tcx> + -> ty::PolyFnSig<'tcx> { debug!("ty_of_closure(expected_sig={:?})", expected_sig); @@ -1338,11 +1336,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("ty_of_closure: output_ty={:?}", output_ty); - ty::ClosureTy { - unsafety: unsafety, - abi: abi, - sig: ty::Binder(self.tcx().mk_fn_sig(input_tys, output_ty, decl.variadic)), - } + ty::Binder(self.tcx().mk_fn_sig( + input_tys, + output_ty, + decl.variadic, + unsafety, + abi + )) } /// Given the bounds on an object, determines what single region bound (if any) we can diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 8f1135adbb454..a253b223ef6ea 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -14,6 +14,7 @@ use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; use rustc::ty::{self, TyCtxt, LvaluePreference, Ty}; +use syntax::abi; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -112,7 +113,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let closure_ty = self.closure_type(def_id, substs); let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, - &closure_ty.sig) + &closure_ty) .0; self.record_deferred_call_resolution(def_id, Box::new(CallResolution { @@ -186,13 +187,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { arg_exprs: &'gcx [hir::Expr], expected: Expectation<'tcx>) -> Ty<'tcx> { - let error_fn_sig; - let (fn_sig, def_span) = match callee_ty.sty { - ty::TyFnDef(def_id, .., &ty::BareFnTy {ref sig, ..}) => { + ty::TyFnDef(def_id, .., sig) => { (sig, self.tcx.hir.span_if_local(def_id)) } - ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => (sig, None), + ty::TyFnPtr(sig) => (sig, None), ref t => { let mut unit_variant = None; if let &ty::TyAdt(adt_def, ..) = t { @@ -232,13 +231,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to // set up all the node type bindings. - error_fn_sig = ty::Binder(self.tcx.mk_fn_sig( + (ty::Binder(self.tcx.mk_fn_sig( self.err_args(arg_exprs.len()).into_iter(), self.tcx.types.err, false, - )); - - (&error_fn_sig, None) + hir::Unsafety::Normal, + abi::Abi::Rust + )), None) } }; @@ -248,7 +247,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // previously appeared within a `Binder<>` and hence would not // have been normalized before. let fn_sig = - self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, fn_sig) + self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig) .0; let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig); @@ -355,7 +354,7 @@ impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tc // (This always bites me, should find a way to // refactor it.) let method_sig = fcx.tcx - .no_late_bound_regions(method_callee.ty.fn_sig()) + .no_late_bound_regions(&method_callee.ty.fn_sig()) .unwrap(); debug!("attempt_resolution: method_callee={:?}", method_callee); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 7979edbf5e27a..51fbc5aab6cd1 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -55,11 +55,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected_sig); let expr_def_id = self.tcx.hir.local_def_id(expr.id); - let mut fn_ty = AstConv::ty_of_closure(self, - hir::Unsafety::Normal, - decl, - Abi::RustCall, - expected_sig); + let sig = AstConv::ty_of_closure(self, + hir::Unsafety::Normal, + decl, + Abi::RustCall, + expected_sig); // Create type variables (for now) to represent the transformed // types of upvars. These will be unified during the upvar @@ -74,32 +74,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type); let extent = self.tcx.region_maps.call_site_extent(expr.id, body.value.id); - let fn_sig = self.tcx.liberate_late_bound_regions(extent, &fn_ty.sig); + let fn_sig = self.tcx.liberate_late_bound_regions(extent, &sig); let fn_sig = self.inh.normalize_associated_types_in(body.value.span, body.value.id, &fn_sig); - check_fn(self, - hir::Unsafety::Normal, - expr.id, - &fn_sig, - decl, - expr.id, - body); + check_fn(self, fn_sig, decl, expr.id, body); // Tuple up the arguments and insert the resulting function type into // the `closures` table. - fn_ty.sig.0 = self.tcx.mk_fn_sig( - iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs(), false)), - fn_ty.sig.skip_binder().output(), - fn_ty.sig.variadic() - ); + let sig = sig.map_bound(|sig| self.tcx.mk_fn_sig( + iter::once(self.tcx.intern_tup(sig.inputs(), false)), + sig.output(), + sig.variadic, + sig.unsafety, + sig.abi + )); debug!("closure for {:?} --> sig={:?} opt_kind={:?}", expr_def_id, - fn_ty.sig, + sig, opt_kind); - self.tables.borrow_mut().closure_tys.insert(expr.id, fn_ty); + self.tables.borrow_mut().closure_tys.insert(expr.id, sig); match opt_kind { Some(kind) => { self.tables.borrow_mut().closure_kinds.insert(expr.id, kind); @@ -228,7 +224,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty); debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty); - let fn_sig = self.tcx.mk_fn_sig(input_tys.cloned(), ret_param_ty, false); + let fn_sig = self.tcx.mk_fn_sig( + input_tys.cloned(), + ret_param_ty, + false, + hir::Unsafety::Normal, + Abi::Rust + ); debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig); Some(fn_sig) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 424e3143929f4..ecde2e1afe9d8 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -507,11 +507,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_safe_fn(&self, a: Ty<'tcx>, - fn_ty_a: &'tcx ty::BareFnTy<'tcx>, + fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { if let ty::TyFnPtr(fn_ty_b) = b.sty { - match (fn_ty_a.unsafety, fn_ty_b.unsafety) { + match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) { (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); return self.unify_and_identity(unsafe_a, b) @@ -525,7 +525,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_fn_pointer(&self, a: Ty<'tcx>, - fn_ty_a: &'tcx ty::BareFnTy<'tcx>, + fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a Rust function item @@ -540,7 +540,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_from_fn_item(&self, a: Ty<'tcx>, - fn_ty_a: &'tcx ty::BareFnTy<'tcx>, + fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { //! Attempts to coerce from the type of a Rust function item @@ -587,7 +587,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` - let sig = self.closure_type(def_id_a, substs_a).sig; + let sig = self.closure_type(def_id_a, substs_a); let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { ty::TyTuple(params, _) => { @@ -595,16 +595,15 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } _ => bug!(), }; - self.tcx.mk_fn_sig(params_iter, - s.output(), - s.variadic) + self.tcx.mk_fn_sig( + params_iter, + s.output(), + s.variadic, + hir::Unsafety::Normal, + abi::Abi::Rust + ) }); - let fn_ty = self.tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: abi::Abi::Rust, - sig: converted_sig, - }); - let pointer_ty = self.tcx.mk_fn_ptr(&fn_ty); + let pointer_ty = self.tcx.mk_fn_ptr(converted_sig); debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty); self.unify_and_identity(pointer_ty, b) diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 2d4749331c08a..06cf653e29368 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -263,19 +263,17 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Compute skolemized form of impl and trait method tys. let tcx = infcx.tcx; - let m_fty = |method: &ty::AssociatedItem| { + let m_sig = |method: &ty::AssociatedItem| { match tcx.item_type(method.def_id).sty { ty::TyFnDef(_, _, f) => f, _ => bug!() } }; - let impl_m_fty = m_fty(impl_m); - let trait_m_fty = m_fty(trait_m); let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, - &impl_m_fty.sig); + &m_sig(impl_m)); let impl_sig = impl_sig.subst(tcx, impl_to_skol_substs); let impl_sig = @@ -284,16 +282,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_m_span, impl_m_body_id, &impl_sig); - let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: impl_m_fty.unsafety, - abi: impl_m_fty.abi, - sig: ty::Binder(impl_sig.clone()), - })); + let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions( infcx.parameter_environment.free_id_outlive, - &trait_m_fty.sig); + &m_sig(trait_m)); let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = @@ -302,11 +296,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_m_span, impl_m_body_id, &trait_sig); - let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: trait_m_fty.unsafety, - abi: trait_m_fty.abi, - sig: ty::Binder(trait_sig.clone()), - })); + let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -662,8 +652,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let impl_m_fty = m_fty(impl_m); let trait_m_fty = m_fty(trait_m); - let trait_number_args = trait_m_fty.sig.inputs().skip_binder().len(); - let impl_number_args = impl_m_fty.sig.inputs().skip_binder().len(); + let trait_number_args = trait_m_fty.inputs().skip_binder().len(); + let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { let trait_m_node_id = tcx.hir.as_local_node_id(trait_m.def_id); let trait_span = if let Some(trait_id) = trait_m_node_id { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index a77887cd221de..232c4c4db7c97 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -123,8 +123,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match method.def() { Def::Method(def_id) => { match self.tcx.item_type(def_id).sty { - ty::TypeVariants::TyFnDef(_, _, fty) => { - fty.sig.skip_binder().inputs().len() == 1 + ty::TypeVariants::TyFnDef(_, _, sig) => { + sig.inputs().skip_binder().len() == 1 } _ => false, } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4d4e312dab37c..28996b40cfdfe 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -39,11 +39,13 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, |_, _| tcx.mk_region(ty::ReErased), |def, _| tcx.mk_param_from_def(def)); - let fty = tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Unsafe, - abi: abi, - sig: ty::Binder(tcx.mk_fn_sig(inputs.into_iter(), output, false)), - })); + let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( + inputs.into_iter(), + output, + false, + hir::Unsafety::Unsafe, + abi + ))); let i_n_tps = tcx.item_generics(def_id).types.len(); if i_n_tps != n_tps { let span = match it.node { @@ -288,11 +290,13 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "try" => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); - let fn_ty = tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - sig: ty::Binder(tcx.mk_fn_sig(iter::once(mut_u8), tcx.mk_nil(), false)), - }); + let fn_ty = ty::Binder(tcx.mk_fn_sig( + iter::once(mut_u8), + tcx.mk_nil(), + false, + hir::Unsafety::Normal, + Abi::Rust, + )); (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32) } @@ -363,7 +367,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap(); let sig = tcx.item_type(def_id).fn_sig(); - let sig = tcx.no_late_bound_regions(sig).unwrap(); + let sig = tcx.no_late_bound_regions(&sig).unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, "platform-specific intrinsic has invalid number of \ diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 917607aab6b5a..e6e4b577bd50d 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -365,10 +365,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("method_predicates after subst = {:?}", method_predicates); - let fty = match self.tcx.item_type(def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - }; + let sig = self.tcx.item_type(def_id).fn_sig(); // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. @@ -376,21 +373,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let method_sig = self.replace_late_bound_regions_with_fresh_var(&fty.sig); + let method_sig = self.replace_late_bound_regions_with_fresh_var(&sig); debug!("late-bound lifetimes from method instantiated, method_sig={:?}", method_sig); let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig); debug!("type scheme substituted, method_sig={:?}", method_sig); - let method_ty = self.tcx.mk_fn_def(def_id, all_substs, - self.tcx.mk_bare_fn(ty::BareFnTy { - sig: ty::Binder(method_sig), - unsafety: fty.unsafety, - abi: fty.abi, - })); - - (method_ty, method_predicates) + (self.tcx.mk_fn_def(def_id, all_substs, ty::Binder(method_sig)), + method_predicates) } fn add_obligations(&mut self, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index eae8989bd342e..62438d87d1860 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -244,21 +244,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // `instantiate_type_scheme` can normalize associated types that // may reference those regions. let original_method_ty = tcx.item_type(def_id); - let fty = match original_method_ty.sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - }; + let fn_sig = original_method_ty.fn_sig(); let fn_sig = self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, - &fty.sig).0; + &fn_sig).0; let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig); let transformed_self_ty = fn_sig.inputs()[0]; let method_ty = tcx.mk_fn_def(def_id, trait_ref.substs, - tcx.mk_bare_fn(ty::BareFnTy { - sig: ty::Binder(fn_sig), - unsafety: fty.unsafety, - abi: fty.abi - })); + ty::Binder(fn_sig)); debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d2cd766fdf009..773fec1d87055 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -675,25 +675,21 @@ fn check_bare_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) { let body = tcx.hir.body(body_id); - let raw_fty = tcx.item_type(tcx.hir.local_def_id(fn_id)); - let fn_ty = match raw_fty.sty { - ty::TyFnDef(.., f) => f, - _ => span_bug!(body.value.span, "check_bare_fn: function type expected") - }; + let fn_sig = tcx.item_type(tcx.hir.local_def_id(fn_id)).fn_sig(); - check_abi(tcx, span, fn_ty.abi); + check_abi(tcx, span, fn_sig.abi()); Inherited::build(tcx, fn_id).enter(|inh| { // 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_sig = - fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs); + fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs); let fn_sig = inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig); let fn_sig = inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig); - let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body); + let fcx = check_fn(&inh, fn_sig, decl, fn_id, body); fcx.select_all_obligations_and_apply_defaults(); fcx.closure_analyze(body); @@ -783,9 +779,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { /// * ... /// * inherited: other fields inherited from the enclosing fn (if any) fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, - unsafety: hir::Unsafety, - unsafety_id: ast::NodeId, - fn_sig: &ty::FnSig<'tcx>, + fn_sig: ty::FnSig<'tcx>, decl: &'gcx hir::FnDecl, fn_id: ast::NodeId, body: &'gcx hir::Body) @@ -799,12 +793,17 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // in the case of function expressions, based on the outer context. let mut fcx = FnCtxt::new(inherited, None, body.value.id); let ret_ty = fn_sig.output(); - *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id); + *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType); fcx.ret_ty = fcx.instantiate_anon_types(&Some(ret_ty)); - fn_sig = fcx.tcx.mk_fn_sig(fn_sig.inputs().iter().cloned(), &fcx.ret_ty.unwrap(), - fn_sig.variadic); + fn_sig = fcx.tcx.mk_fn_sig( + fn_sig.inputs().iter().cloned(), + fcx.ret_ty.unwrap(), + fn_sig.variadic, + fn_sig.unsafety, + fn_sig.abi + ); GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); @@ -2393,13 +2392,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expected_arg_tys = self.expected_types_for_fn_args( sp, expected, - fty.sig.0.output(), - &fty.sig.0.inputs()[1..] + fty.0.output(), + &fty.0.inputs()[1..] ); - self.check_argument_types(sp, &fty.sig.0.inputs()[1..], &expected_arg_tys[..], - args_no_rcvr, fty.sig.0.variadic, tuple_arguments, + self.check_argument_types(sp, &fty.0.inputs()[1..], &expected_arg_tys[..], + args_no_rcvr, fty.0.variadic, tuple_arguments, self.tcx.hir.span_if_local(def_id)); - fty.sig.0.output() + fty.0.output() } _ => { span_bug!(callee_expr.span, "method without bare fn type"); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index a120e3c343155..e1067d299fa01 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -927,7 +927,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // was applied on the base type, as that is always the case. let fn_sig = method.ty.fn_sig(); let fn_sig = // late-bound regions should have been instantiated - self.tcx.no_late_bound_regions(fn_sig).unwrap(); + self.tcx.no_late_bound_regions(&fn_sig).unwrap(); let self_ty = fn_sig.inputs()[0]; let (m, r) = match self_ty.sty { ty::TyRef(r, ref m) => (m.mutbl, r), diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 533223546ad56..a4cb4071b4d88 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -182,11 +182,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let method_ty = fcx.tcx.item_type(item.def_id); let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty); let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs); - let fty = match method_ty.sty { - ty::TyFnDef(_, _, f) => f, - _ => bug!() - }; - this.check_fn_or_method(fcx, span, fty, &predicates, + let sig = method_ty.fn_sig(); + this.check_fn_or_method(fcx, span, sig, &predicates, free_id_outlive, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); this.check_method_receiver(fcx, sig_if_method, &item, @@ -339,18 +336,13 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let def_id = fcx.tcx.hir.local_def_id(item.id); let ty = fcx.tcx.item_type(def_id); let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &ty); - let bare_fn_ty = match item_ty.sty { - ty::TyFnDef(.., ref bare_fn_ty) => bare_fn_ty, - _ => { - span_bug!(item.span, "Fn item without fn type"); - } - }; + let sig = item_ty.fn_sig(); let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs); let mut implied_bounds = vec![]; let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id); - this.check_fn_or_method(fcx, item.span, bare_fn_ty, &predicates, + this.check_fn_or_method(fcx, item.span, sig, &predicates, free_id_outlive, &mut implied_bounds); implied_bounds }) @@ -435,14 +427,14 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fn check_fn_or_method<'fcx, 'tcx>(&mut self, fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, span: Span, - fty: &'tcx ty::BareFnTy<'tcx>, + sig: ty::PolyFnSig<'tcx>, predicates: &ty::InstantiatedPredicates<'tcx>, free_id_outlive: CodeExtent, implied_bounds: &mut Vec>) { let free_substs = &fcx.parameter_environment.free_substs; - let fty = fcx.instantiate_type_scheme(span, free_substs, &fty); - let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig); + let sig = fcx.instantiate_type_scheme(span, free_substs, &sig); + let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &sig); for input_ty in sig.inputs() { fcx.register_wf_obligation(&input_ty, span, self.code.clone()); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ff9c1cc7d3656..1f7772fb9aa65 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -739,11 +739,13 @@ fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, CtorKind::Fn => { let inputs = variant.fields.iter().map(|field| tcx.item_type(field.did)); let substs = mk_item_substs(tcx, def_id); - tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: abi::Abi::Rust, - sig: ty::Binder(tcx.mk_fn_sig(inputs, ty, false)) - })) + tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust + ))) } }; tcx.maps.ty.borrow_mut().insert(def_id, ctor_ty); @@ -1682,11 +1684,11 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( .emit(); } }; - for (input, ty) in decl.inputs.iter().zip(*fty.sig.inputs().skip_binder()) { + for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) { check(&input, ty) } if let hir::Return(ref ty) = decl.output { - check(&ty, *fty.sig.output().skip_binder()) + check(&ty, *fty.output().skip_binder()) } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c3c1952415b90..009a0b92d882c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -196,11 +196,14 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let substs = tcx.intern_substs(&[]); let se_ty = tcx.mk_fn_def(main_def_id, substs, - tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - sig: ty::Binder(tcx.mk_fn_sig(iter::empty(), tcx.mk_nil(), false)) - })); + ty::Binder(tcx.mk_fn_sig( + iter::empty(), + tcx.mk_nil(), + false, + hir::Unsafety::Normal, + Abi::Rust + )) + ); require_same_types( tcx, @@ -243,18 +246,17 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let substs = tcx.intern_substs(&[]); let se_ty = tcx.mk_fn_def(start_def_id, substs, - tcx.mk_bare_fn(ty::BareFnTy { - unsafety: hir::Unsafety::Normal, - abi: Abi::Rust, - sig: ty::Binder(tcx.mk_fn_sig( + ty::Binder(tcx.mk_fn_sig( [ tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)) ].iter().cloned(), tcx.types.isize, false, - )), - })); + hir::Unsafety::Normal, + Abi::Rust + )) + ); require_same_types( tcx, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 3d2b746b85548..f0f543fa6f23b 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -411,8 +411,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - ty::TyFnDef(.., &ty::BareFnTy { ref sig, .. }) | - ty::TyFnPtr(&ty::BareFnTy { ref sig, .. }) => { + ty::TyFnDef(.., sig) | + ty::TyFnPtr(sig) => { self.add_constraints_from_sig(generics, sig, variance); } @@ -465,7 +465,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// `sig` appearing in a context with ambient variance `variance` fn add_constraints_from_sig(&mut self, generics: &ty::Generics, - sig: &ty::PolyFnSig<'tcx>, + sig: ty::PolyFnSig<'tcx>, variance: VarianceTermPtr<'a>) { let contra = self.contravariant(variance); for &input in sig.0.inputs() { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 02d934783d464..61c2a3c9e9512 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -164,11 +164,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { } fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { - let ty = cx.tcx.item_type(did); - let (decl, style, abi) = match ty.sty { - ty::TyFnDef(.., ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi), - _ => panic!("bad function"), - }; + let sig = cx.tcx.item_type(did).fn_sig(); let constness = if cx.tcx.sess.cstore.is_const_fn(did) { hir::Constness::Const @@ -178,11 +174,11 @@ fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { let predicates = cx.tcx.item_predicates(did); clean::Function { - decl: decl, + decl: (did, sig).clean(cx), generics: (cx.tcx.item_generics(did), &predicates).clean(cx), - unsafety: style, + unsafety: sig.unsafety(), constness: constness, - abi: abi, + abi: sig.abi(), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cd94e3fd14a50..73b82fbad5dfd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1163,7 +1163,7 @@ impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) } } -impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { +impl<'a, 'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { fn clean(&self, cx: &DocContext) -> FnDecl { let (did, sig) = *self; let mut names = if cx.tcx.hir.as_local_node_id(did).is_some() { @@ -1352,11 +1352,8 @@ impl<'tcx> Clean for ty::AssociatedItem { ty::AssociatedKind::Method => { let generics = (cx.tcx.item_generics(self.def_id), &cx.tcx.item_predicates(self.def_id)).clean(cx); - let fty = match cx.tcx.item_type(self.def_id).sty { - ty::TyFnDef(_, _, f) => f, - _ => unreachable!() - }; - let mut decl = (self.def_id, &fty.sig).clean(cx); + let sig = cx.tcx.item_type(self.def_id).fn_sig(); + let mut decl = (self.def_id, sig).clean(cx); if self.method_has_self_argument { let self_ty = match self.container { @@ -1365,7 +1362,7 @@ impl<'tcx> Clean for ty::AssociatedItem { } ty::TraitContainer(_) => cx.tcx.mk_self_type() }; - let self_arg_ty = *fty.sig.input(0).skip_binder(); + let self_arg_ty = *sig.input(0).skip_binder(); if self_arg_ty == self_ty { decl.inputs.values[0].type_ = Generic(String::from("Self")); } else if let ty::TyRef(_, mt) = self_arg_ty.sty { @@ -1386,20 +1383,20 @@ impl<'tcx> Clean for ty::AssociatedItem { }; if provided { MethodItem(Method { - unsafety: fty.unsafety, + unsafety: sig.unsafety(), generics: generics, decl: decl, - abi: fty.abi, + abi: sig.abi(), // trait methods canot (currently, at least) be const constness: hir::Constness::NotConst, }) } else { TyMethodItem(TyMethod { - unsafety: fty.unsafety, + unsafety: sig.unsafety(), generics: generics, decl: decl, - abi: fty.abi, + abi: sig.abi(), }) } } @@ -1834,16 +1831,16 @@ impl<'tcx> Clean for ty::Ty<'tcx> { mutability: mt.mutbl.clean(cx), type_: box mt.ty.clean(cx), }, - ty::TyFnDef(.., ref fty) | - ty::TyFnPtr(ref fty) => BareFunction(box BareFunctionDecl { - unsafety: fty.unsafety, + ty::TyFnDef(.., sig) | + ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl { + unsafety: sig.unsafety(), generics: Generics { lifetimes: Vec::new(), type_params: Vec::new(), where_predicates: Vec::new() }, - decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), &fty.sig).clean(cx), - abi: fty.abi, + decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), + abi: sig.abi(), }), ty::TyAdt(def, substs) => { let did = def.did; From 3146ee86723e329ccfb23c6b72594dc96d8e9497 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 13 Feb 2017 23:26:32 +0200 Subject: [PATCH 10/17] rustc: simplify tcx.closure_type(...) as it can copy the cached values. --- src/librustc/infer/mod.rs | 12 ++++-------- src/librustc/middle/liveness.rs | 12 ++++++++---- src/librustc/traits/project.rs | 3 ++- src/librustc/traits/select.rs | 3 ++- src/librustc/ty/mod.rs | 12 ++---------- src/librustc_metadata/encoder.rs | 2 +- src/librustc_trans/callee.rs | 4 ++-- src/librustc_trans/common.rs | 3 ++- src/librustc_trans/mir/constant.rs | 5 +++-- src/librustc_trans/mir/rvalue.rs | 5 +++-- src/librustc_typeck/check/callee.rs | 3 ++- src/librustc_typeck/check/coercion.rs | 3 ++- 12 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index c9abcd38b95ad..d7f254df7538a 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1649,20 +1649,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(self.tcx.closure_kind(def_id)) } - pub fn closure_type(&self, - def_id: DefId, - substs: ty::ClosureSubsts<'tcx>) - -> ty::PolyFnSig<'tcx> - { + pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { if let InferTables::InProgress(tables) = self.tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { - if let Some(ty) = tables.borrow().closure_tys.get(&id) { - return ty.subst(self.tcx, substs.substs); + if let Some(&ty) = tables.borrow().closure_tys.get(&id) { + return ty; } } } - self.tcx.closure_type(def_id, substs) + self.tcx.closure_type(def_id) } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 28f9a23d4593c..a8c1559ae2373 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1432,12 +1432,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { body: &hir::Body) { let fn_ty = self.ir.tcx.item_type(self.ir.tcx.hir.local_def_id(id)); - let fn_ret = match fn_ty.sty { - ty::TyClosure(closure_def_id, substs) => - self.ir.tcx.closure_type(closure_def_id, substs).output(), - _ => fn_ty.fn_ret() + let fn_sig = match fn_ty.sty { + ty::TyClosure(closure_def_id, substs) => { + self.ir.tcx.closure_type(closure_def_id) + .subst(self.ir.tcx, substs.substs) + } + _ => fn_ty.fn_sig() }; + let fn_ret = fn_sig.output(); + // within the fn body, late-bound regions are liberated // and must outlive the *call-site* of the function. let fn_ret = diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 0d498ce1aa3f3..448a3166bd860 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1208,7 +1208,8 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let closure_typer = selcx.closure_typer(); - let closure_type = closure_typer.closure_type(vtable.closure_def_id, vtable.substs); + let closure_type = closure_typer.closure_type(vtable.closure_def_id) + .subst(selcx.tcx(), vtable.substs.substs); let Normalized { value: closure_type, obligations diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 98f814a54f848..e12ebb6d51576 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2779,7 +2779,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::PolyTraitRef<'tcx> { - let closure_type = self.infcx.closure_type(closure_def_id, substs); + let closure_type = self.infcx.closure_type(closure_def_id) + .subst(self.tcx(), substs.substs); let ty::Binder((trait_ref, _)) = self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), obligation.predicate.0.self_ty(), // (1) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c1f372a1c2970..01be42881462a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2467,16 +2467,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.maps.closure_kind(self, def_id) } - pub fn closure_type(self, - def_id: DefId, - substs: ClosureSubsts<'tcx>) - -> ty::PolyFnSig<'tcx> - { - if let Some(ty) = self.maps.closure_type.borrow().get(&def_id) { - return ty.subst(self, substs.substs); - } - - self.maps.closure_type(self, def_id).subst(self, substs.substs) + pub fn closure_type(self, def_id: DefId) -> ty::PolyFnSig<'tcx> { + self.maps.closure_type(self, def_id) } /// Given the def_id of an impl, return the def_id of the trait it implements. diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e101dc8cb5892..ed1cff31f2ff9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1096,7 +1096,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.maps.closure_type.borrow()[&def_id]), + ty: self.lazy(&tcx.closure_type(def_id)), }; Entry { diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 6a9531547c023..4925c9d547e9d 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -18,7 +18,7 @@ pub use self::CalleeData::*; use llvm::{self, ValueRef, get_params}; use rustc::hir::def_id::DefId; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Substs, Subst}; use rustc::traits; use abi::{Abi, FnType}; use attributes; @@ -306,7 +306,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>( let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty); // Make a version with the type of by-ref closure. - let sig = tcx.closure_type(def_id, substs); + let sig = tcx.closure_type(def_id).subst(tcx, substs.substs); let sig = tcx.erase_late_bound_regions_and_normalize(&sig); assert_eq!(sig.abi, Abi::RustCall); let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 5e858ce0e0cd3..1032da7ef75bb 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -29,6 +29,7 @@ use type_::Type; use value::Value; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::Layout; +use rustc::ty::subst::Subst; use rustc::traits::{self, SelectionContext, Reveal}; use rustc::hir; @@ -579,7 +580,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::TyFnPtr(sig) => sig, ty::TyClosure(def_id, substs) => { let tcx = ccx.tcx(); - let sig = tcx.closure_type(def_id, substs); + let sig = tcx.closure_type(def_id).subst(tcx, substs.substs); let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv); let env_ty = match tcx.closure_kind(def_id) { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index a4e74f72a10eb..1f595cae6a805 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -20,7 +20,7 @@ use rustc::mir; use rustc::mir::tcx::LvalueTy; use rustc::ty::{self, layout, Ty, TyCtxt, TypeFoldable}; use rustc::ty::cast::{CastTy, IntTy}; -use rustc::ty::subst::{Kind, Substs}; +use rustc::ty::subst::{Kind, Substs, Subst}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use {abi, adt, base, Disr, machine}; use callee::Callee; @@ -588,7 +588,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = tcx.closure_type(def_id, substs).input(0); + let input = tcx.closure_type(def_id) + .subst(tcx, substs.substs).input(0); let substs = tcx.mk_substs([operand.ty, input.skip_binder()] .iter().cloned().map(Kind::from)); Callee::def(self.ccx, call_once, substs) diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 4036d5152bb91..037c771c97b06 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -12,7 +12,7 @@ use llvm::{self, ValueRef}; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::Layout; -use rustc::ty::subst::Kind; +use rustc::ty::subst::{Kind, Subst}; use rustc::mir::tcx::LvalueTy; use rustc::mir; use middle::lang_items::ExchangeMallocFnLangItem; @@ -201,7 +201,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; // Now create its substs [Closure, Tuple] - let input = bcx.tcx().closure_type(def_id, substs).input(0); + let input = bcx.tcx().closure_type(def_id) + .subst(bcx.tcx(), substs.substs).input(0); let substs = bcx.tcx().mk_substs([operand.ty, input.skip_binder()] .iter().cloned().map(Kind::from)); OperandValue::Immediate( diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index a253b223ef6ea..4b88f5acf42da 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -14,6 +14,7 @@ use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; use rustc::ty::{self, TyCtxt, LvaluePreference, Ty}; +use rustc::ty::subst::Subst; use syntax::abi; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -110,7 +111,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // haven't yet decided on whether the closure is fn vs // fnmut vs fnonce. If so, we have to defer further processing. if self.closure_kind(def_id).is_none() { - let closure_ty = self.closure_type(def_id, substs); + let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs); let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &closure_ty) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index ecde2e1afe9d8..53759cc115d1c 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -72,6 +72,7 @@ use rustc::ty::{self, LvaluePreference, TypeAndMut, use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; +use rustc::ty::subst::Subst; use syntax::abi; use syntax::feature_gate; use util::common::indent; @@ -587,7 +588,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // `extern "rust-call" fn((arg0,arg1,...)) -> _` // to // `fn(arg0,arg1,...) -> _` - let sig = self.closure_type(def_id_a, substs_a); + let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs); let converted_sig = sig.map_bound(|s| { let params_iter = match s.inputs()[0].sty { ty::TyTuple(params, _) => { From 9c3c306800313a119d236e607209e831187e7501 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 14 Feb 2017 01:11:24 +0200 Subject: [PATCH 11/17] rustc_typeck: move the leaves (generics, trait_def, adt_def) to on-demand. --- src/librustc/util/ppaux.rs | 11 +- src/librustc_driver/driver.rs | 1 + src/librustc_typeck/astconv.rs | 15 +- src/librustc_typeck/check/mod.rs | 8 - src/librustc_typeck/collect.rs | 583 +++++++++++++++---------------- src/librustc_typeck/lib.rs | 5 + 6 files changed, 288 insertions(+), 335 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d0c0654b0383b..6323f1dc0d4c4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -750,16 +750,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { TyInfer(infer_ty) => write!(f, "{}", infer_ty), TyError => write!(f, "[type error]"), TyParam(ref param_ty) => write!(f, "{}", param_ty), - TyAdt(def, substs) => { - ty::tls::with(|tcx| { - if def.did.is_local() && - !tcx.maps.ty.borrow().contains_key(&def.did) { - write!(f, "{}<..>", tcx.item_path_str(def.did)) - } else { - parameterized(f, substs, def.did, &[]) - } - }) - } + TyAdt(def, substs) => parameterized(f, substs, def.did, &[]), TyDynamic(data, r) => { write!(f, "{}", data)?; let r = r.to_string(); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b80402a15f67d..96824d19b900d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -873,6 +873,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut local_providers = ty::maps::Providers::default(); mir::mir_map::provide(&mut local_providers); + typeck::provide(&mut local_providers); let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8dc532894f355..54a2c40322ea0 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -51,16 +51,9 @@ pub trait AstConv<'gcx, 'tcx> { /// A cache used for the result of `ast_ty_to_ty_cache` fn ast_ty_to_ty_cache(&self) -> &RefCell>>; - /// Returns the generic type and lifetime parameters for an item. - fn get_generics(&self, id: DefId) -> &'tcx ty::Generics; - /// Identify the type for an item, like a type alias, fn, or struct. fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx>; - /// Returns the `TraitDef` for a given trait. This allows you to - /// figure out the set of type parameters defined on the trait. - fn get_trait_def(&self, id: DefId) -> &'tcx ty::TraitDef; - /// Ensure that the super-predicates for the trait with the given /// id are available and also for the transitive set of /// super-predicates. @@ -248,7 +241,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - let decl_generics = self.get_generics(def_id); + let decl_generics = tcx.item_generics(def_id); let expected_num_region_params = decl_generics.regions.len(); let supplied_num_region_params = lifetimes.len(); if expected_num_region_params != supplied_num_region_params { @@ -485,7 +478,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); - let trait_def = self.get_trait_def(trait_def_id); + let trait_def = self.tcx().lookup_trait_def(trait_def_id); match trait_segment.parameters { hir::AngleBracketedParameters(_) => { @@ -1019,7 +1012,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let node_id = tcx.hir.as_local_node_id(did).unwrap(); let item_id = tcx.hir.get_parent_node(node_id); let item_def_id = tcx.hir.local_def_id(item_id); - let generics = self.get_generics(item_def_id); + let generics = tcx.item_generics(item_def_id); let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]; tcx.mk_param(index, tcx.hir.name(node_id)) } @@ -1186,7 +1179,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Create the anonymized type. if allow { let def_id = tcx.hir.local_def_id(ast_ty.id); - self.get_generics(def_id); + tcx.item_generics(def_id); let substs = Substs::identity_for_item(tcx, def_id); let ty = tcx.mk_anon(tcx.hir.local_def_id(ast_ty.id), substs); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 773fec1d87055..c6d3af547eb02 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1353,18 +1353,10 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { &self.ast_ty_to_ty_cache } - fn get_generics(&self, id: DefId) -> &'tcx ty::Generics { - self.tcx().item_generics(id) - } - fn get_item_type(&self, _: Span, id: DefId) -> Ty<'tcx> { self.tcx().item_type(id) } - fn get_trait_def(&self, id: DefId) -> &'tcx ty::TraitDef { - self.tcx().lookup_trait_def(id) - } - fn ensure_super_predicates(&self, _: Span, _: DefId) { // all super predicates are ensured during collect pass } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1f7772fb9aa65..68e42f5b27ad0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -68,6 +68,7 @@ use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; +use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; use rustc::dep_graph::DepNode; use util::common::MemoizationMap; @@ -95,6 +96,15 @@ pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.visit_all_item_likes_in_krate(DepNode::CollectItem, &mut visitor.as_deep_visitor()); } +pub fn provide(providers: &mut Providers) { + *providers = Providers { + generics, + trait_def, + adt_def, + ..*providers + }; +} + /////////////////////////////////////////////////////////////////////////// /// Context specific to some particular item. This is what implements @@ -189,7 +199,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { if let hir::ExprClosure(..) = expr.node { let def_id = self.tcx.hir.local_def_id(expr.id); - generics_of_def_id(self.tcx, def_id); + self.tcx.item_generics(def_id); type_of_def_id(self.tcx, def_id); } intravisit::walk_expr(self, expr); @@ -198,7 +208,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty) { if let hir::TyImplTrait(..) = ty.node { let def_id = self.tcx.hir.local_def_id(ty.id); - generics_of_def_id(self.tcx, def_id); + self.tcx.item_generics(def_id); } intravisit::walk_ty(self, ty); } @@ -244,26 +254,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { &self.tcx.ast_ty_to_ty_cache } - fn get_generics(&self, id: DefId) -> &'tcx ty::Generics { - generics_of_def_id(self.tcx, id) - } - fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx> { self.tcx.cycle_check(span, ty::maps::Query::ty(id), || { type_of_def_id(self.tcx, id) }) } - fn get_trait_def(&self, def_id: DefId) -> &'tcx ty::TraitDef { - let tcx = self.tcx; - - if let Some(trait_id) = tcx.hir.as_local_node_id(def_id) { - trait_def_of_item(self.tcx, tcx.hir.expect_item(trait_id)) - } else { - tcx.lookup_trait_def(def_id) - } - } - /// Ensure that the (transitive) super predicates for /// `trait_def_id` are available. This will report a cycle error /// if a trait `X` (transitively) extends itself in some form. @@ -362,7 +358,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { let param_id = tcx.hir.as_local_node_id(def_id).unwrap(); let param_owner = tcx.hir.ty_param_owner(param_id); let param_owner_def_id = tcx.hir.local_def_id(param_owner); - let generics = generics_of_def_id(tcx, param_owner_def_id); + let generics = tcx.item_generics(param_owner_def_id); let index = generics.type_param_to_index[&def_id.index]; let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id)); @@ -370,7 +366,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { let parent = if item_def_id == param_owner_def_id { None } else { - generics_of_def_id(tcx, item_def_id).parent + tcx.item_generics(item_def_id).parent }; let mut results = parent.map_or(vec![], |parent| { @@ -407,7 +403,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { if param_id == item_node_id { results.push(ty::TraitRef { def_id: item_def_id, - substs: mk_item_substs(tcx, item_def_id) + substs: Substs::identity_for_item(tcx, item_def_id) }.to_predicate()); } generics @@ -491,7 +487,7 @@ fn convert_field<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, field: &hir::StructField, ty_f: &'tcx ty::FieldDef) { - generics_of_def_id(tcx, ty_f.did); + tcx.item_generics(ty_f.did); let tt = ItemCtxt::new(tcx, ty_f.did).to_ty(&field.ty); tcx.maps.ty.borrow_mut().insert(ty_f.did, tt); tcx.maps.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { @@ -506,7 +502,7 @@ fn convert_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def_id = tcx.hir.local_def_id(id); let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), sig.unsafety, sig.abi, &sig.decl); - let substs = mk_item_substs(tcx, def_id); + let substs = Substs::identity_for_item(tcx, def_id); let fty = tcx.mk_fn_def(def_id, substs, fty); tcx.maps.ty.borrow_mut().insert(def_id, fty); @@ -597,7 +593,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { } } hir::ItemEnum(ref enum_definition, _) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); predicates_of_item(tcx, it); let ty = type_of_def_id(tcx, def_id); convert_enum_variant_types(tcx, @@ -617,7 +613,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { Some(trait_ref)); } hir::ItemImpl(.., ref opt_trait_ref, _, _) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); let selfty = type_of_def_id(tcx, def_id); let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { @@ -628,14 +624,14 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { predicates_of_item(tcx, it); }, hir::ItemTrait(..) => { - generics_of_def_id(tcx, def_id); - trait_def_of_item(tcx, it); + tcx.item_generics(def_id); + tcx.lookup_trait_def(def_id); icx.ensure_super_predicates(it.span, def_id); predicates_of_item(tcx, it); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); predicates_of_item(tcx, it); let ty = type_of_def_id(tcx, def_id); @@ -651,12 +647,12 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { }, hir::ItemTy(_, ref generics) => { ensure_no_ty_param_bounds(tcx, it.span, generics, "type"); - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); predicates_of_item(tcx, it); type_of_def_id(tcx, def_id); }, _ => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); predicates_of_item(tcx, it); type_of_def_id(tcx, def_id); }, @@ -671,7 +667,7 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item: &hir::T let def_id = tcx.hir.local_def_id(trait_item.id); match trait_item.node { hir::TraitItemKind::Const(ref ty, _) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); let ty = ItemCtxt::new(tcx, def_id).to_ty(&ty); convert_associated_const(tcx, TraitContainer(trait_def_id), @@ -680,7 +676,7 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item: &hir::T } hir::TraitItemKind::Type(_, ref opt_ty) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); let typ = opt_ty.as_ref().map(|ty| ItemCtxt::new(tcx, def_id).to_ty(&ty)); @@ -701,7 +697,7 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::Imp let def_id = tcx.hir.local_def_id(impl_item.id); match impl_item.node { hir::ImplItemKind::Const(ref ty, _) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); let ty = ItemCtxt::new(tcx, def_id).to_ty(&ty); convert_associated_const(tcx, ImplContainer(impl_def_id), @@ -710,7 +706,7 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::Imp } hir::ImplItemKind::Type(ref ty) => { - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); if tcx.impl_trait_ref(impl_def_id).is_none() { span_err!(tcx.sess, impl_item.span, E0202, @@ -733,12 +729,12 @@ fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant: &'tcx ty::VariantDef, ty: Ty<'tcx>) { let def_id = tcx.hir.local_def_id(ctor_id); - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); let ctor_ty = match variant.ctor_kind { CtorKind::Fictive | CtorKind::Const => ty, CtorKind::Fn => { let inputs = variant.fields.iter().map(|field| tcx.item_type(field.did)); - let substs = mk_item_substs(tcx, def_id); + let substs = Substs::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( inputs, ty, @@ -835,39 +831,62 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn convert_struct_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - it: &hir::Item, - def: &hir::VariantData) - -> &'tcx ty::AdtDef -{ - let did = tcx.hir.local_def_id(it.id); - // Use separate constructor id for unit/tuple structs and reuse did for braced structs. - let ctor_id = if !def.is_struct() { Some(tcx.hir.local_def_id(def.id())) } else { None }; - let variants = vec![convert_struct_variant(tcx, ctor_id.unwrap_or(did), it.name, - ty::VariantDiscr::Relative(0), def)]; - let adt = tcx.alloc_adt_def(did, AdtKind::Struct, variants, - ReprOptions::new(tcx, did)); - if let Some(ctor_id) = ctor_id { - // Make adt definition available through constructor id as well. - tcx.maps.adt_def.borrow_mut().insert(ctor_id, adt); - } +fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> &'tcx ty::AdtDef { + use rustc::hir::map::*; + use rustc::hir::*; - tcx.maps.adt_def.borrow_mut().insert(did, adt); - adt -} + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item = match tcx.hir.get(node_id) { + NodeItem(item) => item, -fn convert_union_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - it: &hir::Item, - def: &hir::VariantData) - -> &'tcx ty::AdtDef -{ - let did = tcx.hir.local_def_id(it.id); - let variants = vec![convert_struct_variant(tcx, did, it.name, - ty::VariantDiscr::Relative(0), def)]; + // Make adt definition available through constructor id as well. + NodeStructCtor(_) => { + return tcx.lookup_adt_def(tcx.hir.get_parent_did(node_id)); + } + + _ => bug!() + }; - let adt = tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(tcx, did)); - tcx.maps.adt_def.borrow_mut().insert(did, adt); - adt + let repr = ReprOptions::new(tcx, def_id); + let (kind, variants) = match item.node { + ItemEnum(ref def, _) => { + let mut distance_from_explicit = 0; + (AdtKind::Enum, def.variants.iter().map(|v| { + let did = tcx.hir.local_def_id(v.node.data.id()); + let discr = if let Some(e) = v.node.disr_expr { + distance_from_explicit = 0; + ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.node_id)) + } else { + ty::VariantDiscr::Relative(distance_from_explicit) + }; + distance_from_explicit += 1; + + convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data) + }).collect()) + } + ItemStruct(ref def, _) => { + // Use separate constructor id for unit/tuple structs and reuse did for braced structs. + let ctor_id = if !def.is_struct() { + Some(tcx.hir.local_def_id(def.id())) + } else { + None + }; + (AdtKind::Struct, vec![ + convert_struct_variant(tcx, ctor_id.unwrap_or(def_id), item.name, + ty::VariantDiscr::Relative(0), def) + ]) + } + ItemUnion(ref def, _) => { + (AdtKind::Union, vec![ + convert_struct_variant(tcx, def_id, item.name, + ty::VariantDiscr::Relative(0), def) + ]) + } + _ => bug!() + }; + tcx.alloc_adt_def(def_id, kind, variants, repr) } fn evaluate_disr_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -924,31 +943,6 @@ fn evaluate_disr_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn convert_enum_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - it: &hir::Item, - def: &hir::EnumDef) - -> &'tcx ty::AdtDef -{ - let mut distance_from_explicit = 0; - let variants = def.variants.iter().map(|v| { - let did = tcx.hir.local_def_id(v.node.data.id()); - let discr = if let Some(e) = v.node.disr_expr { - distance_from_explicit = 0; - ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.node_id)) - } else { - ty::VariantDiscr::Relative(distance_from_explicit) - }; - distance_from_explicit += 1; - - convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data) - }).collect(); - - let did = tcx.hir.local_def_id(it.id); - let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(tcx, did)); - tcx.maps.adt_def.borrow_mut().insert(did, adt); - adt -} - /// Ensures that the super-predicates of the trait with def-id /// trait_def_id are converted and stored. This also ensures that /// the transitive super-predicates are converted; @@ -1000,227 +994,221 @@ fn super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn trait_def_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef { - let def_id = tcx.hir.local_def_id(it.id); +fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> &'tcx ty::TraitDef { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item = tcx.hir.expect_item(node_id); - tcx.maps.trait_def.memoize(def_id, || { - let unsafety = match it.node { - hir::ItemTrait(unsafety, ..) => unsafety, - _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"), - }; + let unsafety = match item.node { + hir::ItemTrait(unsafety, ..) => unsafety, + _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), + }; - let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar"); - if paren_sugar && !tcx.sess.features.borrow().unboxed_closures { - let mut err = tcx.sess.struct_span_err( - it.span, - "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ - which traits can use parenthetical notation"); - help!(&mut err, - "add `#![feature(unboxed_closures)]` to \ - the crate attributes to use it"); - err.emit(); - } + let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar"); + if paren_sugar && !tcx.sess.features.borrow().unboxed_closures { + let mut err = tcx.sess.struct_span_err( + item.span, + "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ + which traits can use parenthetical notation"); + help!(&mut err, + "add `#![feature(unboxed_closures)]` to \ + the crate attributes to use it"); + err.emit(); + } - let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx); - tcx.alloc_trait_def(ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash)) - }) + let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx); + tcx.alloc_trait_def(ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash)) } -fn generics_of_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> &'tcx ty::Generics { - let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { - id - } else { - return tcx.item_generics(def_id); - }; - tcx.maps.generics.memoize(def_id, || { - use rustc::hir::map::*; - use rustc::hir::*; +fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> &'tcx ty::Generics { + use rustc::hir::map::*; + use rustc::hir::*; - let node = tcx.hir.get(node_id); - let parent_def_id = match node { - NodeImplItem(_) | - NodeTraitItem(_) | - NodeVariant(_) | - NodeStructCtor(_) | - NodeField(_) => { - let parent_id = tcx.hir.get_parent(node_id); - Some(tcx.hir.local_def_id(parent_id)) - } - NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { - Some(tcx.closure_base_def_id(def_id)) - } - NodeTy(&hir::Ty { node: hir::TyImplTrait(..), .. }) => { - let mut parent_id = node_id; - loop { - match tcx.hir.get(parent_id) { - NodeItem(_) | NodeImplItem(_) | NodeTraitItem(_) => break, - _ => { - parent_id = tcx.hir.get_parent_node(parent_id); - } + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + + let node = tcx.hir.get(node_id); + let parent_def_id = match node { + NodeImplItem(_) | + NodeTraitItem(_) | + NodeVariant(_) | + NodeStructCtor(_) | + NodeField(_) => { + let parent_id = tcx.hir.get_parent(node_id); + Some(tcx.hir.local_def_id(parent_id)) + } + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + Some(tcx.closure_base_def_id(def_id)) + } + NodeTy(&hir::Ty { node: hir::TyImplTrait(..), .. }) => { + let mut parent_id = node_id; + loop { + match tcx.hir.get(parent_id) { + NodeItem(_) | NodeImplItem(_) | NodeTraitItem(_) => break, + _ => { + parent_id = tcx.hir.get_parent_node(parent_id); } } - Some(tcx.hir.local_def_id(parent_id)) } - _ => None - }; + Some(tcx.hir.local_def_id(parent_id)) + } + _ => None + }; - let mut opt_self = None; - let mut allow_defaults = false; + let mut opt_self = None; + let mut allow_defaults = false; - let no_generics = hir::Generics::empty(); - let ast_generics = match node { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => &sig.generics, - _ => &no_generics - } + let no_generics = hir::Generics::empty(); + let ast_generics = match node { + NodeTraitItem(item) => { + match item.node { + TraitItemKind::Method(ref sig, _) => &sig.generics, + _ => &no_generics } + } - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => &sig.generics, - _ => &no_generics - } + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => &sig.generics, + _ => &no_generics } + } - NodeItem(item) => { - match item.node { - ItemFn(.., ref generics, _) | - ItemImpl(_, _, ref generics, ..) => generics, - - ItemTy(_, ref generics) | - ItemEnum(_, ref generics) | - ItemStruct(_, ref generics) | - ItemUnion(_, ref generics) => { - allow_defaults = true; - generics - } - - ItemTrait(_, ref generics, ..) => { - // Add in the self type parameter. - // - // Something of a hack: use the node id for the trait, also as - // the node id for the Self type parameter. - let param_id = item.id; - - opt_self = Some(ty::TypeParameterDef { - index: 0, - name: keywords::SelfType.name(), - def_id: tcx.hir.local_def_id(param_id), - has_default: false, - object_lifetime_default: rl::Set1::Empty, - pure_wrt_drop: false, - }); - - allow_defaults = true; - generics - } + NodeItem(item) => { + match item.node { + ItemFn(.., ref generics, _) | + ItemImpl(_, _, ref generics, ..) => generics, + + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) | + ItemUnion(_, ref generics) => { + allow_defaults = true; + generics + } - _ => &no_generics + ItemTrait(_, ref generics, ..) => { + // Add in the self type parameter. + // + // Something of a hack: use the node id for the trait, also as + // the node id for the Self type parameter. + let param_id = item.id; + + opt_self = Some(ty::TypeParameterDef { + index: 0, + name: keywords::SelfType.name(), + def_id: tcx.hir.local_def_id(param_id), + has_default: false, + object_lifetime_default: rl::Set1::Empty, + pure_wrt_drop: false, + }); + + allow_defaults = true; + generics } + + _ => &no_generics } + } - NodeForeignItem(item) => { - match item.node { - ForeignItemStatic(..) => &no_generics, - ForeignItemFn(_, _, ref generics) => generics - } + NodeForeignItem(item) => { + match item.node { + ForeignItemStatic(..) => &no_generics, + ForeignItemFn(_, _, ref generics) => generics } + } - _ => &no_generics - }; + _ => &no_generics + }; - let has_self = opt_self.is_some(); - let mut parent_has_self = false; - let mut own_start = has_self as u32; - let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| { - let generics = generics_of_def_id(tcx, def_id); - assert_eq!(has_self, false); - parent_has_self = generics.has_self; - own_start = generics.count() as u32; - (generics.parent_regions + generics.regions.len() as u32, - generics.parent_types + generics.types.len() as u32) - }); + let has_self = opt_self.is_some(); + let mut parent_has_self = false; + let mut own_start = has_self as u32; + let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| { + let generics = tcx.item_generics(def_id); + assert_eq!(has_self, false); + parent_has_self = generics.has_self; + own_start = generics.count() as u32; + (generics.parent_regions + generics.regions.len() as u32, + generics.parent_types + generics.types.len() as u32) + }); - let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); - let regions = early_lifetimes.enumerate().map(|(i, l)| { - let issue_32330 = tcx.named_region_map.issue_32330 - .get(&l.lifetime.id) - .cloned(); - ty::RegionParameterDef { - name: l.lifetime.name, - index: own_start + i as u32, - def_id: tcx.hir.local_def_id(l.lifetime.id), - pure_wrt_drop: l.pure_wrt_drop, - issue_32330: issue_32330, - } - }).collect::>(); + let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); + let regions = early_lifetimes.enumerate().map(|(i, l)| { + let issue_32330 = tcx.named_region_map.issue_32330.get(&l.lifetime.id).cloned(); + ty::RegionParameterDef { + name: l.lifetime.name, + index: own_start + i as u32, + def_id: tcx.hir.local_def_id(l.lifetime.id), + pure_wrt_drop: l.pure_wrt_drop, + issue_32330: issue_32330, + } + }).collect::>(); - let object_lifetime_defaults = - tcx.named_region_map.object_lifetime_defaults.get(&node_id); + let object_lifetime_defaults = + tcx.named_region_map.object_lifetime_defaults.get(&node_id); - // Now create the real type parameters. - let type_start = own_start + regions.len() as u32; - let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { - if p.name == keywords::SelfType.name() { - span_bug!(p.span, "`Self` should not be the name of a regular parameter"); - } + // Now create the real type parameters. + let type_start = own_start + regions.len() as u32; + let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { + if p.name == keywords::SelfType.name() { + span_bug!(p.span, "`Self` should not be the name of a regular parameter"); + } - if !allow_defaults && p.default.is_some() { - if !tcx.sess.features.borrow().default_type_parameter_fallback { - tcx.sess.add_lint( - lint::builtin::INVALID_TYPE_PARAM_DEFAULT, - p.id, - p.span, - format!("defaults for type parameters are only allowed in `struct`, \ - `enum`, `type`, or `trait` definitions.")); - } + if !allow_defaults && p.default.is_some() { + if !tcx.sess.features.borrow().default_type_parameter_fallback { + tcx.sess.add_lint( + lint::builtin::INVALID_TYPE_PARAM_DEFAULT, + p.id, + p.span, + format!("defaults for type parameters are only allowed in `struct`, \ + `enum`, `type`, or `trait` definitions.")); } + } - ty::TypeParameterDef { + ty::TypeParameterDef { + index: type_start + i as u32, + name: p.name, + def_id: tcx.hir.local_def_id(p.id), + has_default: p.default.is_some(), + object_lifetime_default: + object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]), + pure_wrt_drop: p.pure_wrt_drop, + } + }); + let mut types: Vec<_> = opt_self.into_iter().chain(types).collect(); + + // provide junk type parameter defs - the only place that + // cares about anything but the length is instantiation, + // and we don't do that for closures. + if let NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) = node { + tcx.with_freevars(node_id, |fv| { + types.extend(fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef { index: type_start + i as u32, - name: p.name, - def_id: tcx.hir.local_def_id(p.id), - has_default: p.default.is_some(), - object_lifetime_default: - object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]), - pure_wrt_drop: p.pure_wrt_drop, - } + name: Symbol::intern(""), + def_id: def_id, + has_default: false, + object_lifetime_default: rl::Set1::Empty, + pure_wrt_drop: false, + })); }); - let mut types: Vec<_> = opt_self.into_iter().chain(types).collect(); - - // provide junk type parameter defs - the only place that - // cares about anything but the length is instantiation, - // and we don't do that for closures. - if let NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) = node { - tcx.with_freevars(node_id, |fv| { - types.extend(fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef { - index: type_start + i as u32, - name: Symbol::intern(""), - def_id: def_id, - has_default: false, - object_lifetime_default: rl::Set1::Empty, - pure_wrt_drop: false, - })); - }); - } + } - let mut type_param_to_index = BTreeMap::new(); - for param in &types { - type_param_to_index.insert(param.def_id.index, param.index); - } + let mut type_param_to_index = BTreeMap::new(); + for param in &types { + type_param_to_index.insert(param.def_id.index, param.index); + } - tcx.alloc_generics(ty::Generics { - parent: parent_def_id, - parent_regions: parent_regions, - parent_types: parent_types, - regions: regions, - types: types, - type_param_to_index: type_param_to_index, - has_self: has_self || parent_has_self - }) + tcx.alloc_generics(ty::Generics { + parent: parent_def_id, + parent_regions: parent_regions, + parent_types: parent_types, + regions: regions, + types: types, + type_param_to_index: type_param_to_index, + has_self: has_self || parent_has_self }) } @@ -1237,7 +1225,7 @@ fn type_of_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, use rustc::hir::*; // Alway bring in generics, as computing the type needs them. - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); let icx = ItemCtxt::new(tcx, def_id); @@ -1250,22 +1238,14 @@ fn type_of_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } ItemFn(ref decl, unsafety, _, abi, _, _) => { let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); - let substs = mk_item_substs(tcx, def_id); + let substs = Substs::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs, tofd) } - ItemEnum(ref ei, _) => { - let def = convert_enum_def(tcx, item, ei); - let substs = mk_item_substs(tcx, def_id); - tcx.mk_adt(def, substs) - } - ItemStruct(ref si, _) => { - let def = convert_struct_def(tcx, item, si); - let substs = mk_item_substs(tcx, def_id); - tcx.mk_adt(def, substs) - } - ItemUnion(ref un, _) => { - let def = convert_union_def(tcx, item, un); - let substs = mk_item_substs(tcx, def_id); + ItemEnum(..) | + ItemStruct(..) | + ItemUnion(..) => { + let def = tcx.lookup_adt_def(def_id); + let substs = Substs::identity_for_item(tcx, def_id); tcx.mk_adt(def, substs) } ItemDefaultImpl(..) | @@ -1337,7 +1317,7 @@ fn convert_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // moral failing, but at the moment it seems like the only // convenient way to extract the ABI. - ndm let def_id = tcx.hir.local_def_id(it.id); - generics_of_def_id(tcx, def_id); + tcx.item_generics(def_id); type_of_def_id(tcx, def_id); let no_generics = hir::Generics::empty(); @@ -1413,7 +1393,7 @@ fn ty_generic_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ast_generics: &hir::Generics) { let icx = ItemCtxt::new(tcx, def_id); - let generics = generics_of_def_id(tcx, def_id); + let generics = tcx.item_generics(def_id); let parent_count = generics.parent_count() as u32; let has_own_self = generics.has_self && parent_count == 0; @@ -1426,7 +1406,7 @@ fn ty_generic_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir::ItemTrait(.., ref items) => { (Some((ty::TraitRef { def_id: def_id, - substs: mk_item_substs(tcx, def_id) + substs: Substs::identity_for_item(tcx, def_id) }, items)), None) } hir::ItemImpl(..) => { @@ -1692,15 +1672,6 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = mk_item_substs(tcx, def_id); + let substs = Substs::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs, fty) } - -fn mk_item_substs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> &'tcx Substs<'tcx> { - // FIXME(eddyb) Do this request from Substs::for_item in librustc. - generics_of_def_id(tcx, def_id); - - Substs::identity_for_item(tcx, def_id) -} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 009a0b92d882c..8e6e83bf3013f 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -110,6 +110,7 @@ use hir::map as hir_map; use rustc::infer::InferOk; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::maps::Providers; use rustc::traits::{ObligationCause, ObligationCauseCode, Reveal}; use session::config; use util::common::time; @@ -284,6 +285,10 @@ fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } } +pub fn provide(providers: &mut Providers) { + collect::provide(providers); +} + pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), usize> { let time_passes = tcx.sess.time_passes(); From ba11640179bbde334b525146d3a164999412cc73 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 14 Feb 2017 11:32:00 +0200 Subject: [PATCH 12/17] rustc_typeck: hook up collect and item/body check to on-demand. --- src/librustc/middle/dead.rs | 7 +- src/librustc/mir/tcx.rs | 4 +- src/librustc/traits/fulfill.rs | 139 +-- src/librustc/traits/mod.rs | 1 - src/librustc/traits/select.rs | 11 +- src/librustc/traits/structural_impls.rs | 27 - src/librustc/ty/context.rs | 22 +- src/librustc/ty/layout.rs | 9 +- src/librustc/ty/maps.rs | 84 +- src/librustc/ty/mod.rs | 104 +-- src/librustc/ty/sty.rs | 2 +- src/librustc/ty/util.rs | 15 - .../borrowck/mir/elaborate_drops.rs | 4 +- src/librustc_const_eval/eval.rs | 6 +- .../persist/dirty_clean.rs | 6 + src/librustc_lint/types.rs | 56 +- src/librustc_metadata/cstore_impl.rs | 1 + src/librustc_metadata/decoder.rs | 15 +- src/librustc_metadata/encoder.rs | 4 +- src/librustc_mir/build/matches/test.rs | 4 +- src/librustc_typeck/astconv.rs | 88 +- src/librustc_typeck/check/method/mod.rs | 4 +- src/librustc_typeck/check/mod.rs | 306 +++---- src/librustc_typeck/check/writeback.rs | 54 +- src/librustc_typeck/check_unused.rs | 3 +- src/librustc_typeck/collect.rs | 791 +++++++++--------- src/librustc_typeck/lib.rs | 1 + src/libsyntax/attr.rs | 23 - src/libsyntax_ext/deriving/generic/mod.rs | 2 +- .../cycle-trait-default-type-trait.rs | 1 - .../impl-trait/auto-trait-leak.rs | 17 +- src/test/compile-fail/impl-trait/equality.rs | 17 - src/test/compile-fail/resolve-self-in-impl.rs | 2 +- src/test/incremental/hashes/enum_defs.rs | 5 +- .../run-pass/impl-trait/auto-trait-leak.rs | 13 - src/test/run-pass/impl-trait/equality.rs | 13 + 36 files changed, 773 insertions(+), 1088 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 592e4cb92359c..cc6d6e88dee4e 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -159,10 +159,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { hir_map::NodeItem(item) => { match item.node { hir::ItemStruct(..) | hir::ItemUnion(..) => { - self.struct_has_extern_repr = item.attrs.iter().any(|attr| { - attr::find_repr_attrs(self.tcx.sess.diagnostic(), attr) - .contains(&attr::ReprExtern) - }); + let def_id = self.tcx.hir.local_def_id(item.id); + let def = self.tcx.lookup_adt_def(def_id); + self.struct_has_extern_repr = def.repr.c; intravisit::walk_item(self, &item); } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 527f115277082..50a80305bee27 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -173,9 +173,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::Discriminant(ref lval) => { let ty = lval.ty(mir, tcx).to_ty(tcx); if let ty::TyAdt(adt_def, _) = ty.sty { - let repr_hints = tcx.lookup_repr_hints(adt_def.did); - let repr_type = tcx.enum_repr_type(repr_hints.get(0)); - Some(repr_type.to_ty(tcx)) + Some(adt_def.repr.discr_type().to_ty(tcx)) } else { // Undefined behaviour, bug for now; may want to return something for // the `discriminant` intrinsic later. diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index c31ab2372b69c..b87d18464377f 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -11,11 +11,9 @@ use dep_graph::DepGraph; use infer::{InferCtxt, InferOk}; use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate}; -use ty::subst::Subst; use rustc_data_structures::obligation_forest::{ObligationForest, Error}; use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor}; use std::marker::PhantomData; -use std::mem; use syntax::ast; use util::nodemap::{FxHashSet, NodeMap}; use hir::def_id::DefId; @@ -23,9 +21,8 @@ use hir::def_id::DefId; use super::CodeAmbiguity; use super::CodeProjectionError; use super::CodeSelectionError; -use super::{FulfillmentError, FulfillmentErrorCode, SelectionError}; -use super::{ObligationCause, BuiltinDerivedObligation}; -use super::{PredicateObligation, TraitObligation, Obligation}; +use super::{FulfillmentError, FulfillmentErrorCode}; +use super::{ObligationCause, PredicateObligation, Obligation}; use super::project; use super::select::SelectionContext; use super::Unimplemented; @@ -82,10 +79,6 @@ pub struct FulfillmentContext<'tcx> { // obligations (otherwise, it's easy to fail to walk to a // particular node-id). region_obligations: NodeMap>>, - - // A list of obligations that need to be deferred to - // a later time for them to be properly fulfilled. - deferred_obligations: Vec>, } #[derive(Clone)] @@ -101,100 +94,12 @@ pub struct PendingPredicateObligation<'tcx> { pub stalled_on: Vec>, } -/// An obligation which cannot be fulfilled in the context -/// it was registered in, such as auto trait obligations on -/// `impl Trait`, which require the concrete type to be -/// available, only guaranteed after finishing type-checking. -#[derive(Clone, Debug)] -pub struct DeferredObligation<'tcx> { - pub predicate: ty::PolyTraitPredicate<'tcx>, - pub cause: ObligationCause<'tcx> -} - -impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { - /// If possible, create a `DeferredObligation` from - /// a trait predicate which had failed selection, - /// but could succeed later. - pub fn from_select_error(tcx: TyCtxt<'a, 'gcx, 'tcx>, - obligation: &TraitObligation<'tcx>, - selection_err: &SelectionError<'tcx>) - -> Option> { - if let Unimplemented = *selection_err { - if DeferredObligation::must_defer(tcx, &obligation.predicate) { - return Some(DeferredObligation { - predicate: obligation.predicate.clone(), - cause: obligation.cause.clone() - }); - } - } - - None - } - - /// Returns true if the given trait predicate can be - /// fulfilled at a later time. - pub fn must_defer(tcx: TyCtxt<'a, 'gcx, 'tcx>, - predicate: &ty::PolyTraitPredicate<'tcx>) - -> bool { - // Auto trait obligations on `impl Trait`. - if tcx.trait_has_default_impl(predicate.def_id()) { - let substs = predicate.skip_binder().trait_ref.substs; - if substs.types().count() == 1 && substs.regions().next().is_none() { - if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty { - return true; - } - } - } - - false - } - - /// If possible, return the nested obligations required - /// to fulfill this obligation. - pub fn try_select(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) - -> Option>> { - if let ty::TyAnon(def_id, substs) = self.predicate.skip_binder().self_ty().sty { - let ty = if def_id.is_local() { - tcx.maps.ty.borrow().get(&def_id).cloned() - } else { - Some(tcx.item_type(def_id)) - }; - // We can resolve the `impl Trait` to its concrete type. - if let Some(concrete_ty) = ty.subst(tcx, substs) { - let predicate = ty::TraitRef { - def_id: self.predicate.def_id(), - substs: tcx.mk_substs_trait(concrete_ty, &[]) - }.to_predicate(); - - let original_obligation = Obligation::new(self.cause.clone(), - self.predicate.clone()); - let cause = original_obligation.derived_cause(BuiltinDerivedObligation); - return Some(vec![Obligation::new(cause, predicate)]); - } - } - - None - } - - /// Return the `PredicateObligation` this was created from. - pub fn to_obligation(&self) -> PredicateObligation<'tcx> { - let predicate = ty::Predicate::Trait(self.predicate.clone()); - Obligation::new(self.cause.clone(), predicate) - } - - /// Return an error as if this obligation had failed. - pub fn to_error(&self) -> FulfillmentError<'tcx> { - FulfillmentError::new(self.to_obligation(), CodeSelectionError(Unimplemented)) - } -} - impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. pub fn new() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), region_obligations: NodeMap(), - deferred_obligations: vec![], } } @@ -294,16 +199,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { { self.select_where_possible(infcx)?; - // Fail all of the deferred obligations that haven't - // been otherwise removed from the context. - let deferred_errors = self.deferred_obligations.iter() - .map(|d| d.to_error()); - let errors: Vec<_> = self.predicates.to_errors(CodeAmbiguity) .into_iter() .map(|e| to_fulfillment_error(e)) - .chain(deferred_errors) .collect(); if errors.is_empty() { Ok(()) @@ -324,10 +223,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { self.predicates.pending_obligations() } - pub fn take_deferred_obligations(&mut self) -> Vec> { - mem::replace(&mut self.deferred_obligations, vec![]) - } - /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it /// only attempts to select obligations that haven't been seen before. fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>) @@ -343,7 +238,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { let outcome = self.predicates.process_obligations(&mut FulfillProcessor { selcx: selcx, region_obligations: &mut self.region_obligations, - deferred_obligations: &mut self.deferred_obligations }); debug!("select: outcome={:?}", outcome); @@ -378,7 +272,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> { selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>, region_obligations: &'a mut NodeMap>>, - deferred_obligations: &'a mut Vec> } impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, 'tcx> { @@ -391,8 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, { process_predicate(self.selcx, obligation, - self.region_obligations, - self.deferred_obligations) + self.region_obligations) .map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] @@ -432,8 +324,7 @@ fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 't fn process_predicate<'a, 'gcx, 'tcx>( selcx: &mut SelectionContext<'a, 'gcx, 'tcx>, pending_obligation: &mut PendingPredicateObligation<'tcx>, - region_obligations: &mut NodeMap>>, - deferred_obligations: &mut Vec>) + region_obligations: &mut NodeMap>>) -> Result>>, FulfillmentErrorCode<'tcx>> { @@ -502,21 +393,7 @@ fn process_predicate<'a, 'gcx, 'tcx>( info!("selecting trait `{:?}` at depth {} yielded Err", data, obligation.recursion_depth); - let defer = DeferredObligation::from_select_error(selcx.tcx(), - &trait_obligation, - &selection_err); - if let Some(deferred_obligation) = defer { - if let Some(nested) = deferred_obligation.try_select(selcx.tcx()) { - Ok(Some(nested)) - } else { - // Pretend that the obligation succeeded, - // but record it for later. - deferred_obligations.push(deferred_obligation); - Ok(Some(vec![])) - } - } else { - Err(CodeSelectionError(selection_err)) - } + Err(CodeSelectionError(selection_err)) } } } @@ -714,12 +591,6 @@ impl<'a, 'gcx, 'tcx> GlobalFulfilledPredicates<'gcx> { // already has the required read edges, so we don't need // to add any more edges here. if data.is_global() { - // Don't cache predicates which were fulfilled - // by deferring them for later fulfillment. - if DeferredObligation::must_defer(tcx, data) { - return; - } - if let Some(data) = tcx.lift_to_global(data) { if self.set.insert(data.clone()) { debug!("add_if_global: global predicate `{:?}` added", data); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 58ab713ef2730..117e16da26c3f 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -31,7 +31,6 @@ pub use self::coherence::orphan_check; pub use self::coherence::overlapping_impls; pub use self::coherence::OrphanCheckErr; pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation}; -pub use self::fulfill::DeferredObligation; pub use self::project::MismatchedProjectionTypes; pub use self::project::{normalize, normalize_projection_type, Normalized}; pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal}; diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e12ebb6d51576..4c4ace0d8baf9 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1478,8 +1478,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // `assemble_candidates_from_object_ty`. } ty::TyParam(..) | - ty::TyProjection(..) | - ty::TyAnon(..) => { + ty::TyProjection(..) => { // In these cases, we don't know what the actual // type is. Therefore, we cannot break it down // into its constituent types. So we don't @@ -1902,7 +1901,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyDynamic(..) | ty::TyParam(..) | ty::TyProjection(..) | - ty::TyAnon(..) | ty::TyInfer(ty::TyVar(_)) | ty::TyInfer(ty::FreshTy(_)) | ty::TyInfer(ty::FreshIntTy(_)) | @@ -1947,6 +1945,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map(|f| f.ty(self.tcx(), substs)) .collect() } + + ty::TyAnon(def_id, substs) => { + // We can resolve the `impl Trait` to its concrete type, + // which enforces a DAG between the functions requiring + // the auto trait bounds in question. + vec![self.tcx().item_type(def_id).subst(self.tcx(), substs)] + } } } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index dedb126d7ff6d..717c171db2ac7 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -269,20 +269,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> { } } -impl<'a, 'tcx> Lift<'tcx> for traits::DeferredObligation<'a> { - type Lifted = traits::DeferredObligation<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - tcx.lift(&self.predicate).and_then(|predicate| { - tcx.lift(&self.cause).map(|cause| { - traits::DeferredObligation { - predicate: predicate, - cause: cause - } - }) - }) - } -} - // For trans only. impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { type Lifted = traits::Vtable<'tcx, ()>; @@ -589,16 +575,3 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCause<'tcx> { self.code.visit_with(visitor) } } - -impl<'tcx> TypeFoldable<'tcx> for traits::DeferredObligation<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::DeferredObligation { - predicate: self.predicate.fold_with(folder), - cause: self.cause.fold_with(folder) - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.predicate.visit_with(visitor) || self.cause.visit_with(visitor) - } -} diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f1945fd57ef64..318c866a59fbe 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -38,7 +38,6 @@ use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; use ty::inhabitedness::DefIdForest; use ty::maps; -use util::common::MemoizationMap; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; @@ -50,7 +49,6 @@ use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; use std::mem; use std::ops::Deref; -use std::rc::Rc; use std::iter; use std::cmp::Ordering; use syntax::abi; @@ -242,6 +240,10 @@ pub struct TypeckTables<'tcx> { /// Lints for the body of this fn generated by typeck. pub lints: lint::LintTable, + + /// Set of trait imports actually used in the method resolution. + /// This is used for warning unused imports. + pub used_trait_imports: DefIdSet, } impl<'tcx> TypeckTables<'tcx> { @@ -259,6 +261,7 @@ impl<'tcx> TypeckTables<'tcx> { fru_field_types: NodeMap(), cast_kinds: NodeMap(), lints: lint::LintTable::new(), + used_trait_imports: DefIdSet(), } } @@ -531,11 +534,6 @@ pub struct GlobalCtxt<'tcx> { /// shouldn't taint the common path (hence the RefCell). pub all_traits: RefCell>>, - /// 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>>>, - /// HIR Ty -> Ty lowering cache. pub ast_ty_to_ty_cache: RefCell>>, } @@ -734,7 +732,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { derive_macros: RefCell::new(NodeMap()), stability_interner: RefCell::new(FxHashSet()), all_traits: RefCell::new(None), - deferred_obligations: RefCell::new(NodeMap()), ast_ty_to_ty_cache: RefCell::new(NodeMap()), }, f) } @@ -1449,15 +1446,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from)) } - - /// Obtain the representation annotation for a struct definition. - pub fn lookup_repr_hints(self, did: DefId) -> Rc> { - self.maps.repr_hints.memoize(did, || { - Rc::new(self.get_attrs(did).iter().flat_map(|meta| { - attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter() - }).collect()) - }) - } } pub trait InternAs { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 5829ae195c941..3773796e47d47 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1147,7 +1147,7 @@ impl<'a, 'gcx, 'tcx> Layout { } // SIMD vector types. - ty::TyAdt(def, ..) if def.is_simd() => { + ty::TyAdt(def, ..) if def.repr.simd => { let element = ty.simd_type(tcx); match *element.layout(infcx)? { Scalar { value, .. } => { @@ -1227,9 +1227,8 @@ impl<'a, 'gcx, 'tcx> Layout { let fields = def.variants[0].fields.iter().map(|field| { field.ty(tcx, substs).layout(infcx) }).collect::, _>>()?; - let packed = tcx.lookup_packed(def.did); let layout = if def.is_union() { - let mut un = Union::new(dl, packed); + let mut un = Union::new(dl, def.repr.packed); un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?; UntaggedUnion { variants: un } } else { @@ -1353,9 +1352,7 @@ impl<'a, 'gcx, 'tcx> Layout { return Err(LayoutError::SizeOverflow(ty)); } - let repr_hints = tcx.lookup_repr_hints(def.did); - let repr_type = tcx.enum_repr_type(repr_hints.get(0)); - let typeck_ity = Integer::from_attr(dl, repr_type); + let typeck_ity = Integer::from_attr(dl, def.repr.discr_type()); if typeck_ity < min_ity { // It is a bug if Layout decided on a greater discriminant size than typeck for // some reason at this point (based on values discriminant can take on). Mostly diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 6958df093d0e8..ce4d1f5ec974c 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -14,28 +14,33 @@ use middle::const_val::ConstVal; use mir; use ty::{self, Ty, TyCtxt}; use util::common::MemoizationMap; -use util::nodemap::DefIdSet; use rustc_data_structures::indexed_vec::IndexVec; use std::cell::RefCell; use std::rc::Rc; -use syntax::attr; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; trait Key { fn map_crate(&self) -> CrateNum; + fn default_span(&self, tcx: TyCtxt) -> Span; } impl Key for DefId { fn map_crate(&self) -> CrateNum { self.krate } + fn default_span(&self, tcx: TyCtxt) -> Span { + tcx.def_span(*self) + } } impl Key for (DefId, DefId) { fn map_crate(&self) -> CrateNum { self.0.krate } + fn default_span(&self, tcx: TyCtxt) -> Span { + self.1.default_span(tcx) + } } trait Value<'tcx>: Sized { @@ -83,7 +88,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { err.emit(); } - pub fn cycle_check(self, span: Span, query: Query, compute: F) -> R + fn cycle_check(self, span: Span, query: Query, compute: F) -> R where F: FnOnce() -> R { { @@ -104,23 +109,28 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -impl Query { - fn describe(&self, tcx: TyCtxt) -> String { - match *self { - Query::ty(def_id) => { - format!("processing `{}`", tcx.item_path_str(def_id)) - } - Query::super_predicates(def_id) => { - format!("computing the supertraits of `{}`", - tcx.item_path_str(def_id)) - } - Query::type_param_predicates((_, def_id)) => { - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - format!("computing the bounds for type parameter `{}`", - tcx.hir.ty_param_name(id)) - } - _ => bug!("unexpected `{:?}`", self) - } +trait QueryDescription: DepTrackingMapConfig { + fn describe(tcx: TyCtxt, key: Self::Key) -> String; +} + +impl> QueryDescription for M { + default fn describe(tcx: TyCtxt, def_id: DefId) -> String { + format!("processing `{}`", tcx.item_path_str(def_id)) + } +} + +impl<'tcx> QueryDescription for queries::super_predicates<'tcx> { + fn describe(tcx: TyCtxt, def_id: DefId) -> String { + format!("computing the supertraits of `{}`", + tcx.item_path_str(def_id)) + } +} + +impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> { + fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String { + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + format!("computing the bounds for type parameter `{}`", + tcx.hir.ty_param_name(id)) } } @@ -152,6 +162,14 @@ macro_rules! define_maps { $($(#[$attr])* $name($K)),* } + impl Query { + pub fn describe(&self, tcx: TyCtxt) -> String { + match *self { + $(Query::$name(key) => queries::$name::describe(tcx, key)),* + } + } + } + pub mod queries { use std::marker::PhantomData; @@ -186,11 +204,22 @@ macro_rules! define_maps { } } - impl<$tcx> Maps<$tcx> { + impl<'a, $tcx, 'lcx> Maps<$tcx> { $($(#[$attr])* - pub fn $name<'a, 'lcx>(&self, tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V { + pub fn $name(&self, + tcx: TyCtxt<'a, $tcx, 'lcx>, + mut span: Span, + key: $K) -> $V { self.$name.memoize(key, || { - (self.providers[key.map_crate()].$name)(tcx.global_tcx(), key) + // FIXME(eddyb) Get more valid Span's on queries. + if span == DUMMY_SP { + span = key.default_span(tcx); + } + + tcx.cycle_check(span, Query::$name(key), || { + let provider = self.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + }) }) })* } @@ -246,9 +275,6 @@ define_maps! { <'tcx> /// Methods in these implementations don't need to be exported. pub inherent_impls: InherentImpls(DefId) -> Vec, - /// Caches the representation hints for struct definitions. - pub repr_hints: ReprHints(DefId) -> Rc>, - /// Maps from the def-id of a function/method or const/static /// to its MIR. Mutation is done at an item granularity to /// allow MIR optimization passes to function and still @@ -272,10 +298,6 @@ define_maps! { <'tcx> pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, - /// Set of trait imports actually used in the method resolution. - /// This is used for warning unused imports. - pub used_trait_imports: UsedTraitImports(DefId) -> DefIdSet, - /// Results of evaluating monomorphic constants embedded in /// other items, such as enum variant explicit discriminants. pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 01be42881462a..357d12bc4dd6c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1296,10 +1296,9 @@ bitflags! { const IS_DTORCK = 1 << 1, // is this a dtorck type? const IS_DTORCK_VALID = 1 << 2, const IS_PHANTOM_DATA = 1 << 3, - const IS_SIMD = 1 << 4, - const IS_FUNDAMENTAL = 1 << 5, - const IS_UNION = 1 << 6, - const IS_BOX = 1 << 7, + const IS_FUNDAMENTAL = 1 << 4, + const IS_UNION = 1 << 5, + const IS_BOX = 1 << 6, } } @@ -1384,18 +1383,29 @@ pub struct ReprOptions { impl ReprOptions { pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions { let mut ret = ReprOptions::default(); - let attrs = tcx.lookup_repr_hints(did); - for r in attrs.iter() { - match *r { - attr::ReprExtern => ret.c = true, - attr::ReprPacked => ret.packed = true, - attr::ReprSimd => ret.simd = true, - attr::ReprInt(i) => ret.int = Some(i), - attr::ReprAny => (), + + for attr in tcx.get_attrs(did).iter() { + for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) { + match r { + attr::ReprExtern => ret.c = true, + attr::ReprPacked => ret.packed = true, + attr::ReprSimd => ret.simd = true, + attr::ReprInt(i) => ret.int = Some(i), + } } } + + // FIXME(eddyb) This is deprecated and should be removed. + if tcx.has_attr(did, "simd") { + ret.simd = true; + } + ret } + + pub fn discr_type(&self) -> attr::IntType { + self.int.unwrap_or(attr::SignedInt(ast::IntTy::Is)) + } } impl<'a, 'gcx, 'tcx> AdtDef { @@ -1409,9 +1419,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { if attr::contains_name(&attrs, "fundamental") { flags = flags | AdtFlags::IS_FUNDAMENTAL; } - if tcx.lookup_simd(did) { - flags = flags | AdtFlags::IS_SIMD; - } if Some(did) == tcx.lang_items.phantom_data() { flags = flags | AdtFlags::IS_PHANTOM_DATA; } @@ -1500,11 +1507,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.flags.get().intersects(AdtFlags::IS_FUNDAMENTAL) } - #[inline] - pub fn is_simd(&self) -> bool { - self.flags.get().intersects(AdtFlags::IS_SIMD) - } - /// Returns true if this is PhantomData. #[inline] pub fn is_phantom_data(&self) -> bool { @@ -1584,8 +1586,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> impl Iterator + 'a { - let repr_hints = tcx.lookup_repr_hints(self.did); - let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx.global_tcx()); let mut prev_discr = None::; self.variants.iter().map(move |v| { @@ -1946,25 +1947,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn item_tables(self, def_id: DefId) -> &'gcx TypeckTables<'gcx> { - self.maps.typeck_tables.memoize(def_id, || { - if def_id.is_local() { - // Closures' tables come from their outermost function, - // as they are part of the same "inference environment". - let outer_def_id = self.closure_base_def_id(def_id); - if outer_def_id != def_id { - return self.item_tables(outer_def_id); - } - - bug!("No def'n found for {:?} in tcx.tables", def_id); - } - - // Cross-crate side-tables only exist alongside serialized HIR. - self.sess.cstore.maybe_get_item_body(self.global_tcx(), def_id).map(|_| { - self.maps.typeck_tables.borrow()[&def_id] - }).unwrap_or_else(|| { - bug!("tcx.item_tables({:?}): missing from metadata", def_id) - }) - }) + self.maps.typeck_tables(self, DUMMY_SP, def_id) } pub fn expr_span(self, id: NodeId) -> Span { @@ -2072,12 +2055,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized { - self.maps.custom_coerce_unsized_kind(self, did) + self.maps.custom_coerce_unsized_kind(self, DUMMY_SP, did) } pub fn associated_item(self, def_id: DefId) -> AssociatedItem { if !def_id.is_local() { - return self.maps.associated_item(self, def_id); + return self.maps.associated_item(self, DUMMY_SP, def_id); } self.maps.associated_item.memoize(def_id, || { @@ -2182,7 +2165,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn associated_item_def_ids(self, def_id: DefId) -> Rc> { if !def_id.is_local() { - return self.maps.associated_item_def_ids(self, def_id); + return self.maps.associated_item_def_ids(self, DUMMY_SP, def_id); } self.maps.associated_item_def_ids.memoize(def_id, || { @@ -2217,7 +2200,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the trait-ref corresponding to a given impl, or None if it is /// an inherent impl. pub fn impl_trait_ref(self, id: DefId) -> Option> { - self.maps.impl_trait_ref(self, id) + self.maps.impl_trait_ref(self, DUMMY_SP, id) } // Returns `ty::VariantDef` if `def` refers to a struct, @@ -2296,37 +2279,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If the given item is in an external crate, looks up its type and adds it to // the type cache. Returns the type parameters and type. pub fn item_type(self, did: DefId) -> Ty<'gcx> { - self.maps.ty(self, did) + self.maps.ty(self, DUMMY_SP, did) } /// Given the did of a trait, returns its canonical trait ref. pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef { - self.maps.trait_def(self, did) + self.maps.trait_def(self, DUMMY_SP, did) } /// Given the did of an ADT, return a reference to its definition. pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef { - self.maps.adt_def(self, did) + self.maps.adt_def(self, DUMMY_SP, did) } /// Given the did of an item, returns its generics. pub fn item_generics(self, did: DefId) -> &'gcx Generics { - self.maps.generics(self, did) + self.maps.generics(self, DUMMY_SP, did) } /// Given the did of an item, returns its full set of predicates. pub fn item_predicates(self, did: DefId) -> GenericPredicates<'gcx> { - self.maps.predicates(self, did) + self.maps.predicates(self, DUMMY_SP, did) } /// Given the did of a trait, returns its superpredicates. pub fn item_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> { - self.maps.super_predicates(self, did) + self.maps.super_predicates(self, DUMMY_SP, did) } /// Given the did of an item, returns its MIR, borrowed immutably. pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> { - self.maps.mir(self, did).borrow() + self.maps.mir(self, DUMMY_SP, did).borrow() } /// If `type_needs_drop` returns true, then `ty` is definitely @@ -2377,19 +2360,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.get_attrs(did).iter().any(|item| item.check_name(attr)) } - /// Determine whether an item is annotated with `#[repr(packed)]` - pub fn lookup_packed(self, did: DefId) -> bool { - self.lookup_repr_hints(did).contains(&attr::ReprPacked) - } - - /// Determine whether an item is annotated with `#[simd]` - pub fn lookup_simd(self, did: DefId) -> bool { - self.has_attr(did, "simd") - || self.lookup_repr_hints(did).contains(&attr::ReprSimd) - } - pub fn item_variances(self, item_id: DefId) -> Rc> { - self.maps.variances(self, item_id) + self.maps.variances(self, DUMMY_SP, item_id) } pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool { @@ -2464,11 +2436,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind { - self.maps.closure_kind(self, def_id) + self.maps.closure_kind(self, DUMMY_SP, def_id) } pub fn closure_type(self, def_id: DefId) -> ty::PolyFnSig<'tcx> { - self.maps.closure_type(self, def_id) + self.maps.closure_type(self, DUMMY_SP, def_id) } /// Given the def_id of an impl, return the def_id of the trait it implements. diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3d6c1da8830a7..aa2990679b6ac 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1077,7 +1077,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { #[inline] pub fn is_simd(&self) -> bool { match self.sty { - TyAdt(def, _) => def.is_simd(), + TyAdt(def, _) => def.repr.simd, _ => false } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index bda76550f341c..d1c22651a9e00 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -232,21 +232,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// Returns the IntType representation. - /// This used to ensure `int_ty` doesn't contain `usize` and `isize` - /// by converting them to their actual types. That doesn't happen anymore. - pub fn enum_repr_type(self, opt_hint: Option<&attr::ReprAttr>) -> attr::IntType { - match opt_hint { - // Feed in the given type - Some(&attr::ReprInt(int_t)) => int_t, - // ... but provide sensible default if none provided - // - // NB. Historically `fn enum_variants` generate i64 here, while - // rustc_typeck::check would generate isize. - _ => SignedInt(ast::IntTy::Is), - } - } - /// Returns the deeply last field of nested structures, or the same type, /// if not a structure at all. Corresponds to the only possible unsized /// field, and its type can be used to determine unsizing strategy. diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index c64b25032c9ef..f8c0044774a01 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -677,9 +677,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // Additionally, we do not want to switch on the // discriminant after it is free-ed, because that // way lies only trouble. - let repr_hints = self.tcx.lookup_repr_hints(adt.did); - let repr_type = self.tcx.enum_repr_type(repr_hints.get(0)); - let discr_ty = repr_type.to_ty(self.tcx); + let discr_ty = adt.repr.discr_type().to_ty(self.tcx); let discr = Lvalue::Local(self.patch.new_temp(discr_ty)); let switch_block = self.patch.new_block(BasicBlockData { statements: vec![ diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 967705c748161..eadb49a0731a4 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -902,8 +902,7 @@ fn infer<'a, 'tcx>(i: ConstInt, (&ty::TyUint(ity), i) => Err(TypeMismatch(ity.to_string(), i)), (&ty::TyAdt(adt, _), i) if adt.is_enum() => { - let hints = tcx.lookup_repr_hints(adt.did); - let int_ty = tcx.enum_repr_type(hints.iter().next()); + let int_ty = adt.repr.discr_type(); infer(i, tcx, &int_ty.to_ty(tcx).sty) }, (_, i) => Err(BadType(ConstVal::Integral(i))), @@ -1093,8 +1092,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind, }, None => Ok(Integral(Infer(n as u128))), Some(&ty::TyAdt(adt, _)) => { - let hints = tcx.lookup_repr_hints(adt.did); - let int_ty = tcx.enum_repr_type(hints.iter().next()); + let int_ty = adt.repr.discr_type(); infer(Infer(n as u128), tcx, &int_ty.to_ty(tcx).sty).map(Integral) }, Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit), diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index a0bcb54af320f..156f8b9e7c489 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -257,6 +257,12 @@ pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> { impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { fn visit_item(&mut self, item: &'tcx hir::Item) { self.check_item(item.id, item.span); + + if let hir::ItemEnum(ref def, _) = item.node { + for v in &def.variants { + self.check_item(v.node.data.id(), v.span); + } + } } fn visit_trait_item(&mut self, item: &hir::TraitItem) { diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index dd7f751338dcc..3301a98968ee8 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -381,6 +381,17 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, false } +fn is_ffi_safe(ty: attr::IntType) -> bool { + match ty { + attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) | + attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) | + attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) | + attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) | + attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => true, + attr::SignedInt(ast::IntTy::Is) | attr::UnsignedInt(ast::UintTy::Us) => false + } +} + impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Check if the given type is "ffi-safe" (has a stable, well-defined /// representation which can be exported to C code). @@ -406,7 +417,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct => { - if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { + if !def.repr.c { return FfiUnsafe("found struct without foreign-function-safe \ representation annotation in foreign module, \ consider adding a #[repr(C)] attribute to the type"); @@ -440,7 +451,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if all_phantom { FfiPhantom } else { FfiSafe } } AdtKind::Union => { - if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { + if !def.repr.c { return FfiUnsafe("found union without foreign-function-safe \ representation annotation in foreign module, \ consider adding a #[repr(C)] attribute to the type"); @@ -479,35 +490,28 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check for a repr() attribute to specify the size of the // discriminant. - let repr_hints = cx.lookup_repr_hints(def.did); - match &repr_hints[..] { - &[] => { - // Special-case types like `Option`. - if !is_repr_nullable_ptr(cx, def, substs) { - return FfiUnsafe("found enum without foreign-function-safe \ - representation annotation in foreign \ - module, consider adding a #[repr(...)] \ - attribute to the type"); - } + if !def.repr.c && def.repr.int.is_none() { + // Special-case types like `Option`. + if !is_repr_nullable_ptr(cx, def, substs) { + return FfiUnsafe("found enum without foreign-function-safe \ + representation annotation in foreign \ + module, consider adding a #[repr(...)] \ + attribute to the type"); } - &[ref hint] => { - if !hint.is_ffi_safe() { - // FIXME: This shouldn't be reachable: we should check - // this earlier. - return FfiUnsafe("enum has unexpected #[repr(...)] attribute"); - } - - // Enum with an explicitly sized discriminant; either - // a C-style enum or a discriminated union. + } - // The layout of enum variants is implicitly repr(C). - // FIXME: Is that correct? - } - _ => { + if let Some(int_ty) = def.repr.int { + if !is_ffi_safe(int_ty) { // FIXME: This shouldn't be reachable: we should check // this earlier. - return FfiUnsafe("enum has too many #[repr(...)] attributes"); + return FfiUnsafe("enum has unexpected #[repr(...)] attribute"); } + + // Enum with an explicitly sized discriminant; either + // a C-style enum or a discriminated union. + + // The layout of enum variants is implicitly repr(C). + // FIXME: Is that correct? } // Check the contained variants. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 770591bc17ad7..fc7b50f11da96 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -101,6 +101,7 @@ provide! { <'tcx> tcx, def_id, cdata mir } + typeck_tables => { cdata.item_body_tables(def_id.index, tcx) } closure_kind => { cdata.closure_kind(def_id.index) } closure_type => { cdata.closure_ty(def_id.index, tcx) } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0e92c492e4b0d..e81d752fde047 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -780,16 +780,19 @@ impl<'a, 'tcx> CrateMetadata { if self.is_proc_macro(id) { return None; } self.entry(id).ast.map(|ast| { let def_id = self.local_def_id(id); - let ast = ast.decode(self); - - let tables = ast.tables.decode((self, tcx)); - tcx.maps.typeck_tables.borrow_mut().insert(def_id, tcx.alloc_tables(tables)); - - let body = ast.body.decode((self, tcx)); + let body = ast.decode(self).body.decode(self); tcx.hir.intern_inlined_body(def_id, body) }) } + pub fn item_body_tables(&self, + id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::TypeckTables<'tcx> { + let ast = self.entry(id).ast.unwrap().decode(self); + tcx.alloc_tables(ast.tables.decode((self, tcx))) + } + pub fn item_body_nested_bodies(&self, id: DefIndex) -> BTreeMap { self.entry(id).ast.into_iter().flat_map(|ast| { ast.decode(self).nested_bodies.decode(self).map(|body| (body.id(), body)) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index ed1cff31f2ff9..f5fd7a152a87e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -36,7 +36,7 @@ use syntax::ast::{self, CRATE_NODE_ID}; use syntax::codemap::Spanned; use syntax::attr; use syntax::symbol::Symbol; -use syntax_pos; +use syntax_pos::{self, DUMMY_SP}; use rustc::hir::{self, PatKind}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -264,7 +264,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { discr: variant.discr, evaluated_discr: match variant.discr { ty::VariantDiscr::Explicit(def_id) => { - tcx.maps.monomorphic_const_eval.borrow()[&def_id].clone().ok() + tcx.maps.monomorphic_const_eval(tcx, DUMMY_SP, def_id).ok() } ty::VariantDiscr::Relative(_) => None }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 3256bdf9c25e3..fa8d7ffccde40 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -209,9 +209,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}", num_enum_variants, values, variants); - let repr_hints = tcx.lookup_repr_hints(adt_def.did); - let repr_type = tcx.enum_repr_type(repr_hints.get(0)); - let discr_ty = repr_type.to_ty(tcx); + let discr_ty = adt_def.repr.discr_type().to_ty(tcx); let discr = self.temp(discr_ty); self.cfg.push_assign(block, source_info, &discr, Rvalue::Discriminant(lvalue.clone())); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 54a2c40322ea0..2d373ca7473e5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -11,17 +11,6 @@ //! Conversion from AST representation of types to the ty.rs //! representation. The main routine here is `ast_ty_to_ty()`: each use //! is parameterized by an instance of `AstConv`. -//! -//! The parameterization of `ast_ty_to_ty()` is because it behaves -//! somewhat differently during the collect and check phases, -//! particularly with respect to looking up the types of top-level -//! items. In the collect phase, the crate context is used as the -//! `AstConv` instance; in this phase, the `get_item_type()` -//! function triggers a recursive call to `type_of_item()` -//! (note that `ast_ty_to_ty()` will detect recursive types and report -//! an error). In the check phase, when the FnCtxt is used as the -//! `AstConv`, `get_item_type()` just looks up the item type in -//! `tcx.types` (using `TyCtxt::item_type`). use rustc_const_eval::eval_length; use rustc_data_structures::accumulate_vec::AccumulateVec; @@ -51,18 +40,10 @@ pub trait AstConv<'gcx, 'tcx> { /// A cache used for the result of `ast_ty_to_ty_cache` fn ast_ty_to_ty_cache(&self) -> &RefCell>>; - /// Identify the type for an item, like a type alias, fn, or struct. - fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx>; - - /// Ensure that the super-predicates for the trait with the given - /// id are available and also for the transitive set of - /// super-predicates. - fn ensure_super_predicates(&self, span: Span, id: DefId); - /// Returns the set of bounds in scope for the type parameter with /// the given id. fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> Vec>; + -> ty::GenericPredicates<'tcx>; /// Return an (optional) substitution to convert bound type parameters that /// are in scope into free ones. This function should only return Some @@ -262,7 +243,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let default_needs_object_self = |p: &ty::TypeParameterDef| { if is_object && p.has_default { - if self.get_item_type(span, p.def_id).has_self_ty() { + if tcx.maps.ty(tcx, span, p.def_id).has_self_ty() { // There is no suitable inference default for a type parameter // that references self, in an object type. return true; @@ -329,7 +310,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.err } else { // This is a default type parameter. - self.get_item_type(span, def.def_id).subst_spanned(tcx, substs, Some(span)) + tcx.maps.ty(tcx, span, def.def_id).subst_spanned(tcx, substs, Some(span)) } } else { // We've already errored above about the mismatch. @@ -591,8 +572,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Otherwise, we have to walk through the supertraits to find // those that do. - self.ensure_super_predicates(binding.span, trait_ref.def_id()); - let candidates = traits::supertraits(tcx, trait_ref.clone()) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name)); @@ -620,7 +599,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); - self.get_item_type(span, did).subst(self.tcx(), substs) + self.tcx().maps.ty(self.tcx(), span, did).subst(self.tcx(), substs) } /// Transform a PolyTraitRef into a PolyExistentialTraitRef by @@ -677,9 +656,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }) }); - // ensure the super predicates - self.ensure_super_predicates(span, principal.def_id()); - // check that there are no gross object safety violations, // most importantly, that the supertraits don't contain Self, // to avoid ICE-s. @@ -776,12 +752,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let tcx = self.tcx(); let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id) - .into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect(); - - // Ensure the super predicates. - for b in &bounds { - self.ensure_super_predicates(span, b.def_id()); - } + .predicates.into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect(); // Check that there is exactly one way to find an associated type with the // correct name. @@ -880,28 +851,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait - we have a concrete self type and a // trait reference. - // 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. - let trait_ref = if impl_def_id.is_local() { - tcx.maps.impl_trait_ref.borrow().get(&impl_def_id) - .cloned().and_then(|x| x) - } else { - tcx.impl_trait_ref(impl_def_id) - }; - let trait_ref = if let Some(trait_ref) = trait_ref { - trait_ref - } else { - tcx.sess.span_err(span, "`Self` type is used before it's determined"); - return (tcx.types.err, Def::Err); + let trait_ref = match tcx.impl_trait_ref(impl_def_id) { + Some(trait_ref) => trait_ref, + None => { + // A cycle error occurred, most likely. + return (tcx.types.err, Def::Err); + } }; + let trait_ref = if let Some(free_substs) = self.get_free_substs() { trait_ref.subst(tcx, free_substs) } else { trait_ref }; - self.ensure_super_predicates(span, trait_ref.def_id); - let candidates = traits::supertraits(tcx, ty::Binder(trait_ref)) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), @@ -1022,7 +985,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { assert_eq!(opt_self_ty, None); tcx.prohibit_type_params(&path.segments); - let ty = self.get_item_type(span, def_id); + let ty = tcx.maps.ty(tcx, span, def_id); if let Some(free_substs) = self.get_free_substs() { ty.subst(tcx, free_substs) } else { @@ -1137,9 +1100,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyTraitObject(ref bounds, ref lifetime) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) } - hir::TyImplTrait(ref bounds) => { - use collect::{compute_bounds, SizedByDefault}; - + hir::TyImplTrait(_) => { // Figure out if we can allow an `impl Trait` here, by walking up // to a `fn` or inherent `impl` method, going only through `Ty` // or `TraitRef` nodes (as nothing else should be in types) and @@ -1179,22 +1140,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Create the anonymized type. if allow { let def_id = tcx.hir.local_def_id(ast_ty.id); - tcx.item_generics(def_id); - let substs = Substs::identity_for_item(tcx, def_id); - let ty = tcx.mk_anon(tcx.hir.local_def_id(ast_ty.id), substs); - - // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. - let bounds = compute_bounds(self, ty, bounds, - SizedByDefault::Yes, - ast_ty.span); - let predicates = bounds.predicates(tcx, ty); - let predicates = tcx.lift_to_global(&predicates).unwrap(); - tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { - parent: None, - predicates: predicates - }); - - ty + tcx.mk_anon(def_id, Substs::identity_for_item(tcx, def_id)) } else { span_err!(tcx.sess, ast_ty.span, E0562, "`impl Trait` not allowed outside of function \ @@ -1353,10 +1299,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates); - if let Some(principal) = existential_predicates.principal() { - self.ensure_super_predicates(span, principal.def_id()); - } - // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 62438d87d1860..4085a171bbef5 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -139,7 +139,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); - self.used_trait_imports.borrow_mut().insert(import_def_id); + self.tables.borrow_mut().used_trait_imports.insert(import_def_id); } self.tcx.check_stability(pick.item.def_id, call_expr.id, span); @@ -333,7 +333,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); - self.used_trait_imports.borrow_mut().insert(import_def_id); + self.tables.borrow_mut().used_trait_imports.insert(import_def_id); } let def = pick.item.def(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c6d3af547eb02..68d8280d397d7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,13 +95,14 @@ use rustc::ty::{self, Ty, TyCtxt, Visibility}; use rustc::ty::{MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; +use rustc::ty::maps::Providers; use rustc::ty::util::{Representability, IntTypeExt}; use require_c_abi_if_variadic; use session::{Session, CompileResult}; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; -use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap}; +use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap}; use std::cell::{Cell, RefCell}; use std::cmp; @@ -109,7 +110,6 @@ use std::mem::replace; use std::ops::{self, Deref}; use syntax::abi::Abi; use syntax::ast; -use syntax::attr; use syntax::codemap::{self, original_sp, Spanned}; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; @@ -174,16 +174,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // associated fresh inference variable. Writeback resolves these // variables to get the concrete type, which can be used to // deanonymize TyAnon, after typeck is done with all functions. - anon_types: RefCell>>, - - // Obligations which will have to be checked at the end of - // type-checking, after all functions have been inferred. - deferred_obligations: RefCell>>, - - // a set of trait import def-ids that we use during method - // resolution; during writeback, this is written into - // `tcx.used_trait_imports` for this item def-id - used_trait_imports: RefCell>, + anon_types: RefCell>>, } impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { @@ -507,9 +498,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { locals: RefCell::new(NodeMap()), deferred_call_resolutions: RefCell::new(DefIdMap()), deferred_cast_checks: RefCell::new(Vec::new()), - anon_types: RefCell::new(DefIdMap()), - deferred_obligations: RefCell::new(Vec::new()), - used_trait_imports: RefCell::new(DefIdSet()), + anon_types: RefCell::new(NodeMap()), } } @@ -545,7 +534,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &'tcx hir::Ty) { match t.node { hir::TyArray(_, length) => { - check_const_with_type(self.tcx, length, self.tcx.types.usize, length.node_id); + self.tcx.item_tables(self.tcx.hir.local_def_id(length.node_id)); } _ => {} } @@ -556,7 +545,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_expr(&mut self, e: &'tcx hir::Expr) { match e.node { hir::ExprRepeat(_, count) => { - check_const_with_type(self.tcx, count, self.tcx.types.usize, count.node_id); + self.tcx.item_tables(self.tcx.hir.local_def_id(count.node_id)); } _ => {} } @@ -568,8 +557,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { - hir::ItemFn(ref decl, .., body_id) => { - check_bare_fn(self.tcx, &decl, body_id, item.id, item.span); + hir::ItemFn(..) => { + self.tcx.item_tables(self.tcx.hir.local_def_id(item.id)); } _ => { } } @@ -577,11 +566,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { match trait_item.node { - hir::TraitItemKind::Const(_, Some(expr)) => { - check_const(self.tcx, expr, trait_item.id) - } - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => { - check_bare_fn(self.tcx, &sig.decl, body_id, trait_item.id, trait_item.span); + hir::TraitItemKind::Const(_, Some(_)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { + self.tcx.item_tables(self.tcx.hir.local_def_id(trait_item.id)); } hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Const(_, None) | @@ -593,11 +580,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { match impl_item.node { - hir::ImplItemKind::Const(_, expr) => { - check_const(self.tcx, expr, impl_item.id) - } - hir::ImplItemKind::Method(ref sig, body_id) => { - check_bare_fn(self.tcx, &sig.decl, body_id, impl_item.id, impl_item.span); + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Method(..) => { + self.tcx.item_tables(self.tcx.hir.local_def_id(impl_item.id)); } hir::ImplItemKind::Type(_) => { // Nothing to do here. @@ -625,26 +610,6 @@ pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult tcx.sess.track_errors(|| { let mut visit = CheckItemBodiesVisitor { tcx: tcx }; tcx.visit_all_item_likes_in_krate(DepNode::TypeckTables, &mut visit); - - // Process deferred obligations, now that all functions - // bodies have been fully inferred. - for (&item_id, obligations) in tcx.deferred_obligations.borrow().iter() { - // Use the same DepNode as for the body of the original function/item. - let def_id = tcx.hir.local_def_id(item_id); - let _task = tcx.dep_graph.in_task(DepNode::TypeckTables(def_id)); - - let param_env = ParameterEnvironment::for_item(tcx, item_id); - tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { - let mut fulfillment_cx = traits::FulfillmentContext::new(); - for obligation in obligations.iter().map(|o| o.to_obligation()) { - fulfillment_cx.register_predicate_obligation(&infcx, obligation); - } - - if let Err(errors) = fulfillment_cx.select_all_or_error(&infcx) { - infcx.report_fulfillment_errors(&errors); - } - }); - } }) } @@ -668,38 +633,145 @@ pub fn check_drop_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult }) } -fn check_bare_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - decl: &'tcx hir::FnDecl, - body_id: hir::BodyId, - fn_id: ast::NodeId, - span: Span) { +pub fn provide(providers: &mut Providers) { + *providers = Providers { + typeck_tables, + closure_type, + closure_kind, + ..*providers + }; +} + +fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::PolyFnSig<'tcx> { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + tcx.item_tables(def_id).closure_tys[&node_id] +} + +fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::ClosureKind { + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + tcx.item_tables(def_id).closure_kinds[&node_id] +} + +fn typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> &'tcx ty::TypeckTables<'tcx> { + // Closures' tables come from their outermost function, + // as they are part of the same "inference environment". + let outer_def_id = tcx.closure_base_def_id(def_id); + if outer_def_id != def_id { + return tcx.item_tables(outer_def_id); + } + + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let span = tcx.hir.span(id); + let unsupported = || { + span_bug!(span, "can't type-check body of {:?}", def_id); + }; + + // Figure out what primary body this item has. + let mut fn_decl = None; + let body_id = match tcx.hir.get(id) { + hir::map::NodeItem(item) => { + match item.node { + hir::ItemConst(_, body) | + hir::ItemStatic(_, _, body) => body, + hir::ItemFn(ref decl, .., body) => { + fn_decl = Some(decl); + body + } + _ => unsupported() + } + } + hir::map::NodeTraitItem(item) => { + match item.node { + hir::TraitItemKind::Const(_, Some(body)) => body, + hir::TraitItemKind::Method(ref sig, + hir::TraitMethod::Provided(body)) => { + fn_decl = Some(&sig.decl); + body + } + _ => unsupported() + } + } + hir::map::NodeImplItem(item) => { + match item.node { + hir::ImplItemKind::Const(_, body) => body, + hir::ImplItemKind::Method(ref sig, body) => { + fn_decl = Some(&sig.decl); + body + } + _ => unsupported() + } + } + hir::map::NodeExpr(expr) => { + // FIXME(eddyb) Closures should have separate + // function definition IDs and expression IDs. + // Type-checking should not let closures get + // this far in a constant position. + // Assume that everything other than closures + // is a constant "initializer" expression. + match expr.node { + hir::ExprClosure(..) => { + // We should've bailed out above for closures. + span_bug!(expr.span, "unexpected closure") + } + _ => hir::BodyId { node_id: expr.id } + } + } + _ => unsupported() + }; let body = tcx.hir.body(body_id); - let fn_sig = tcx.item_type(tcx.hir.local_def_id(fn_id)).fn_sig(); + Inherited::build(tcx, id).enter(|inh| { + let fcx = if let Some(decl) = fn_decl { + let fn_sig = tcx.item_type(def_id).fn_sig(); + + check_abi(tcx, span, fn_sig.abi()); - check_abi(tcx, span, fn_sig.abi()); + // Compute the fty from point of view of inside fn. + let fn_scope = inh.tcx.region_maps.call_site_extent(id, body_id.node_id); + let fn_sig = + fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs); + let fn_sig = + inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig); + let fn_sig = + inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig); - Inherited::build(tcx, fn_id).enter(|inh| { - // 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_sig = - fn_sig.subst(inh.tcx, &inh.parameter_environment.free_substs); - let fn_sig = - inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig); - let fn_sig = - inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig); + check_fn(&inh, fn_sig, decl, id, body) + } else { + let expected_type = tcx.item_type(def_id); + let fcx = FnCtxt::new(&inh, None, body.value.id); + fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); - let fcx = check_fn(&inh, fn_sig, decl, fn_id, body); + // Gather locals in statics (because of block expressions). + // This is technically unnecessary because locals in static items are forbidden, + // but prevents type checking from blowing up before const checking can properly + // emit an error. + GatherLocalsVisitor { fcx: &fcx }.visit_body(body); + + fcx.check_expr_coercable_to_type(&body.value, expected_type); + + fcx + }; fcx.select_all_obligations_and_apply_defaults(); fcx.closure_analyze(body); fcx.select_obligations_where_possible(); fcx.check_casts(); - fcx.select_all_obligations_or_error(); // Casts can introduce new obligations. + fcx.select_all_obligations_or_error(); - fcx.regionck_fn(fn_id, body); - fcx.resolve_type_vars_in_body(body); - }); + if fn_decl.is_some() { + fcx.regionck_fn(id, body); + } else { + fcx.regionck_expr(body); + } + + fcx.resolve_type_vars_in_body(body) + }) } fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { @@ -772,7 +844,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { _: hir::BodyId, _: Span, _: ast::NodeId) { } } -/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function +/// Helper used for fns and closures. Does the grungy work of checking a function /// body and returns the function context used for that purpose, since in the case of a fn item /// there is still a bit more to do. /// @@ -835,7 +907,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def_id = tcx.hir.local_def_id(id); check_representable(tcx, span, def_id); - if tcx.lookup_simd(def_id) { + if tcx.lookup_adt_def(def_id).repr.simd { check_simd(tcx, span, def_id); } } @@ -853,8 +925,10 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item let _indenter = indenter(); match it.node { // Consts can play a role in type-checking, so they are included here. - hir::ItemStatic(.., e) | - hir::ItemConst(_, e) => check_const(tcx, e, it.id), + hir::ItemStatic(..) | + hir::ItemConst(..) => { + tcx.item_tables(tcx.hir.local_def_id(it.id)); + } hir::ItemEnum(ref enum_definition, _) => { check_enum_variants(tcx, it.span, @@ -1197,42 +1271,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -/// Checks a constant with a given type. -fn check_const_with_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - body: hir::BodyId, - expected_type: Ty<'tcx>, - id: ast::NodeId) { - let body = tcx.hir.body(body); - Inherited::build(tcx, id).enter(|inh| { - let fcx = FnCtxt::new(&inh, None, body.value.id); - fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); - - // Gather locals in statics (because of block expressions). - // This is technically unnecessary because locals in static items are forbidden, - // but prevents type checking from blowing up before const checking can properly - // emit an error. - GatherLocalsVisitor { fcx: &fcx }.visit_body(body); - - fcx.check_expr_coercable_to_type(&body.value, expected_type); - - fcx.select_all_obligations_and_apply_defaults(); - fcx.closure_analyze(body); - fcx.select_obligations_where_possible(); - fcx.check_casts(); - fcx.select_all_obligations_or_error(); - - fcx.regionck_expr(body); - fcx.resolve_type_vars_in_body(body); - }); -} - -fn check_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - body: hir::BodyId, - id: ast::NodeId) { - let decl_ty = tcx.item_type(tcx.hir.local_def_id(id)); - check_const_with_type(tcx, body, decl_ty, id); -} - /// Checks whether a type can be represented in memory. In particular, it /// identifies types that contain themselves without indirection through a /// pointer, which would mean their size is unbounded. @@ -1293,9 +1331,9 @@ pub fn check_enum_variants<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, vs: &'tcx [hir::Variant], id: ast::NodeId) { let def_id = tcx.hir.local_def_id(id); - let hint = *tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny); + let def = tcx.lookup_adt_def(def_id); - if hint != attr::ReprAny && vs.is_empty() { + if vs.is_empty() && tcx.has_attr(def_id, "repr") { struct_span_err!( tcx.sess, sp, E0084, "unsupported representation for zero-variant enum") @@ -1303,7 +1341,7 @@ pub fn check_enum_variants<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .emit(); } - let repr_type_ty = tcx.enum_repr_type(Some(&hint)).to_ty(tcx); + let repr_type_ty = def.repr.discr_type().to_ty(tcx); if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { if !tcx.sess.features.borrow().i128_type { emit_feature_err(&tcx.sess.parse_sess, @@ -1313,13 +1351,10 @@ pub fn check_enum_variants<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for v in vs { if let Some(e) = v.node.disr_expr { - check_const_with_type(tcx, e, repr_type_ty, e.node_id); + tcx.item_tables(tcx.hir.local_def_id(e.node_id)); } } - let def_id = tcx.hir.local_def_id(id); - - let def = tcx.lookup_adt_def(def_id); let mut disr_vals: Vec = Vec::new(); for (discr, v) in def.discriminants(tcx).zip(vs) { // Check for duplicate discriminant values @@ -1353,20 +1388,12 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { &self.ast_ty_to_ty_cache } - fn get_item_type(&self, _: Span, id: DefId) -> Ty<'tcx> { - self.tcx().item_type(id) - } - - fn ensure_super_predicates(&self, _: Span, _: DefId) { - // all super predicates are ensured during collect pass - } - fn get_free_substs(&self) -> Option<&Substs<'tcx>> { Some(&self.parameter_environment.free_substs) } fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) - -> Vec> + -> ty::GenericPredicates<'tcx> { let tcx = self.tcx; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -1374,14 +1401,17 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.item_generics(item_def_id); let index = generics.type_param_to_index[&def_id.index]; - self.parameter_environment.caller_bounds.iter().filter(|predicate| { - match **predicate { - ty::Predicate::Trait(ref data) => { - data.0.self_ty().is_param(index) + ty::GenericPredicates { + parent: None, + predicates: self.parameter_environment.caller_bounds.iter().filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref data) => { + data.0.self_ty().is_param(index) + } + _ => false } - _ => false - } - }).cloned().collect() + }).cloned().collect() + } } fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>) @@ -1666,12 +1696,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let ty::TyAnon(def_id, substs) = ty.sty { // Use the same type variable if the exact same TyAnon appears more // than once in the return type (e.g. if it's pased to a type alias). - if let Some(ty_var) = self.anon_types.borrow().get(&def_id) { + let id = self.tcx.hir.as_local_node_id(def_id).unwrap(); + if let Some(ty_var) = self.anon_types.borrow().get(&id) { return ty_var; } let span = self.tcx.def_span(def_id); let ty_var = self.next_ty_var(TypeVariableOrigin::TypeInference(span)); - self.anon_types.borrow_mut().insert(def_id, ty_var); + self.anon_types.borrow_mut().insert(id, ty_var); let item_predicates = self.tcx.item_predicates(def_id); let bounds = item_predicates.instantiate(self.tcx, substs); @@ -2206,11 +2237,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); - // Steal the deferred obligations before the fulfillment - // context can turn all of them into errors. - let obligations = fulfillment_cx.take_deferred_obligations(); - self.deferred_obligations.borrow_mut().extend(obligations); - match fulfillment_cx.select_all_or_error(self) { Ok(()) => { } Err(errors) => { self.report_fulfillment_errors(&errors); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index f7f004fbaef12..4f0cfa8d014e6 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -14,7 +14,6 @@ use self::ResolveReason::*; use check::FnCtxt; -use hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{TypeFolder,TypeFoldable}; @@ -34,7 +33,8 @@ use rustc::hir; // Entry point impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) { + pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) + -> &'gcx ty::TypeckTables<'gcx> { assert_eq!(self.writeback_errors.get(), false); let item_id = self.tcx.hir.body_owner(body.id()); @@ -50,18 +50,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); wbcx.visit_anon_types(); - wbcx.visit_deferred_obligations(item_id); wbcx.visit_type_nodes(); wbcx.visit_cast_types(); wbcx.visit_lints(); - let tables = self.tcx.alloc_tables(wbcx.tables); - self.tcx.maps.typeck_tables.borrow_mut().insert(item_def_id, tables); - - let used_trait_imports = mem::replace(&mut *self.used_trait_imports.borrow_mut(), + let used_trait_imports = mem::replace(&mut self.tables.borrow_mut().used_trait_imports, DefIdSet()); debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); - self.tcx.maps.used_trait_imports.borrow_mut().insert(item_def_id, used_trait_imports); + wbcx.tables.used_trait_imports = used_trait_imports; + + self.tcx.alloc_tables(wbcx.tables) } } @@ -282,20 +280,18 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_closures(&self) { + fn visit_closures(&mut self) { if self.fcx.writeback_errors.get() { return } for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); - let def_id = self.tcx().hir.local_def_id(id); - self.tcx().maps.closure_type.borrow_mut().insert(def_id, closure_ty); + self.tables.closure_tys.insert(id, closure_ty); } for (&id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { - let def_id = self.tcx().hir.local_def_id(id); - self.tcx().maps.closure_kind.borrow_mut().insert(def_id, closure_kind); + self.tables.closure_kinds.insert(id, closure_kind); } } @@ -316,14 +312,14 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints); } - fn visit_anon_types(&self) { + fn visit_anon_types(&mut self) { if self.fcx.writeback_errors.get() { return } let gcx = self.tcx().global_tcx(); - for (&def_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() { - let reason = ResolvingAnonTy(def_id); + for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() { + let reason = ResolvingAnonTy(node_id); let inside_ty = self.resolve(&concrete_ty, reason); // Convert the type from the function into a type valid outside @@ -361,7 +357,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } }); - gcx.maps.ty.borrow_mut().insert(def_id, outside_ty); + self.tables.node_types.insert(node_id, outside_ty); } } @@ -483,19 +479,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_deferred_obligations(&mut self, item_id: ast::NodeId) { - let deferred_obligations = self.fcx.deferred_obligations.borrow(); - let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| { - let reason = ResolvingDeferredObligation(obligation.cause.span); - self.resolve(obligation, reason) - }).collect(); - - if !obligations.is_empty() { - assert!(self.fcx.tcx.deferred_obligations.borrow_mut() - .insert(item_id, obligations).is_none()); - } - } - fn visit_type_nodes(&self) { for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() { let ty = self.resolve(ty, ResolvingTyNode(id)); @@ -528,8 +511,7 @@ enum ResolveReason { ResolvingClosure(ast::NodeId), ResolvingFnSig(ast::NodeId), ResolvingFieldTypes(ast::NodeId), - ResolvingAnonTy(DefId), - ResolvingDeferredObligation(Span), + ResolvingAnonTy(ast::NodeId), ResolvingTyNode(ast::NodeId), } @@ -545,13 +527,10 @@ impl<'a, 'gcx, 'tcx> ResolveReason { ResolvingClosure(id) | ResolvingFnSig(id) | ResolvingFieldTypes(id) | - ResolvingTyNode(id) => { + ResolvingTyNode(id) | + ResolvingAnonTy(id) => { tcx.hir.span(id) } - ResolvingAnonTy(did) => { - tcx.def_span(did) - } - ResolvingDeferredObligation(span) => span } } } @@ -626,7 +605,6 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { ResolvingFnSig(_) | ResolvingFieldTypes(_) | - ResolvingDeferredObligation(_) | ResolvingTyNode(_) => { // any failures here should also fail when // resolving the patterns, closure types, or diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 0f992f75fce34..3791079dc812c 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -70,7 +70,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let item_def_id = tcx.hir.local_def_id(item_id); // this will have been written by the main typeck pass - if let Some(imports) = tcx.maps.used_trait_imports.borrow().get(&item_def_id) { + if let Some(tables) = tcx.maps.typeck_tables.borrow().get(&item_def_id) { + let imports = &tables.used_trait_imports; debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend(imports); } else { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 68e42f5b27ad0..2a95f5f5d0804 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -47,10 +47,6 @@ item, we may need to compute the *type scheme* or *trait definition* for other items. There are some shortcomings in this design: - -- Before walking the set of supertraits for a given trait, you must - call `ensure_super_predicates` on that trait def-id. Otherwise, - `item_super_predicates` will result in ICEs. - Because the item generics include defaults, cycles through type parameter defaults are illegal even if those defaults are never employed. This is not necessarily a bug. @@ -66,7 +62,7 @@ use middle::resolve_lifetime as rl; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; -use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer, ReprOptions}; +use rustc::ty::{ToPredicate, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc::ty::util::IntTypeExt; @@ -80,6 +76,7 @@ use std::cell::RefCell; use std::collections::BTreeMap; use syntax::{abi, ast, attr}; +use syntax::codemap::Spanned; use syntax::symbol::{Symbol, keywords}; use syntax_pos::{Span, DUMMY_SP}; @@ -98,9 +95,14 @@ pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { pub fn provide(providers: &mut Providers) { *providers = Providers { + ty, generics, + predicates, + super_predicates, + type_param_predicates, trait_def, adt_def, + impl_trait_ref, ..*providers }; } @@ -190,7 +192,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { for param in &generics.ty_params { if param.default.is_some() { let def_id = self.tcx.hir.local_def_id(param.id); - type_of_def_id(self.tcx, def_id); + self.tcx.item_type(def_id); } } intravisit::walk_generics(self, generics); @@ -200,7 +202,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { if let hir::ExprClosure(..) = expr.node { let def_id = self.tcx.hir.local_def_id(expr.id); self.tcx.item_generics(def_id); - type_of_def_id(self.tcx, def_id); + self.tcx.item_type(def_id); } intravisit::walk_expr(self, expr); } @@ -209,6 +211,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { if let hir::TyImplTrait(..) = ty.node { let def_id = self.tcx.hir.local_def_id(ty.id); self.tcx.item_generics(def_id); + self.tcx.item_predicates(def_id); } intravisit::walk_ty(self, ty); } @@ -254,42 +257,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { &self.tcx.ast_ty_to_ty_cache } - fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx> { - self.tcx.cycle_check(span, ty::maps::Query::ty(id), || { - type_of_def_id(self.tcx, id) - }) - } - - /// Ensure that the (transitive) super predicates for - /// `trait_def_id` are available. This will report a cycle error - /// if a trait `X` (transitively) extends itself in some form. - fn ensure_super_predicates(&self, - span: Span, - trait_def_id: DefId) { - if !trait_def_id.is_local() { - // If this trait comes from an external crate, then all of the - // supertraits it may depend on also must come from external - // crates, and hence all of them already have their - // super-predicates "converted" (and available from crate - // meta-data), so there is no need to transitively test them. - return; - } - - self.tcx.maps.super_predicates.memoize(trait_def_id, || { - self.tcx.cycle_check(span, ty::maps::Query::super_predicates(trait_def_id), || { - super_predicates(self.tcx, trait_def_id) - }) - }); - } - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> Vec> + -> ty::GenericPredicates<'tcx> { - self.tcx.cycle_check(span, - ty::maps::Query::type_param_predicates((self.item_def_id, def_id)), - || get_type_parameter_bounds(self.tcx, self.item_def_id, def_id)) + self.tcx.maps.type_param_predicates(self.tcx, span, (self.item_def_id, def_id)) } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { @@ -343,89 +316,91 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } } - fn get_type_parameter_bounds<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_def_id: DefId, - def_id: DefId) - -> Vec> - { - use rustc::hir::map::*; - use rustc::hir::*; - - // In the AST, bounds can derive from two places. Either - // written inline like `` or in a where clause like - // `where T:Foo`. - - let param_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let param_owner = tcx.hir.ty_param_owner(param_id); - let param_owner_def_id = tcx.hir.local_def_id(param_owner); - let generics = tcx.item_generics(param_owner_def_id); - let index = generics.type_param_to_index[&def_id.index]; - let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id)); - - // Don't look for bounds where the type parameter isn't in scope. - let parent = if item_def_id == param_owner_def_id { - None - } else { - tcx.item_generics(item_def_id).parent - }; +fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + (item_def_id, def_id): (DefId, DefId)) + -> ty::GenericPredicates<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; - let mut results = parent.map_or(vec![], |parent| { - let icx = ItemCtxt::new(tcx, parent); - icx.get_type_parameter_bounds(DUMMY_SP, def_id) - }); + // In the AST, bounds can derive from two places. Either + // written inline like `` or in a where clause like + // `where T:Foo`. - let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); - let ast_generics = match tcx.hir.get(item_node_id) { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => &sig.generics, - _ => return results - } + let param_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let param_owner = tcx.hir.ty_param_owner(param_id); + let param_owner_def_id = tcx.hir.local_def_id(param_owner); + let generics = tcx.item_generics(param_owner_def_id); + let index = generics.type_param_to_index[&def_id.index]; + let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id)); + + // Don't look for bounds where the type parameter isn't in scope. + let parent = if item_def_id == param_owner_def_id { + None + } else { + tcx.item_generics(item_def_id).parent + }; + + let mut result = parent.map_or(ty::GenericPredicates { + parent: None, + predicates: vec![] + }, |parent| { + let icx = ItemCtxt::new(tcx, parent); + icx.get_type_parameter_bounds(DUMMY_SP, def_id) + }); + + let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); + let ast_generics = match tcx.hir.get(item_node_id) { + NodeTraitItem(item) => { + match item.node { + TraitItemKind::Method(ref sig, _) => &sig.generics, + _ => return result } + } - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => &sig.generics, - _ => return results - } + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => &sig.generics, + _ => return result } + } - NodeItem(item) => { - match item.node { - ItemFn(.., ref generics, _) | - ItemImpl(_, _, ref generics, ..) | - ItemTy(_, ref generics) | - ItemEnum(_, ref generics) | - ItemStruct(_, ref generics) | - ItemUnion(_, ref generics) => generics, - ItemTrait(_, ref generics, ..) => { - // Implied `Self: Trait` and supertrait bounds. - if param_id == item_node_id { - results.push(ty::TraitRef { - def_id: item_def_id, - substs: Substs::identity_for_item(tcx, item_def_id) - }.to_predicate()); - } - generics + NodeItem(item) => { + match item.node { + ItemFn(.., ref generics, _) | + ItemImpl(_, _, ref generics, ..) | + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) | + ItemUnion(_, ref generics) => generics, + ItemTrait(_, ref generics, ..) => { + // Implied `Self: Trait` and supertrait bounds. + if param_id == item_node_id { + result.predicates.push(ty::TraitRef { + def_id: item_def_id, + substs: Substs::identity_for_item(tcx, item_def_id) + }.to_predicate()); } - _ => return results + generics } + _ => return result } + } - NodeForeignItem(item) => { - match item.node { - ForeignItemFn(_, _, ref generics) => generics, - _ => return results - } + NodeForeignItem(item) => { + match item.node { + ForeignItemFn(_, _, ref generics) => generics, + _ => return result } + } - _ => return results - }; + _ => return result + }; - let icx = ItemCtxt::new(tcx, item_def_id); - results.extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); - results - } + let icx = ItemCtxt::new(tcx, item_def_id); + result.predicates.extend( + icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty)); + result +} impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { /// Find bounds from hir::Generics. This requires scanning through the @@ -483,63 +458,6 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn convert_field<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - field: &hir::StructField, - ty_f: &'tcx ty::FieldDef) -{ - tcx.item_generics(ty_f.did); - let tt = ItemCtxt::new(tcx, ty_f.did).to_ty(&field.ty); - tcx.maps.ty.borrow_mut().insert(ty_f.did, tt); - tcx.maps.predicates.borrow_mut().insert(ty_f.did, ty::GenericPredicates { - parent: Some(tcx.hir.get_parent_did(field.id)), - predicates: vec![] - }); -} - -fn convert_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: ast::NodeId, - sig: &hir::MethodSig) { - let def_id = tcx.hir.local_def_id(id); - - let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), sig.unsafety, sig.abi, &sig.decl); - let substs = Substs::identity_for_item(tcx, def_id); - let fty = tcx.mk_fn_def(def_id, substs, fty); - tcx.maps.ty.borrow_mut().insert(def_id, fty); - - ty_generic_predicates(tcx, def_id, &sig.generics); -} - -fn convert_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - container: AssociatedItemContainer, - id: ast::NodeId, - ty: ty::Ty<'tcx>) -{ - let predicates = ty::GenericPredicates { - parent: Some(container.id()), - predicates: vec![] - }; - let def_id = tcx.hir.local_def_id(id); - tcx.maps.predicates.borrow_mut().insert(def_id, predicates); - tcx.maps.ty.borrow_mut().insert(def_id, ty); -} - -fn convert_associated_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - container: AssociatedItemContainer, - id: ast::NodeId, - ty: Option>) -{ - let predicates = ty::GenericPredicates { - parent: Some(container.id()), - predicates: vec![] - }; - let def_id = tcx.hir.local_def_id(id); - tcx.maps.predicates.borrow_mut().insert(def_id, predicates); - - if let Some(ty) = ty { - tcx.maps.ty.borrow_mut().insert(def_id, ty); - } -} - fn ensure_no_ty_param_bounds(tcx: TyCtxt, span: Span, generics: &hir::Generics, @@ -582,195 +500,125 @@ fn ensure_no_ty_param_bounds(tcx: TyCtxt, fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { debug!("convert: item {} with id {}", it.name, it.id); let def_id = tcx.hir.local_def_id(it.id); - let icx = ItemCtxt::new(tcx, def_id); match it.node { // These don't define types. hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => { } hir::ItemForeignMod(ref foreign_mod) => { for item in &foreign_mod.items { - convert_foreign_item(tcx, item); + let def_id = tcx.hir.local_def_id(item.id); + tcx.item_generics(def_id); + tcx.item_type(def_id); + tcx.item_predicates(def_id); } } hir::ItemEnum(ref enum_definition, _) => { tcx.item_generics(def_id); - predicates_of_item(tcx, it); - let ty = type_of_def_id(tcx, def_id); - convert_enum_variant_types(tcx, - tcx.lookup_adt_def(tcx.hir.local_def_id(it.id)), - ty, - &enum_definition.variants); + tcx.item_type(def_id); + tcx.item_predicates(def_id); + convert_enum_variant_types(tcx, def_id, &enum_definition.variants); }, - hir::ItemDefaultImpl(_, ref ast_trait_ref) => { - let trait_ref = - AstConv::instantiate_mono_trait_ref(&icx, - ast_trait_ref, - tcx.mk_self_type()); - - tcx.record_trait_has_default_impl(trait_ref.def_id); - - tcx.maps.impl_trait_ref.borrow_mut().insert(tcx.hir.local_def_id(it.id), - Some(trait_ref)); + hir::ItemDefaultImpl(..) => { + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { + tcx.record_trait_has_default_impl(trait_ref.def_id); + } } - hir::ItemImpl(.., ref opt_trait_ref, _, _) => { + hir::ItemImpl(..) => { tcx.item_generics(def_id); - let selfty = type_of_def_id(tcx, def_id); - - let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { - AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) - }); - tcx.maps.impl_trait_ref.borrow_mut().insert(def_id, trait_ref); - - predicates_of_item(tcx, it); + tcx.item_type(def_id); + tcx.impl_trait_ref(def_id); + tcx.item_predicates(def_id); }, hir::ItemTrait(..) => { tcx.item_generics(def_id); tcx.lookup_trait_def(def_id); - icx.ensure_super_predicates(it.span, def_id); - predicates_of_item(tcx, it); + tcx.maps.super_predicates(tcx, it.span, def_id); + tcx.item_predicates(def_id); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { tcx.item_generics(def_id); - predicates_of_item(tcx, it); - let ty = type_of_def_id(tcx, def_id); - - let variant = tcx.lookup_adt_def(def_id).struct_variant(); - - for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) { - convert_field(tcx, f, ty_f) + tcx.item_type(def_id); + tcx.item_predicates(def_id); + + for f in struct_def.fields() { + let def_id = tcx.hir.local_def_id(f.id); + tcx.item_generics(def_id); + tcx.item_type(def_id); + tcx.item_predicates(def_id); } if !struct_def.is_struct() { - convert_variant_ctor(tcx, struct_def.id(), variant, ty); + convert_variant_ctor(tcx, struct_def.id()); } }, hir::ItemTy(_, ref generics) => { ensure_no_ty_param_bounds(tcx, it.span, generics, "type"); tcx.item_generics(def_id); - predicates_of_item(tcx, it); - type_of_def_id(tcx, def_id); + tcx.item_type(def_id); + tcx.item_predicates(def_id); }, _ => { tcx.item_generics(def_id); - predicates_of_item(tcx, it); - type_of_def_id(tcx, def_id); + tcx.item_type(def_id); + tcx.item_predicates(def_id); }, } } fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item: &hir::TraitItem) { - // we can lookup details about the trait because items are visited - // before trait-items - let trait_def_id = tcx.hir.get_parent_did(trait_item.id); - let def_id = tcx.hir.local_def_id(trait_item.id); + tcx.item_generics(def_id); + match trait_item.node { - hir::TraitItemKind::Const(ref ty, _) => { - tcx.item_generics(def_id); - let ty = ItemCtxt::new(tcx, def_id).to_ty(&ty); - convert_associated_const(tcx, - TraitContainer(trait_def_id), - trait_item.id, - ty); + hir::TraitItemKind::Const(..) | + hir::TraitItemKind::Type(_, Some(_)) | + hir::TraitItemKind::Method(..) => { + tcx.item_type(def_id); } - hir::TraitItemKind::Type(_, ref opt_ty) => { - tcx.item_generics(def_id); - - let typ = opt_ty.as_ref().map(|ty| ItemCtxt::new(tcx, def_id).to_ty(&ty)); - - convert_associated_type(tcx, TraitContainer(trait_def_id), trait_item.id, typ); - } + hir::TraitItemKind::Type(_, None) => {} + }; - hir::TraitItemKind::Method(ref sig, _) => { - convert_method(tcx, trait_item.id, sig); - } - } + tcx.item_predicates(def_id); } fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::ImplItem) { - // we can lookup details about the impl because items are visited - // before impl-items - let impl_def_id = tcx.hir.get_parent_did(impl_item.id); - let def_id = tcx.hir.local_def_id(impl_item.id); - match impl_item.node { - hir::ImplItemKind::Const(ref ty, _) => { - tcx.item_generics(def_id); - let ty = ItemCtxt::new(tcx, def_id).to_ty(&ty); - convert_associated_const(tcx, - ImplContainer(impl_def_id), - impl_item.id, - ty); - } - - hir::ImplItemKind::Type(ref ty) => { - tcx.item_generics(def_id); - - if tcx.impl_trait_ref(impl_def_id).is_none() { - span_err!(tcx.sess, impl_item.span, E0202, - "associated types are not allowed in inherent impls"); - } - - let typ = ItemCtxt::new(tcx, def_id).to_ty(ty); - - convert_associated_type(tcx, ImplContainer(impl_def_id), impl_item.id, Some(typ)); - } - - hir::ImplItemKind::Method(ref sig, _) => { - convert_method(tcx, impl_item.id, sig); - } - } + tcx.item_generics(def_id); + tcx.item_type(def_id); + tcx.item_predicates(def_id); } fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ctor_id: ast::NodeId, - variant: &'tcx ty::VariantDef, - ty: Ty<'tcx>) { + ctor_id: ast::NodeId) { let def_id = tcx.hir.local_def_id(ctor_id); tcx.item_generics(def_id); - let ctor_ty = match variant.ctor_kind { - CtorKind::Fictive | CtorKind::Const => ty, - CtorKind::Fn => { - let inputs = variant.fields.iter().map(|field| tcx.item_type(field.did)); - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust - ))) - } - }; - tcx.maps.ty.borrow_mut().insert(def_id, ctor_ty); - tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { - parent: Some(tcx.hir.get_parent_did(ctor_id)), - predicates: vec![] - }); + tcx.item_type(def_id); + tcx.item_predicates(def_id); } fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def: &'tcx ty::AdtDef, - ty: Ty<'tcx>, + def_id: DefId, variants: &[hir::Variant]) { - let repr_hints = tcx.lookup_repr_hints(def.did); - let repr_type = tcx.enum_repr_type(repr_hints.get(0)); + let def = tcx.lookup_adt_def(def_id); + let repr_type = def.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); let mut prev_discr = None::; // fill the discriminant values and field types - for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) { + for variant in variants { let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr()); prev_discr = Some(if let Some(e) = variant.node.disr_expr { - let result = evaluate_disr_expr(tcx, repr_type, e); - let expr_did = tcx.hir.local_def_id(e.node_id); - tcx.maps.monomorphic_const_eval.borrow_mut() - .insert(expr_did, result.map(ConstVal::Integral)); + let result = tcx.maps.monomorphic_const_eval.memoize(expr_did, || { + evaluate_disr_expr(tcx, repr_type, e).map(ConstVal::Integral) + }); - result.ok() + match result { + Ok(ConstVal::Integral(x)) => Some(x), + _ => None + } } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { Some(discr) } else { @@ -784,13 +632,16 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, None }.unwrap_or(wrapped_discr)); - for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) { - convert_field(tcx, f, ty_f) + for f in variant.node.data.fields() { + let def_id = tcx.hir.local_def_id(f.id); + tcx.item_generics(def_id); + tcx.item_type(def_id); + tcx.item_predicates(def_id); } // Convert the ctor, if any. This also registers the variant as // an item. - convert_variant_ctor(tcx, variant.node.data.id(), ty_variant, ty); + convert_variant_ctor(tcx, variant.node.data.id()); } } @@ -985,7 +836,7 @@ fn super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. for bound in superbounds.iter().filter_map(|p| p.to_opt_poly_trait_ref()) { - icx.ensure_super_predicates(item.span, bound.def_id()); + tcx.maps.super_predicates(tcx, item.span, bound.def_id()); } ty::GenericPredicates { @@ -1212,121 +1063,179 @@ fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) } -fn type_of_def_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Ty<'tcx> { - let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) { - id - } else { - return tcx.item_type(def_id); - }; - tcx.maps.ty.memoize(def_id, || { - use rustc::hir::map::*; - use rustc::hir::*; +fn ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Ty<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; - // Alway bring in generics, as computing the type needs them. - tcx.item_generics(def_id); + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let icx = ItemCtxt::new(tcx, def_id); + let icx = ItemCtxt::new(tcx, def_id); - match tcx.hir.get(node_id) { - NodeItem(item) => { - match item.node { - ItemStatic(ref t, ..) | ItemConst(ref t, _) | - ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { - icx.to_ty(t) - } - ItemFn(ref decl, unsafety, _, abi, _, _) => { - let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs, tofd) - } - ItemEnum(..) | - ItemStruct(..) | - ItemUnion(..) => { - let def = tcx.lookup_adt_def(def_id); - let substs = Substs::identity_for_item(tcx, def_id); - tcx.mk_adt(def, substs) - } - ItemDefaultImpl(..) | - ItemTrait(..) | - ItemMod(..) | - ItemForeignMod(..) | - ItemExternCrate(..) | - ItemUse(..) => { - span_bug!( - item.span, - "compute_type_of_item: unexpected item type: {:?}", - item.node); - } + match tcx.hir.get(node_id) { + NodeTraitItem(item) => { + match item.node { + TraitItemKind::Method(ref sig, _) => { + let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs, fty) + } + TraitItemKind::Const(ref ty, _) | + TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), + TraitItemKind::Type(_, None) => { + span_bug!(item.span, "associated type missing default"); } } - NodeForeignItem(foreign_item) => { - let abi = tcx.hir.get_foreign_abi(node_id); + } - match foreign_item.node { - ForeignItemFn(ref fn_decl, _, _) => { - compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => { + let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl); + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs, fty) + } + ImplItemKind::Const(ref ty, _) => icx.to_ty(ty), + ImplItemKind::Type(ref ty) => { + if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() { + span_err!(tcx.sess, item.span, E0202, + "associated types are not allowed in inherent impls"); } - ForeignItemStatic(ref t, _) => icx.to_ty(t) + + icx.to_ty(ty) } } - NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { - tcx.mk_closure(def_id, Substs::for_item( - tcx, def_id, - |def, _| { - let region = def.to_early_bound_region_data(); - tcx.mk_region(ty::ReEarlyBound(region)) - }, - |def, _| tcx.mk_param_from_def(def) - )) + } + + NodeItem(item) => { + match item.node { + ItemStatic(ref t, ..) | ItemConst(ref t, _) | + ItemTy(ref t, _) | ItemImpl(.., ref t, _) => { + icx.to_ty(t) + } + ItemFn(ref decl, unsafety, _, abi, _, _) => { + let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl); + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs, tofd) + } + ItemEnum(..) | + ItemStruct(..) | + ItemUnion(..) => { + let def = tcx.lookup_adt_def(def_id); + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_adt(def, substs) + } + ItemDefaultImpl(..) | + ItemTrait(..) | + ItemMod(..) | + ItemForeignMod(..) | + ItemExternCrate(..) | + ItemUse(..) => { + span_bug!( + item.span, + "compute_type_of_item: unexpected item type: {:?}", + item.node); + } } - NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { - icx.to_ty(ty) + } + + NodeForeignItem(foreign_item) => { + let abi = tcx.hir.get_foreign_abi(node_id); + + match foreign_item.node { + ForeignItemFn(ref fn_decl, _, _) => { + compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + } + ForeignItemStatic(ref t, _) => icx.to_ty(t) } - x => { - bug!("unexpected sort of node in type_of_def_id(): {:?}", x); + } + + NodeStructCtor(&ref def) | + NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => { + let ty = tcx.item_type(tcx.hir.get_parent_did(node_id)); + match *def { + VariantData::Unit(..) | VariantData::Struct(..) => ty, + VariantData::Tuple(ref fields, _) => { + let inputs = fields.iter().map(|f| { + tcx.item_type(tcx.hir.local_def_id(f.id)) + }); + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust + ))) + } } } - }) -} -fn predicates_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { - let def_id = tcx.hir.local_def_id(it.id); + NodeField(field) => icx.to_ty(&field.ty), - let no_generics = hir::Generics::empty(); - let generics = match it.node { - hir::ItemFn(.., ref generics, _) | - hir::ItemTy(_, ref generics) | - hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) | - hir::ItemUnion(_, ref generics) | - hir::ItemTrait(_, ref generics, _, _) | - hir::ItemImpl(_, _, ref generics, ..) => generics, - _ => &no_generics - }; + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + tcx.mk_closure(def_id, Substs::for_item( + tcx, def_id, + |def, _| { + let region = def.to_early_bound_region_data(); + tcx.mk_region(ty::ReEarlyBound(region)) + }, + |def, _| tcx.mk_param_from_def(def) + )) + } - ty_generic_predicates(tcx, def_id, generics); -} + NodeExpr(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) { + NodeTy(&hir::Ty { node: TyArray(_, body), .. }) | + NodeExpr(&hir::Expr { node: ExprRepeat(_, body), .. }) + if body.node_id == node_id => tcx.types.usize, -fn convert_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - it: &hir::ForeignItem) -{ - // For reasons I cannot fully articulate, I do so hate the AST - // map, and I regard each time that I use it as a personal and - // moral failing, but at the moment it seems like the only - // convenient way to extract the ABI. - ndm - let def_id = tcx.hir.local_def_id(it.id); - tcx.item_generics(def_id); - type_of_def_id(tcx, def_id); + NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(e), .. }, .. }) + if e.node_id == node_id => { + tcx.lookup_adt_def(tcx.hir.get_parent_did(node_id)) + .repr.discr_type().to_ty(tcx) + } - let no_generics = hir::Generics::empty(); - let generics = match it.node { - hir::ForeignItemFn(_, _, ref generics) => generics, - hir::ForeignItemStatic(..) => &no_generics - }; + x => { + bug!("unexpected expr parent in type_of_def_id(): {:?}", x); + } + }, + + NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { + icx.to_ty(ty) + } + + NodeTy(&hir::Ty { node: TyImplTrait(..), .. }) => { + let owner = tcx.hir.get_parent_did(node_id); + tcx.item_tables(owner).node_id_to_type(node_id) + } - ty_generic_predicates(tcx, def_id, generics); + x => { + bug!("unexpected sort of node in type_of_def_id(): {:?}", x); + } + } +} + +fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Option> { + let icx = ItemCtxt::new(tcx, def_id); + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + match tcx.hir.expect_item(node_id).node { + hir::ItemDefaultImpl(_, ref ast_trait_ref) => { + Some(AstConv::instantiate_mono_trait_ref(&icx, + ast_trait_ref, + tcx.mk_self_type())) + } + hir::ItemImpl(.., ref opt_trait_ref, _, _) => { + opt_trait_ref.as_ref().map(|ast_trait_ref| { + let selfty = tcx.item_type(def_id); + AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) + }) + } + _ => bug!() + } } // Is it marked with ?Sized @@ -1389,37 +1298,87 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( .filter(move |l| !tcx.named_region_map.late_bound.contains(&l.lifetime.id)) } -fn ty_generic_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, - ast_generics: &hir::Generics) { +fn predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> ty::GenericPredicates<'tcx> { + use rustc::hir::map::*; + use rustc::hir::*; + + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let node = tcx.hir.get(node_id); + + let mut is_trait = None; + let icx = ItemCtxt::new(tcx, def_id); - let generics = tcx.item_generics(def_id); - let parent_count = generics.parent_count() as u32; - let has_own_self = generics.has_self && parent_count == 0; + let no_generics = hir::Generics::empty(); + let ast_generics = match node { + NodeTraitItem(item) => { + match item.node { + TraitItemKind::Method(ref sig, _) => &sig.generics, + _ => &no_generics + } + } - let mut predicates = vec![]; + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => &sig.generics, + _ => &no_generics + } + } - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let (is_trait, is_impl) = match tcx.hir.get(node_id) { - hir::map::NodeItem(item) => { + NodeItem(item) => { match item.node { - hir::ItemTrait(.., ref items) => { - (Some((ty::TraitRef { + ItemFn(.., ref generics, _) | + ItemImpl(_, _, ref generics, ..) | + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) | + ItemUnion(_, ref generics) => { + generics + } + + ItemTrait(_, ref generics, .., ref items) => { + is_trait = Some((ty::TraitRef { def_id: def_id, substs: Substs::identity_for_item(tcx, def_id) - }, items)), None) - } - hir::ItemImpl(..) => { - let self_ty = type_of_def_id(tcx, def_id); - let trait_ref = tcx.impl_trait_ref(def_id); - (None, Some((self_ty, trait_ref))) + }, items)); + generics } - _ => (None, None) + + _ => &no_generics } } - _ => (None, None) + + NodeForeignItem(item) => { + match item.node { + ForeignItemStatic(..) => &no_generics, + ForeignItemFn(_, _, ref generics) => generics + } + } + + NodeTy(&Ty { node: TyImplTrait(ref bounds), span, .. }) => { + let substs = Substs::identity_for_item(tcx, def_id); + let anon_ty = tcx.mk_anon(def_id, substs); + + // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. + let bounds = compute_bounds(&icx, anon_ty, bounds, + SizedByDefault::Yes, + span); + return ty::GenericPredicates { + parent: None, + predicates: bounds.predicates(tcx, anon_ty) + }; + } + + _ => &no_generics }; + let generics = tcx.item_generics(def_id); + let parent_count = generics.parent_count() as u32; + let has_own_self = generics.has_self && parent_count == 0; + + let mut predicates = vec![]; + // Below we'll consider the bounds on the type parameters (including `Self`) // and the explicit where-clauses, but to get the full set of predicates // on a trait we need to add in the supertrait bounds and bounds found on @@ -1543,16 +1502,18 @@ fn ty_generic_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // before uses of `U`. This avoids false ambiguity errors // in trait checking. See `setup_constraining_predicates` // for details. - if let Some((self_ty, trait_ref)) = is_impl { + if let NodeItem(&Item { node: ItemImpl(..), .. }) = node { + let self_ty = tcx.item_type(def_id); + let trait_ref = tcx.impl_trait_ref(def_id); ctp::setup_constraining_predicates(&mut predicates, trait_ref, &mut ctp::parameters_for_impl(self_ty, trait_ref)); } - tcx.maps.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + ty::GenericPredicates { parent: generics.parent, predicates: predicates - }); + } } pub enum SizedByDefault { Yes, No, } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 8e6e83bf3013f..0f425baec10bb 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -287,6 +287,7 @@ fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { pub fn provide(providers: &mut Providers) { collect::provide(providers); + check::provide(providers); } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 455a6a0fb32e2..096657a6e7ac8 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -909,25 +909,12 @@ fn int_type_of_word(s: &str) -> Option { #[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum ReprAttr { - ReprAny, ReprInt(IntType), ReprExtern, ReprPacked, ReprSimd, } -impl ReprAttr { - pub fn is_ffi_safe(&self) -> bool { - match *self { - ReprAny => false, - ReprInt(ity) => ity.is_ffi_safe(), - ReprExtern => true, - ReprPacked => false, - ReprSimd => true, - } - } -} - #[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum IntType { SignedInt(ast::IntTy), @@ -942,16 +929,6 @@ impl IntType { UnsignedInt(..) => false } } - fn is_ffi_safe(self) -> bool { - match self { - SignedInt(ast::IntTy::I8) | UnsignedInt(ast::UintTy::U8) | - SignedInt(ast::IntTy::I16) | UnsignedInt(ast::UintTy::U16) | - SignedInt(ast::IntTy::I32) | UnsignedInt(ast::UintTy::U32) | - SignedInt(ast::IntTy::I64) | UnsignedInt(ast::UintTy::U64) | - SignedInt(ast::IntTy::I128) | UnsignedInt(ast::UintTy::U128) => true, - SignedInt(ast::IntTy::Is) | UnsignedInt(ast::UintTy::Us) => false - } - } } pub trait HasAttrs: Sized { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index ce64aef516f49..fe492bd7fc849 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -773,7 +773,7 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> & for a in type_attrs { for r in &attr::find_repr_attrs(diagnostic, a) { repr_type_name = match *r { - attr::ReprAny | attr::ReprPacked | attr::ReprSimd => continue, + attr::ReprPacked | attr::ReprSimd => continue, attr::ReprExtern => "i32", attr::ReprInt(attr::SignedInt(ast::IntTy::Is)) => "isize", diff --git a/src/test/compile-fail/cycle-trait-default-type-trait.rs b/src/test/compile-fail/cycle-trait-default-type-trait.rs index 6825572b26c83..e6caeb34a8c8f 100644 --- a/src/test/compile-fail/cycle-trait-default-type-trait.rs +++ b/src/test/compile-fail/cycle-trait-default-type-trait.rs @@ -13,7 +13,6 @@ trait Foo> { //~^ ERROR unsupported cyclic reference - //~| ERROR unsupported cyclic reference } fn main() { } diff --git a/src/test/compile-fail/impl-trait/auto-trait-leak.rs b/src/test/compile-fail/impl-trait/auto-trait-leak.rs index f055d20e1343b..13e53cab17226 100644 --- a/src/test/compile-fail/impl-trait/auto-trait-leak.rs +++ b/src/test/compile-fail/impl-trait/auto-trait-leak.rs @@ -52,23 +52,20 @@ fn after() -> impl Fn(i32) { // independently resolved and only require the concrete // return type, which can't depend on the obligation. fn cycle1() -> impl Clone { + //~^ ERROR unsupported cyclic reference between types/traits detected + //~| cyclic reference + //~| NOTE the cycle begins when processing `cycle1`... + //~| NOTE ...which then requires processing `cycle1::{{impl-Trait}}`... + //~| NOTE ...which then again requires processing `cycle1`, completing the cycle. send(cycle2().clone()); - //~^ ERROR the trait bound `std::rc::Rc: std::marker::Send` is not satisfied - //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc` - //~| NOTE `std::rc::Rc` cannot be sent between threads safely - //~| NOTE required because it appears within the type `impl std::clone::Clone` - //~| NOTE required by `send` Rc::new(Cell::new(5)) } fn cycle2() -> impl Clone { + //~^ NOTE ...which then requires processing `cycle2::{{impl-Trait}}`... + //~| NOTE ...which then requires processing `cycle2`... send(cycle1().clone()); - //~^ ERROR the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied - //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc>` - //~| NOTE `std::rc::Rc>` cannot be sent between threads safely - //~| NOTE required because it appears within the type `impl std::clone::Clone` - //~| NOTE required by `send` Rc::new(String::from("foo")) } diff --git a/src/test/compile-fail/impl-trait/equality.rs b/src/test/compile-fail/impl-trait/equality.rs index 59ad1132b3501..36df4f0eb4d46 100644 --- a/src/test/compile-fail/impl-trait/equality.rs +++ b/src/test/compile-fail/impl-trait/equality.rs @@ -49,17 +49,6 @@ impl Leak for i32 { fn leak(self) -> i32 { self } } -trait CheckIfSend: Sized { - type T: Default; - fn check(self) -> Self::T { Default::default() } -} -impl CheckIfSend for T { - default type T = (); -} -impl CheckIfSend for T { - type T = bool; -} - fn main() { let _: u32 = hide(0_u32); //~^ ERROR mismatched types @@ -73,12 +62,6 @@ fn main() { //~| found type `::T` //~| expected i32, found associated type - let _: bool = CheckIfSend::check(hide(0_i32)); - //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `::T` - //~| expected bool, found associated type - let mut x = (hide(0_u32), hide(0_i32)); x = (x.1, //~^ ERROR mismatched types diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs index 7a5ef3540e93d..710d8e11ff034 100644 --- a/src/test/compile-fail/resolve-self-in-impl.rs +++ b/src/test/compile-fail/resolve-self-in-impl.rs @@ -26,6 +26,6 @@ impl Tr for Self {} //~ ERROR unsupported cyclic reference between types/traits impl Tr for S {} //~ ERROR unsupported cyclic reference between types/traits detected impl Self {} //~ ERROR unsupported cyclic reference between types/traits detected impl S {} //~ ERROR unsupported cyclic reference between types/traits detected -impl Tr for S {} //~ ERROR `Self` type is used before it's determined +impl Tr for S {} //~ ERROR unsupported cyclic reference between types/traits detected fn main() {} diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index da3a953d11eaa..048ccb529a24f 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -112,10 +112,13 @@ enum EnumChangeValueCStyleVariant0 { #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_dirty(label="HirBody", cfg="cfail2")] #[rustc_clean(label="HirBody", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant0 { Variant1, + + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] Variant2 = 22, } diff --git a/src/test/run-pass/impl-trait/auto-trait-leak.rs b/src/test/run-pass/impl-trait/auto-trait-leak.rs index c1201e7fa4f4c..011d910c5a50f 100644 --- a/src/test/run-pass/impl-trait/auto-trait-leak.rs +++ b/src/test/run-pass/impl-trait/auto-trait-leak.rs @@ -29,16 +29,3 @@ fn after() -> impl FnMut(i32) { let mut p = Box::new(0); move |x| *p = x } - -// Cycles should work as the deferred obligations are -// independently resolved and only require the concrete -// return type, which can't depend on the obligation. -fn cycle1() -> impl Clone { - send(cycle2().clone()); - 5 -} - -fn cycle2() -> impl Clone { - send(cycle1().clone()); - String::from("foo") -} diff --git a/src/test/run-pass/impl-trait/equality.rs b/src/test/run-pass/impl-trait/equality.rs index 72b0e588ff483..ceed454e5ad7e 100644 --- a/src/test/run-pass/impl-trait/equality.rs +++ b/src/test/run-pass/impl-trait/equality.rs @@ -28,6 +28,17 @@ impl Leak for T { fn leak(self) -> T { self } } +trait CheckIfSend: Sized { + type T: Default; + fn check(self) -> Self::T { Default::default() } +} +impl CheckIfSend for T { + default type T = (); +} +impl CheckIfSend for T { + type T = bool; +} + fn lucky_seven() -> impl Fn(usize) -> u8 { let a = [1, 2, 3, 4, 5, 6, 7]; move |i| a[i] @@ -40,4 +51,6 @@ fn main() { assert_eq!(std::mem::size_of_val(&lucky_seven()), 7); assert_eq!(Leak::::leak(hide(5_i32)), 5_i32); + + assert_eq!(CheckIfSend::check(hide(0_i32)), false); } From 9890e0466d951d1b0020ae38e2a4c0d8c43cfea1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 19 Feb 2017 14:37:50 +0200 Subject: [PATCH 13/17] rustc: allow handling cycle errors gracefully in on-demand. --- src/librustc/dep_graph/dep_tracking_map.rs | 6 ++ src/librustc/ty/maps.rs | 100 ++++++++++++------ src/librustc/ty/mod.rs | 32 +++--- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_typeck/astconv.rs | 9 +- src/librustc_typeck/collect.rs | 6 +- .../cycle-trait-default-type-trait.rs | 1 + 8 files changed, 104 insertions(+), 54 deletions(-) diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 2ffc3951cc94d..9f45e66f0d937 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -11,6 +11,7 @@ use hir::def_id::DefId; use rustc_data_structures::fx::FxHashMap; use std::cell::RefCell; +use std::collections::hash_map::Entry; use std::ops::Index; use std::hash::Hash; use std::marker::PhantomData; @@ -67,6 +68,11 @@ impl DepTrackingMap { assert!(old_value.is_none()); } + pub fn entry(&mut self, k: M::Key) -> Entry { + self.write(&k); + self.map.entry(k) + } + pub fn contains_key(&self, k: &M::Key) -> bool { self.read(k); self.map.contains_key(k) diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index ce4d1f5ec974c..26c92e3e7ecf7 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -13,10 +13,9 @@ use hir::def_id::{CrateNum, DefId}; use middle::const_val::ConstVal; use mir; use ty::{self, Ty, TyCtxt}; -use util::common::MemoizationMap; use rustc_data_structures::indexed_vec::IndexVec; -use std::cell::RefCell; +use std::cell::{RefCell, RefMut}; use std::rc::Rc; use syntax_pos::{Span, DUMMY_SP}; @@ -66,8 +65,13 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> { } } +pub struct CycleError<'a> { + span: Span, + cycle: RefMut<'a, [(Span, Query)]> +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - fn report_cycle(self, span: Span, cycle: &[(Span, Query)]) { + pub fn report_cycle(self, CycleError { span, cycle }: CycleError) { assert!(!cycle.is_empty()); let mut err = struct_span_err!(self.sess, span, E0391, @@ -88,16 +92,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { err.emit(); } - fn cycle_check(self, span: Span, query: Query, compute: F) -> R + fn cycle_check(self, span: Span, query: Query, compute: F) + -> Result> where F: FnOnce() -> R { { let mut stack = self.maps.query_stack.borrow_mut(); if let Some((i, _)) = stack.iter().enumerate().rev() .find(|&(_, &(_, ref q))| *q == query) { - let cycle = &stack[i..]; - self.report_cycle(span, cycle); - return R::from_cycle_error(self.global_tcx()); + return Err(CycleError { + span: span, + cycle: RefMut::map(stack, |stack| &mut stack[i..]) + }); } stack.push((span, query)); } @@ -105,7 +111,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let result = compute(); self.maps.query_stack.borrow_mut().pop(); - result + + Ok(result) } } @@ -140,7 +147,7 @@ macro_rules! define_maps { pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => { pub struct Maps<$tcx> { providers: IndexVec>, - pub query_stack: RefCell>, + query_stack: RefCell>, $($(#[$attr])* pub $name: RefCell>>),* } @@ -182,7 +189,60 @@ macro_rules! define_maps { $(impl<$tcx> DepTrackingMapConfig for queries::$name<$tcx> { type Key = $K; type Value = $V; - fn to_dep_node(key: &$K) -> DepNode { DepNode::$node(*key) } + + #[allow(unused)] + fn to_dep_node(key: &$K) -> DepNode { + use dep_graph::DepNode::*; + + $node(*key) + } + } + impl<'a, $tcx, 'lcx> queries::$name<$tcx> { + fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, + mut span: Span, + key: $K, + f: F) + -> Result> + where F: FnOnce(&$V) -> R + { + if let Some(result) = tcx.maps.$name.borrow().get(&key) { + return Ok(f(result)); + } + + // FIXME(eddyb) Get more valid Span's on queries. + if span == DUMMY_SP { + span = key.default_span(tcx); + } + + let _task = tcx.dep_graph.in_task(Self::to_dep_node(&key)); + + let result = tcx.cycle_check(span, Query::$name(key), || { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + })?; + + Ok(f(&tcx.maps.$name.borrow_mut().entry(key).or_insert(result))) + } + + pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) + -> Result<$V, CycleError<'a>> { + Self::try_get_with(tcx, span, key, Clone::clone) + } + + $(#[$attr])* + pub fn get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) -> $V { + Self::try_get(tcx, span, key).unwrap_or_else(|e| { + tcx.report_cycle(e); + Value::from_cycle_error(tcx.global_tcx()) + }) + } + + pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) { + match Self::try_get_with(tcx, span, key, |_| ()) { + Ok(()) => {} + Err(e) => tcx.report_cycle(e) + } + } })* pub struct Providers<$tcx> { @@ -203,26 +263,6 @@ macro_rules! define_maps { Providers { $($name),* } } } - - impl<'a, $tcx, 'lcx> Maps<$tcx> { - $($(#[$attr])* - pub fn $name(&self, - tcx: TyCtxt<'a, $tcx, 'lcx>, - mut span: Span, - key: $K) -> $V { - self.$name.memoize(key, || { - // FIXME(eddyb) Get more valid Span's on queries. - if span == DUMMY_SP { - span = key.default_span(tcx); - } - - tcx.cycle_check(span, Query::$name(key), || { - let provider = self.providers[key.map_crate()].$name; - provider(tcx.global_tcx(), key) - }) - }) - })* - } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 357d12bc4dd6c..5ab0c9e565519 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -75,6 +75,8 @@ pub use self::context::{Lift, TypeckTables}; pub use self::trait_def::{TraitDef, TraitFlags}; +pub use self::maps::queries; + pub mod adjustment; pub mod cast; pub mod error; @@ -1947,7 +1949,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn item_tables(self, def_id: DefId) -> &'gcx TypeckTables<'gcx> { - self.maps.typeck_tables(self, DUMMY_SP, def_id) + queries::typeck_tables::get(self, DUMMY_SP, def_id) } pub fn expr_span(self, id: NodeId) -> Span { @@ -2055,12 +2057,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized { - self.maps.custom_coerce_unsized_kind(self, DUMMY_SP, did) + queries::custom_coerce_unsized_kind::get(self, DUMMY_SP, did) } pub fn associated_item(self, def_id: DefId) -> AssociatedItem { if !def_id.is_local() { - return self.maps.associated_item(self, DUMMY_SP, def_id); + return queries::associated_item::get(self, DUMMY_SP, def_id); } self.maps.associated_item.memoize(def_id, || { @@ -2165,7 +2167,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn associated_item_def_ids(self, def_id: DefId) -> Rc> { if !def_id.is_local() { - return self.maps.associated_item_def_ids(self, DUMMY_SP, def_id); + return queries::associated_item_def_ids::get(self, DUMMY_SP, def_id); } self.maps.associated_item_def_ids.memoize(def_id, || { @@ -2200,7 +2202,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the trait-ref corresponding to a given impl, or None if it is /// an inherent impl. pub fn impl_trait_ref(self, id: DefId) -> Option> { - self.maps.impl_trait_ref(self, DUMMY_SP, id) + queries::impl_trait_ref::get(self, DUMMY_SP, id) } // Returns `ty::VariantDef` if `def` refers to a struct, @@ -2279,37 +2281,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If the given item is in an external crate, looks up its type and adds it to // the type cache. Returns the type parameters and type. pub fn item_type(self, did: DefId) -> Ty<'gcx> { - self.maps.ty(self, DUMMY_SP, did) + queries::ty::get(self, DUMMY_SP, did) } /// Given the did of a trait, returns its canonical trait ref. pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef { - self.maps.trait_def(self, DUMMY_SP, did) + queries::trait_def::get(self, DUMMY_SP, did) } /// Given the did of an ADT, return a reference to its definition. pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef { - self.maps.adt_def(self, DUMMY_SP, did) + queries::adt_def::get(self, DUMMY_SP, did) } /// Given the did of an item, returns its generics. pub fn item_generics(self, did: DefId) -> &'gcx Generics { - self.maps.generics(self, DUMMY_SP, did) + queries::generics::get(self, DUMMY_SP, did) } /// Given the did of an item, returns its full set of predicates. pub fn item_predicates(self, did: DefId) -> GenericPredicates<'gcx> { - self.maps.predicates(self, DUMMY_SP, did) + queries::predicates::get(self, DUMMY_SP, did) } /// Given the did of a trait, returns its superpredicates. pub fn item_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> { - self.maps.super_predicates(self, DUMMY_SP, did) + queries::super_predicates::get(self, DUMMY_SP, did) } /// Given the did of an item, returns its MIR, borrowed immutably. pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> { - self.maps.mir(self, DUMMY_SP, did).borrow() + queries::mir::get(self, DUMMY_SP, did).borrow() } /// If `type_needs_drop` returns true, then `ty` is definitely @@ -2361,7 +2363,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn item_variances(self, item_id: DefId) -> Rc> { - self.maps.variances(self, DUMMY_SP, item_id) + queries::variances::get(self, DUMMY_SP, item_id) } pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool { @@ -2436,11 +2438,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind { - self.maps.closure_kind(self, DUMMY_SP, def_id) + queries::closure_kind::get(self, DUMMY_SP, def_id) } pub fn closure_type(self, def_id: DefId) -> ty::PolyFnSig<'tcx> { - self.maps.closure_type(self, DUMMY_SP, def_id) + queries::closure_type::get(self, DUMMY_SP, def_id) } /// Given the def_id of an impl, return the def_id of the trait it implements. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index fc7b50f11da96..1b19e79d489d6 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -47,7 +47,7 @@ macro_rules! provide { (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident $($name:ident => $compute:block)*) => { pub fn provide<$lt>(providers: &mut Providers<$lt>) { $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) - -> as + -> as DepTrackingMapConfig>::Value { assert!(!$def_id.is_local()); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f5fd7a152a87e..e73700f04fa4e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { discr: variant.discr, evaluated_discr: match variant.discr { ty::VariantDiscr::Explicit(def_id) => { - tcx.maps.monomorphic_const_eval(tcx, DUMMY_SP, def_id).ok() + ty::queries::monomorphic_const_eval::get(tcx, DUMMY_SP, def_id).ok() } ty::VariantDiscr::Relative(_) => None }, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2d373ca7473e5..aae3947df1424 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -243,7 +243,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let default_needs_object_self = |p: &ty::TypeParameterDef| { if is_object && p.has_default { - if tcx.maps.ty(tcx, span, p.def_id).has_self_ty() { + if ty::queries::ty::get(tcx, span, p.def_id).has_self_ty() { // There is no suitable inference default for a type parameter // that references self, in an object type. return true; @@ -310,7 +310,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.err } else { // This is a default type parameter. - tcx.maps.ty(tcx, span, def.def_id).subst_spanned(tcx, substs, Some(span)) + ty::queries::ty::get(tcx, span, def.def_id) + .subst_spanned(tcx, substs, Some(span)) } } else { // We've already errored above about the mismatch. @@ -599,7 +600,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); - self.tcx().maps.ty(self.tcx(), span, did).subst(self.tcx(), substs) + ty::queries::ty::get(self.tcx(), span, did).subst(self.tcx(), substs) } /// Transform a PolyTraitRef into a PolyExistentialTraitRef by @@ -985,7 +986,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { assert_eq!(opt_self_ty, None); tcx.prohibit_type_params(&path.segments); - let ty = tcx.maps.ty(tcx, span, def_id); + let ty = ty::queries::ty::get(tcx, span, def_id); if let Some(free_substs) = self.get_free_substs() { ty.subst(tcx, free_substs) } else { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2a95f5f5d0804..83adbdaf0307d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -262,7 +262,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { def_id: DefId) -> ty::GenericPredicates<'tcx> { - self.tcx.maps.type_param_predicates(self.tcx, span, (self.item_def_id, def_id)) + ty::queries::type_param_predicates::get(self.tcx, span, (self.item_def_id, def_id)) } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { @@ -532,7 +532,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { hir::ItemTrait(..) => { tcx.item_generics(def_id); tcx.lookup_trait_def(def_id); - tcx.maps.super_predicates(tcx, it.span, def_id); + ty::queries::super_predicates::get(tcx, it.span, def_id); tcx.item_predicates(def_id); }, hir::ItemStruct(ref struct_def, _) | @@ -836,7 +836,7 @@ fn super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. for bound in superbounds.iter().filter_map(|p| p.to_opt_poly_trait_ref()) { - tcx.maps.super_predicates(tcx, item.span, bound.def_id()); + ty::queries::super_predicates::get(tcx, item.span, bound.def_id()); } ty::GenericPredicates { diff --git a/src/test/compile-fail/cycle-trait-default-type-trait.rs b/src/test/compile-fail/cycle-trait-default-type-trait.rs index e6caeb34a8c8f..6825572b26c83 100644 --- a/src/test/compile-fail/cycle-trait-default-type-trait.rs +++ b/src/test/compile-fail/cycle-trait-default-type-trait.rs @@ -13,6 +13,7 @@ trait Foo> { //~^ ERROR unsupported cyclic reference + //~| ERROR unsupported cyclic reference } fn main() { } From c832e6f3272fd01e22a6370e7745e305fe13a4c9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 19 Feb 2017 14:46:29 +0200 Subject: [PATCH 14/17] rustc_typeck: rework coherence to be almost completely on-demand. --- src/librustc/dep_graph/dep_node.rs | 2 + src/librustc/hir/lowering.rs | 22 +- src/librustc/hir/map/mod.rs | 20 + src/librustc/hir/mod.rs | 3 + src/librustc/infer/mod.rs | 2 +- src/librustc/middle/cstore.rs | 2 - src/librustc/traits/mod.rs | 2 +- src/librustc/traits/project.rs | 37 +- src/librustc/traits/specialize/mod.rs | 2 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/ty/contents.rs | 2 +- src/librustc/ty/maps.rs | 49 +++ src/librustc/ty/mod.rs | 56 ++- src/librustc/ty/trait_def.rs | 75 +++- src/librustc/ty/util.rs | 8 +- src/librustc_borrowck/borrowck/check_loans.rs | 2 +- .../borrowck/gather_loans/gather_moves.rs | 2 +- .../borrowck/gather_loans/move_error.rs | 2 +- .../borrowck/mir/elaborate_drops.rs | 2 +- .../borrowck/mir/gather_moves.rs | 2 +- src/librustc_borrowck/borrowck/mir/mod.rs | 2 +- src/librustc_const_eval/check_match.rs | 2 +- src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/test.rs | 2 +- .../calculate_svh/svh_visitor.rs | 3 + src/librustc_lint/builtin.rs | 4 +- src/librustc_metadata/cstore_impl.rs | 6 - src/librustc_metadata/decoder.rs | 21 +- src/librustc_mir/mir_map.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 4 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_passes/consts.rs | 4 +- src/librustc_passes/rvalues.rs | 2 +- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/glue.rs | 4 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/dropck.rs | 4 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 57 ++- src/librustc_typeck/coherence/inherent.rs | 356 ++++++++++++++++++ src/librustc_typeck/coherence/mod.rs | 203 ++++------ src/librustc_typeck/coherence/orphan.rs | 227 +---------- src/librustc_typeck/coherence/overlap.rs | 213 ++++------- src/librustc_typeck/coherence/unsafety.rs | 17 +- src/librustc_typeck/collect.rs | 12 +- src/librustc_typeck/lib.rs | 3 +- src/librustdoc/clean/inline.rs | 3 +- src/test/compile-fail/E0117.rs | 2 + .../coherence-cross-crate-conflict.rs | 1 + .../coherence-default-trait-impl.rs | 2 +- .../compile-fail/coherence-impls-sized.rs | 12 +- src/test/ui/span/E0204.stderr | 18 +- 53 files changed, 824 insertions(+), 670 deletions(-) create mode 100644 src/librustc_typeck/coherence/inherent.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 769c08a81efa6..e0233d6f8b98c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -70,6 +70,7 @@ pub enum DepNode { Resolve, EntryPoint, CheckEntryFn, + CoherenceCheckTrait(D), CoherenceCheckImpl(D), CoherenceOverlapCheck(D), CoherenceOverlapCheckSpecial(D), @@ -241,6 +242,7 @@ impl DepNode { MetaData(ref d) => op(d).map(MetaData), CollectItem(ref d) => op(d).map(CollectItem), CollectItemSig(ref d) => op(d).map(CollectItemSig), + CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait), CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl), CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck), CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial), diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index bfcaf1e00f06e..468421a68b54c 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -80,6 +80,9 @@ pub struct LoweringContext<'a> { impl_items: BTreeMap, bodies: FxHashMap, + trait_impls: BTreeMap>, + trait_default_impl: BTreeMap, + loop_scopes: Vec, is_in_loop_condition: bool, @@ -116,6 +119,8 @@ pub fn lower_crate(sess: &Session, trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), bodies: FxHashMap(), + trait_impls: BTreeMap::new(), + trait_default_impl: BTreeMap::new(), loop_scopes: Vec::new(), is_in_loop_condition: false, type_def_lifetime_params: DefIdMap(), @@ -201,6 +206,8 @@ impl<'a> LoweringContext<'a> { trait_items: self.trait_items, impl_items: self.impl_items, bodies: self.bodies, + trait_impls: self.trait_impls, + trait_default_impl: self.trait_default_impl, } } @@ -1089,14 +1096,27 @@ impl<'a> LoweringContext<'a> { hir::ItemUnion(vdata, self.lower_generics(generics)) } ItemKind::DefaultImpl(unsafety, ref trait_ref) => { + let trait_ref = self.lower_trait_ref(trait_ref); + + if let Def::Trait(def_id) = trait_ref.path.def { + self.trait_default_impl.insert(def_id, id); + } + hir::ItemDefaultImpl(self.lower_unsafety(unsafety), - self.lower_trait_ref(trait_ref)) + trait_ref) } ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => { let new_impl_items = impl_items.iter() .map(|item| self.lower_impl_item_ref(item)) .collect(); let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref)); + + if let Some(ref trait_ref) = ifce { + if let Def::Trait(def_id) = trait_ref.path.def { + self.trait_impls.entry(def_id).or_insert(vec![]).push(id); + } + } + hir::ItemImpl(self.lower_unsafety(unsafety), self.lower_impl_polarity(polarity), self.lower_generics(generics), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 13b786541c502..20b4d8d8a8f03 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -461,6 +461,26 @@ impl<'hir> Map<'hir> { } } + pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] { + self.dep_graph.read(DepNode::TraitImpls(trait_did)); + + // NB: intentionally bypass `self.forest.krate()` so that we + // do not trigger a read of the whole krate here + self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..]) + } + + pub fn trait_default_impl(&self, trait_did: DefId) -> Option { + self.dep_graph.read(DepNode::TraitImpls(trait_did)); + + // NB: intentionally bypass `self.forest.krate()` so that we + // do not trigger a read of the whole krate here + self.forest.krate.trait_default_impl.get(&trait_did).cloned() + } + + pub fn trait_is_auto(&self, trait_did: DefId) -> bool { + self.trait_default_impl(trait_did).is_some() + } + /// Get the attributes on the krate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e8c5f2447cd6f..8b6c75886baa8 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -410,6 +410,9 @@ pub struct Crate { pub trait_items: BTreeMap, pub impl_items: BTreeMap, pub bodies: FxHashMap, + + pub trait_impls: BTreeMap>, + pub trait_default_impl: BTreeMap, } impl Crate { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index d7f254df7538a..a929060cf9890 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -505,7 +505,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { evaluation_cache: traits::EvaluationCache::new(), projection_cache: RefCell::new(traits::ProjectionCache::new()), reported_trait_errors: RefCell::new(FxHashSet()), - projection_mode: Reveal::NotSpecializable, + projection_mode: Reveal::UserFacing, tainted_by_errors_flag: Cell::new(false), err_count_on_creation: self.sess.err_count(), obligations_in_snapshot: Cell::new(false), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index cb5ced57bd8b9..4a7027b8997a5 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -191,7 +191,6 @@ pub trait CrateStore { // flags fn is_const_fn(&self, did: DefId) -> bool; - fn is_defaulted_trait(&self, did: DefId) -> bool; fn is_default_impl(&self, impl_did: DefId) -> bool; fn is_foreign_item(&self, did: DefId) -> bool; fn is_dllimport_foreign_item(&self, def: DefId) -> bool; @@ -327,7 +326,6 @@ impl CrateStore for DummyCrateStore { // flags fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } - fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") } fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") } fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") } fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 117e16da26c3f..7e7d06e4b814e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -473,7 +473,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - tcx.infer_ctxt(elaborated_env, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| { let predicates = match fully_normalize(&infcx, cause, &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 448a3166bd860..3d8f9e41c675b 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -38,36 +38,6 @@ use util::common::FN_OUTPUT_NAME; /// more or less conservative. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Reveal { - /// FIXME (#32205) - /// At coherence-checking time, we're still constructing the - /// specialization graph, and thus we only project - /// non-`default` associated types that are defined directly in - /// the applicable impl. (This behavior should be improved over - /// time, to allow for successful projections modulo cycles - /// between different impls). - /// - /// Here's an example that will fail due to the restriction: - /// - /// ``` - /// trait Assoc { - /// type Output; - /// } - /// - /// impl Assoc for T { - /// type Output = bool; - /// } - /// - /// impl Assoc for u8 {} // <- inherits the non-default type from above - /// - /// trait Foo {} - /// impl Foo for u32 {} - /// impl Foo for ::Output {} // <- this projection will fail - /// ``` - /// - /// The projection would succeed if `Output` had been defined - /// directly in the impl for `u8`. - ExactMatch, - /// At type-checking time, we refuse to project any associated /// type that is marked `default`. Non-`default` ("final") types /// are always projected. This is necessary in general for @@ -90,7 +60,7 @@ pub enum Reveal { /// fn main() { /// let <() as Assoc>::Output = true; /// } - NotSpecializable, + UserFacing, /// At trans time, all monomorphic projections will succeed. /// Also, `impl Trait` is normalized to the concrete type, @@ -1347,8 +1317,9 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( -> Option> { let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id; + let trait_def = selcx.tcx().lookup_trait_def(trait_def_id); - if selcx.projection_mode() == Reveal::ExactMatch { + if !trait_def.is_complete(selcx.tcx()) { let impl_node = specialization_graph::Node::Impl(impl_def_id); for item in impl_node.items(selcx.tcx()) { if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name { @@ -1360,7 +1331,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( } None } else { - selcx.tcx().lookup_trait_def(trait_def_id) + trait_def .ancestors(impl_def_id) .defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type) .next() diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 0fe054b30ba31..79df7de04f540 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -189,7 +189,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .subst(tcx, &penv.free_substs); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(penv, Reveal::ExactMatch).enter(|infcx| { + let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 368b1fb4bcbd3..40eb69395678f 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 56621c57eb8f7..e14295982916f 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -219,7 +219,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { res = res - TC::OwnsDtor; } - if def.has_dtor() { + if def.has_dtor(tcx) { res = res | TC::OwnsDtor; } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 26c92e3e7ecf7..358d69ff8dba9 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -24,6 +24,15 @@ trait Key { fn default_span(&self, tcx: TyCtxt) -> Span; } +impl Key for CrateNum { + fn map_crate(&self) -> CrateNum { + *self + } + fn default_span(&self, _: TyCtxt) -> Span { + DUMMY_SP + } +} + impl Key for DefId { fn map_crate(&self) -> CrateNum { self.krate @@ -42,6 +51,15 @@ impl Key for (DefId, DefId) { } } +impl Key for (CrateNum, DefId) { + fn map_crate(&self) -> CrateNum { + self.0 + } + fn default_span(&self, tcx: TyCtxt) -> Span { + self.1.default_span(tcx) + } +} + trait Value<'tcx>: Sized { fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self; } @@ -141,6 +159,19 @@ impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> { } } +impl<'tcx> QueryDescription for queries::coherent_trait<'tcx> { + fn describe(tcx: TyCtxt, (_, def_id): (CrateNum, DefId)) -> String { + format!("coherence checking all impls of trait `{}`", + tcx.item_path_str(def_id)) + } +} + +impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + format!("coherence checking all inherent impls") + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -238,6 +269,12 @@ macro_rules! define_maps { } pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) { + // FIXME(eddyb) Move away from using `DepTrackingMap` + // so we don't have to explicitly ignore a false edge: + // we can't observe a value dependency, only side-effects, + // through `force`, and once everything has been updated, + // perhaps only diagnostics, if those, will remain. + let _ignore = tcx.dep_graph.in_ignore(); match Self::try_get_with(tcx, span, key, |_| ()) { Ok(()) => {} Err(e) => tcx.report_cycle(e) @@ -338,7 +375,19 @@ define_maps! { <'tcx> pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, + pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), + + pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (), + /// Results of evaluating monomorphic constants embedded in /// other items, such as enum variant explicit discriminants. pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result } + +fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode { + DepNode::CoherenceCheckTrait(def_id) +} + +fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode { + DepNode::Coherence +} diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5ab0c9e565519..55b6f61148d77 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1301,6 +1301,7 @@ bitflags! { const IS_FUNDAMENTAL = 1 << 4, const IS_UNION = 1 << 5, const IS_BOX = 1 << 6, + const IS_DTOR_VALID = 1 << 7, } } @@ -1522,8 +1523,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { } /// Returns whether this type has a destructor. - pub fn has_dtor(&self) -> bool { - self.destructor.get().is_some() + pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { + self.destructor(tcx).is_some() } /// Asserts this is a struct and returns the struct's unique @@ -1578,12 +1579,36 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } - pub fn destructor(&self) -> Option { - self.destructor.get() + pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { + if self.flags.get().intersects(AdtFlags::IS_DTOR_VALID) { + return self.destructor.get(); + } + + let dtor = self.destructor_uncached(tcx); + self.destructor.set(dtor); + self.flags.set(self.flags.get() | AdtFlags::IS_DTOR_VALID); + + dtor } - pub fn set_destructor(&self, dtor: DefId) { - self.destructor.set(Some(dtor)); + fn destructor_uncached(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { + let drop_trait = if let Some(def_id) = tcx.lang_items.drop_trait() { + def_id + } else { + return None; + }; + + queries::coherent_trait::get(tcx, DUMMY_SP, (LOCAL_CRATE, drop_trait)); + + let mut dtor = None; + let ty = tcx.item_type(self.did); + tcx.lookup_trait_def(drop_trait).for_each_relevant_impl(tcx, ty, |def_id| { + if let Some(item) = tcx.associated_items(def_id).next() { + dtor = Some(item.def_id); + } + }); + + dtor } pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>) @@ -2367,23 +2392,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool { - self.populate_implementations_for_trait_if_necessary(trait_def_id); - let def = self.lookup_trait_def(trait_def_id); def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL) } - /// Records a trait-to-implementation mapping. - pub fn record_trait_has_default_impl(self, trait_def_id: DefId) { - let def = self.lookup_trait_def(trait_def_id); - def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL) - } - /// Populates the type context with all the inherent implementations for /// the given type if necessary. pub fn populate_inherent_implementations_for_type_if_necessary(self, + span: Span, type_id: DefId) { if type_id.is_local() { + // Make sure coherence of inherent impls ran already. + ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE); return } @@ -2416,16 +2436,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let _ignore = self.dep_graph.in_ignore(); let def = self.lookup_trait_def(trait_id); - if def.flags.get().intersects(TraitFlags::IMPLS_VALID) { + if def.flags.get().intersects(TraitFlags::HAS_REMOTE_IMPLS) { return; } debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def); - if self.sess.cstore.is_defaulted_trait(trait_id) { - self.record_trait_has_default_impl(trait_id); - } - for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) { let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); @@ -2434,7 +2450,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { def.record_remote_impl(self, impl_def_id, trait_ref, parent); } - def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); + def.flags.set(def.flags.get() | TraitFlags::HAS_REMOTE_IMPLS); } pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind { diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 1dc494ca277b3..097b596c5ebb6 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -9,7 +9,7 @@ // except according to those terms. use dep_graph::DepNode; -use hir::def_id::DefId; +use hir::def_id::{DefId, LOCAL_CRATE}; use traits::{self, specialization_graph}; use ty; use ty::fast_reject; @@ -18,6 +18,9 @@ use std::cell::{Cell, RefCell}; use hir; use util::nodemap::FxHashMap; +use syntax::ast; +use syntax_pos::DUMMY_SP; + /// A trait's definition with type information. pub struct TraitDef { pub def_id: DefId, @@ -60,6 +63,11 @@ pub struct TraitDef { /// Various flags pub flags: Cell, + /// The number of impls we've added from the local crate. + /// When this number matches up the list in the HIR map, + /// we're done, and the specialization graph is correct. + local_impl_count: Cell, + /// The ICH of this trait's DefPath, cached here so it doesn't have to be /// recomputed all the time. pub def_path_hash: u64, @@ -78,6 +86,7 @@ impl<'a, 'gcx, 'tcx> TraitDef { nonblanket_impls: RefCell::new(FxHashMap()), blanket_impls: RefCell::new(vec![]), flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS), + local_impl_count: Cell::new(0), specialization_graph: RefCell::new(traits::specialization_graph::Graph::new()), def_path_hash: def_path_hash, } @@ -155,6 +164,13 @@ impl<'a, 'gcx, 'tcx> TraitDef { assert!(impl_def_id.is_local()); let was_new = self.record_impl(tcx, impl_def_id, impl_trait_ref); assert!(was_new); + + self.local_impl_count.set(self.local_impl_count.get() + 1); + } + + /// Records a trait-to-implementation mapping. + pub fn record_has_default_impl(&self) { + self.flags.set(self.flags.get() | TraitFlags::HAS_DEFAULT_IMPL); } /// Records a trait-to-implementation mapping for a non-local impl. @@ -194,10 +210,51 @@ impl<'a, 'gcx, 'tcx> TraitDef { specialization_graph::ancestors(self, of_impl) } + /// Whether the impl set and specialization graphs are complete. + pub fn is_complete(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { + tcx.populate_implementations_for_trait_if_necessary(self.def_id); + ty::queries::coherent_trait::try_get(tcx, DUMMY_SP, (LOCAL_CRATE, self.def_id)).is_ok() + } + + /// If any local impls haven't been added yet, returns + /// Some(list of local impls for this trait). + fn missing_local_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) + -> Option<&'gcx [ast::NodeId]> { + if self.flags.get().intersects(TraitFlags::HAS_LOCAL_IMPLS) { + return None; + } + + if self.is_complete(tcx) { + self.flags.set(self.flags.get() | TraitFlags::HAS_LOCAL_IMPLS); + return None; + } + + let impls = tcx.hir.trait_impls(self.def_id); + assert!(self.local_impl_count.get() <= impls.len()); + if self.local_impl_count.get() == impls.len() { + self.flags.set(self.flags.get() | TraitFlags::HAS_LOCAL_IMPLS); + return None; + } + + Some(impls) + } + pub fn for_each_impl(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) { self.read_trait_impls(tcx); tcx.populate_implementations_for_trait_if_necessary(self.def_id); + let local_impls = self.missing_local_impls(tcx); + if let Some(impls) = local_impls { + for &id in impls { + f(tcx.hir.local_def_id(id)); + } + } + let mut f = |def_id: DefId| { + if !(local_impls.is_some() && def_id.is_local()) { + f(def_id); + } + }; + for &impl_def_id in self.blanket_impls.borrow().iter() { f(impl_def_id); } @@ -217,9 +274,20 @@ impl<'a, 'gcx, 'tcx> TraitDef { mut f: F) { self.read_trait_impls(tcx); - tcx.populate_implementations_for_trait_if_necessary(self.def_id); + let local_impls = self.missing_local_impls(tcx); + if let Some(impls) = local_impls { + for &id in impls { + f(tcx.hir.local_def_id(id)); + } + } + let mut f = |def_id: DefId| { + if !(local_impls.is_some() && def_id.is_local()) { + f(def_id); + } + }; + for &impl_def_id in self.blanket_impls.borrow().iter() { f(impl_def_id); } @@ -258,6 +326,7 @@ bitflags! { const HAS_DEFAULT_IMPL = 1 << 0, const IS_OBJECT_SAFE = 1 << 1, const OBJECT_SAFETY_VALID = 1 << 2, - const IMPLS_VALID = 1 << 3, + const HAS_REMOTE_IMPLS = 1 << 3, + const HAS_LOCAL_IMPLS = 1 << 4, } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d1c22651a9e00..64480e510229e 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -149,7 +149,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(), CopyImplementationError> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(self.clone(), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(self.clone(), Reveal::UserFacing).enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt) @@ -171,7 +171,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { } } - if adt.has_dtor() { + if adt.has_dtor(tcx) { return Err(CopyImplementationError::HasDestructor); } @@ -353,7 +353,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// (This allows programs to make cyclic structures without /// resorting to unasfe means; see RFCs 769 and 1238). pub fn is_adt_dtorck(self, adt: &ty::AdtDef) -> bool { - let dtor_method = match adt.destructor() { + let dtor_method = match adt.destructor(self) { Some(dtor) => dtor, None => return false }; @@ -524,7 +524,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } } let result = - tcx.infer_ctxt(param_env.clone(), Reveal::ExactMatch) + tcx.infer_ctxt(param_env.clone(), Reveal::UserFacing) .enter(|infcx| { traits::type_known_to_meet_bound(&infcx, self, def_id, span) }); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index e3dec97472a48..3ce31882b86c4 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -783,7 +783,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => { match lp_base.to_type().sty { - ty::TyAdt(def, _) if def.has_dtor() => { + ty::TyAdt(def, _) if def.has_dtor(self.tcx()) => { // In the case where the owner implements drop, then // the path must be initialized to prevent a case of // partial reinitialization diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index c33ced52e2bd6..0577ba7f45a93 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -177,7 +177,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => { match b.ty.sty { ty::TyAdt(def, _) => { - if def.has_dtor() { + if def.has_dtor(bccx.tcx) { Some(cmt.clone()) } else { check_and_get_illegal_move_origin(bccx, b) diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index 47f8d978704f4..3678c2e55c1fd 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -150,7 +150,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Downcast(ref b, _) | Categorization::Interior(ref b, mc::InteriorField(_)) => { match b.ty.sty { - ty::TyAdt(def, _) if def.has_dtor() => { + ty::TyAdt(def, _) if def.has_dtor(bccx.tcx) => { let mut err = struct_span_err!(bccx, move_from.span, E0509, "cannot move out of type `{}`, \ which implements the `Drop` trait", diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index f8c0044774a01..13f898219bc12 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -898,7 +898,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { match ty.sty { ty::TyAdt(def, _) => { - if def.has_dtor() && !def.is_box() { + if def.has_dtor(self.tcx) && !def.is_box() { self.tcx.sess.span_warn( c.source_info.span, &format!("dataflow bug??? moving out of type with dtor {:?}", diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 35ace6628cfed..8d866676dbd18 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -289,7 +289,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { // error: can't move out of borrowed content ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove), // error: can't move out of struct with destructor - ty::TyAdt(adt, _) if adt.has_dtor() && !adt.is_box() => + ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() => return Err(MovePathError::IllegalMove), // move out of union - always move the entire union ty::TyAdt(adt, _) if adt.is_union() => diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index d9283e7037f50..1c9ee335699ae 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -248,7 +248,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx lv, ty); true } - ty::TyAdt(def, _) if (def.has_dtor() && !def.is_box()) || def.is_union() => { + ty::TyAdt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => { debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} Drop => true", lv, ty); true diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 9b30946c0bebb..db5df72267df7 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -516,7 +516,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::NotSpecializable).enter(|infcx| { + cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::UserFacing).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index eadb49a0731a4..0ab2255aab0ff 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -922,7 +922,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>( trait_ref); tcx.populate_implementations_for_trait_if_necessary(trait_id); - tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 36ba1e7f95bd8..9568cc3d6de0e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -151,7 +151,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { body(Env { infcx: &infcx }); let free_regions = FreeRegionMap::new(); diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 486900fc2fed5..150a2c39db7a8 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -1167,6 +1167,9 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { trait_items: _, impl_items: _, bodies: _, + + trait_impls: _, + trait_default_impl: _, } = *krate; visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 75269f58ed62d..b3f09c28277ad 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -523,7 +523,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { } _ => return, }; - if def.has_dtor() { + if def.has_dtor(cx.tcx) { return; } let parameter_environment = cx.tcx.empty_parameter_environment(); @@ -882,7 +882,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { let node_id = tcx.hir.as_local_node_id(method.def_id).unwrap(); let param_env = ty::ParameterEnvironment::for_item(tcx, node_id); - tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { // The method comes from a `T: Trait` bound. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 1b19e79d489d6..443e75e63d3dd 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -203,12 +203,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(did.krate).is_const_fn(did.index) } - fn is_defaulted_trait(&self, trait_def_id: DefId) -> bool - { - self.dep_graph.read(DepNode::MetaData(trait_def_id)); - self.get_crate_data(trait_def_id.krate).is_defaulted_trait(trait_def_id.index) - } - fn is_default_impl(&self, impl_did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(impl_did)); self.get_crate_data(impl_did.krate).is_default_impl(impl_did.index) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e81d752fde047..1627b22cd5fa1 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -501,10 +501,16 @@ impl<'a, 'tcx> CrateMetadata { _ => bug!(), }; - ty::TraitDef::new(self.local_def_id(item_id), - data.unsafety, - data.paren_sugar, - self.def_path(item_id).deterministic_hash(tcx)) + let def = ty::TraitDef::new(self.local_def_id(item_id), + data.unsafety, + data.paren_sugar, + self.def_path(item_id).deterministic_hash(tcx)); + + if data.has_default_impl { + def.record_has_default_impl(); + } + + def } fn get_variant(&self, @@ -1027,13 +1033,6 @@ impl<'a, 'tcx> CrateMetadata { self.dllimport_foreign_items.contains(&id) } - pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool { - match self.entry(trait_id).kind { - EntryKind::Trait(data) => data.decode(self).has_default_impl, - _ => bug!(), - } - } - pub fn is_default_impl(&self, impl_id: DefIndex) -> bool { match self.entry(impl_id).kind { EntryKind::DefaultImpl(_) => true, diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 34b701a3a9dd5..0d7be189f883a 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -96,7 +96,7 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) }; let src = MirSource::from_node(tcx, id); - tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| { let cx = Cx::new(&infcx, src); let mut mir = if let MirSource::Fn(id) = src { // fetch the fully liberated fn signature (that is, all bound diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4f80e21af64e4..9f38564d1e2f3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -758,7 +758,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { Rvalue::Aggregate(ref kind, _) => { if let AggregateKind::Adt(def, ..) = *kind { - if def.has_dtor() { + if def.has_dtor(self.tcx) { self.add(Qualif::NEEDS_DROP); self.deny_drop(); } @@ -1042,7 +1042,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty; - tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, ty, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 40485e4b66d77..af4a4a53905eb 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -699,7 +699,7 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { return; } let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); - tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| { let mut checker = TypeChecker::new(&infcx, src.item_id()); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index e3772a09968ec..e3a77a9359980 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(&body.value); } - let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| { let param_env = infcx.parameter_environment.clone(); let outer_penv = mem::replace(&mut self.param_env, param_env); euv::ExprUseVisitor::new(self, &infcx).consume_body(body); @@ -274,7 +274,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { /// instead of producing errors. fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) { match node_ty.sty { - ty::TyAdt(def, _) if def.has_dtor() => { + ty::TyAdt(def, _) if def.has_dtor(v.tcx) => { v.promotable = false; } _ => {} diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index 9de5ff541a52c..c367e71fcd246 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { fn visit_nested_body(&mut self, body_id: hir::BodyId) { let body = self.tcx.hir.body(body_id); - self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| { let mut delegate = RvalueContextDelegate { tcx: infcx.tcx, param_env: &infcx.parameter_environment diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 14ef48a902703..b12c1220b2b4d 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -754,7 +754,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // If the type implements Drop, also add a translation item for the // monomorphized Drop::drop() implementation. let destructor_did = match ty.sty { - ty::TyAdt(def, _) => def.destructor(), + ty::TyAdt(def, _) => def.destructor(scx.tcx()), _ => None }; diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 58e0a9e589f33..32fc3d5af2445 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -237,7 +237,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi bcx.call(dtor, &[ptr.llval], None); bcx } - ty::TyAdt(def, ..) if def.has_dtor() && !skip_dtor => { + ty::TyAdt(def, ..) if def.has_dtor(bcx.tcx()) && !skip_dtor => { let shallow_drop = def.is_union(); let tcx = bcx.tcx(); @@ -265,7 +265,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi traits::VtableImpl(data) => data, _ => bug!("dtor for {:?} is not an impl???", t) }; - let dtor_did = def.destructor().unwrap(); + let dtor_did = def.destructor(tcx).unwrap(); let callee = Callee::def(bcx.ccx, dtor_did, vtbl.substs); let fn_ty = callee.direct_fn_type(bcx.ccx, &[]); let llret; diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 06cf653e29368..0e9abaf1cf955 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -224,7 +224,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_param_env, normalize_cause.clone()); - tcx.infer_ctxt(trait_param_env, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| { let inh = Inherited::new(infcx); let infcx = &inh.infcx; let fulfillment_cx = &inh.fulfillment_cx; @@ -730,7 +730,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_trait_ref: ty::TraitRef<'tcx>) { debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); // The below is for the most part highly similar to the procedure diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 385ea7d52e1ce..07cc35ed67bbb 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -80,7 +80,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id); - tcx.infer_ctxt(impl_param_env, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|infcx| { let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -554,7 +554,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Find the `impl<..> Drop for _` to inspect any // attributes attached to the impl's generics. - let dtor_method = adt_def.destructor() + let dtor_method = adt_def.destructor(tcx) .expect("dtorck type without destructor impossible"); let method = tcx.associated_item(dtor_method); let impl_def_id = method.container.id(); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b6071d01ff1cf..dfa7ababca0bb 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -481,7 +481,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) { // Read the inherent implementation candidates for this type from the // metadata if necessary. - self.tcx.populate_inherent_implementations_for_type_if_necessary(def_id); + self.tcx.populate_inherent_implementations_for_type_if_necessary(self.span, def_id); if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) { for &impl_def_id in impl_infos.iter() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 68d8280d397d7..aa1fc0f8579da 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -477,7 +477,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { let tables = ty::TypeckTables::empty(); let param_env = ParameterEnvironment::for_item(tcx, id); InheritedBuilder { - infcx: tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable) + infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing) } } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index bfe8abb201cae..3cdf9fc93ae60 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -26,47 +26,38 @@ use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use rustc::hir::{self, ItemImpl}; -pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - check_trait(tcx, tcx.lang_items.drop_trait(), visit_implementation_of_drop); - check_trait(tcx, tcx.lang_items.copy_trait(), visit_implementation_of_copy); - check_trait( - tcx, - tcx.lang_items.coerce_unsized_trait(), - visit_implementation_of_coerce_unsized); +pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) { + Checker { tcx, trait_def_id } + .check(tcx.lang_items.drop_trait(), visit_implementation_of_drop) + .check(tcx.lang_items.copy_trait(), visit_implementation_of_copy) + .check(tcx.lang_items.coerce_unsized_trait(), + visit_implementation_of_coerce_unsized); } -fn check_trait<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - trait_def_id: Option, - mut f: F) - where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId) -{ - if let Some(trait_def_id) = trait_def_id { - let mut impls = vec![]; - tcx.lookup_trait_def(trait_def_id).for_each_impl(tcx, |did| { - impls.push(did); - }); - impls.sort(); - for impl_def_id in impls { - f(tcx, trait_def_id, impl_def_id); +struct Checker<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + trait_def_id: DefId +} + +impl<'a, 'tcx> Checker<'a, 'tcx> { + fn check(&self, trait_def_id: Option, mut f: F) -> &Self + where F: FnMut(TyCtxt<'a, 'tcx, 'tcx>, DefId, DefId) + { + if Some(self.trait_def_id) == trait_def_id { + for &impl_id in self.tcx.hir.trait_impls(self.trait_def_id) { + let impl_def_id = self.tcx.hir.local_def_id(impl_id); + f(self.tcx, self.trait_def_id, impl_def_id); + } } + self } } fn visit_implementation_of_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _drop_did: DefId, impl_did: DefId) { - let items = tcx.associated_item_def_ids(impl_did); - if items.is_empty() { - // We'll error out later. For now, just don't ICE. - return; - } - let method_def_id = items[0]; - - let self_type = tcx.item_type(impl_did); - match self_type.sty { - ty::TyAdt(type_def, _) => { - type_def.set_destructor(method_def_id); - } + match tcx.item_type(impl_did).sty { + ty::TyAdt(..) => {} _ => { // Destructors only work on nominal types. if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_did) { @@ -205,7 +196,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt(param_env, Reveal::ExactMatch).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, diff --git a/src/librustc_typeck/coherence/inherent.rs b/src/librustc_typeck/coherence/inherent.rs new file mode 100644 index 0000000000000..e3b4ba9eb1b9e --- /dev/null +++ b/src/librustc_typeck/coherence/inherent.rs @@ -0,0 +1,356 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::dep_graph::DepNode; +use rustc::hir::def_id::DefId; +use rustc::hir; +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::lint; +use rustc::traits::{self, Reveal}; +use rustc::ty::{self, TyCtxt}; + +use syntax::ast; +use syntax_pos::Span; + +struct InherentCollect<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx> +} + +impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { + fn visit_item(&mut self, item: &hir::Item) { + let (unsafety, ty) = match item.node { + hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty), + _ => return + }; + + match unsafety { + hir::Unsafety::Normal => { + // OK + } + hir::Unsafety::Unsafe => { + span_err!(self.tcx.sess, + item.span, + E0197, + "inherent impls cannot be declared as unsafe"); + } + } + + let def_id = self.tcx.hir.local_def_id(item.id); + let self_ty = self.tcx.item_type(def_id); + match self_ty.sty { + ty::TyAdt(def, _) => { + self.check_def_id(item, def.did); + } + ty::TyDynamic(ref data, ..) if data.principal().is_some() => { + self.check_def_id(item, data.principal().unwrap().def_id()); + } + ty::TyChar => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.char_impl(), + "char", + "char", + item.span); + } + ty::TyStr => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.str_impl(), + "str", + "str", + item.span); + } + ty::TySlice(_) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.slice_impl(), + "slice", + "[T]", + item.span); + } + ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.const_ptr_impl(), + "const_ptr", + "*const T", + item.span); + } + ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.mut_ptr_impl(), + "mut_ptr", + "*mut T", + item.span); + } + ty::TyInt(ast::IntTy::I8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i8_impl(), + "i8", + "i8", + item.span); + } + ty::TyInt(ast::IntTy::I16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i16_impl(), + "i16", + "i16", + item.span); + } + ty::TyInt(ast::IntTy::I32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i32_impl(), + "i32", + "i32", + item.span); + } + ty::TyInt(ast::IntTy::I64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i64_impl(), + "i64", + "i64", + item.span); + } + ty::TyInt(ast::IntTy::I128) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i128_impl(), + "i128", + "i128", + item.span); + } + ty::TyInt(ast::IntTy::Is) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.isize_impl(), + "isize", + "isize", + item.span); + } + ty::TyUint(ast::UintTy::U8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u8_impl(), + "u8", + "u8", + item.span); + } + ty::TyUint(ast::UintTy::U16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u16_impl(), + "u16", + "u16", + item.span); + } + ty::TyUint(ast::UintTy::U32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u32_impl(), + "u32", + "u32", + item.span); + } + ty::TyUint(ast::UintTy::U64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u64_impl(), + "u64", + "u64", + item.span); + } + ty::TyUint(ast::UintTy::U128) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u128_impl(), + "u128", + "u128", + item.span); + } + ty::TyUint(ast::UintTy::Us) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.usize_impl(), + "usize", + "usize", + item.span); + } + ty::TyFloat(ast::FloatTy::F32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f32_impl(), + "f32", + "f32", + item.span); + } + ty::TyFloat(ast::FloatTy::F64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f64_impl(), + "f64", + "f64", + item.span); + } + ty::TyError => { + return; + } + _ => { + struct_span_err!(self.tcx.sess, + ty.span, + E0118, + "no base type found for inherent implementation") + .span_label(ty.span, &format!("impl requires a base type")) + .note(&format!("either implement a trait on it or create a newtype \ + to wrap it instead")) + .emit(); + return; + } + } + } + + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } +} + +impl<'a, 'tcx> InherentCollect<'a, 'tcx> { + fn check_def_id(&self, item: &hir::Item, def_id: DefId) { + if def_id.is_local() { + // Add the implementation to the mapping from implementation to base + // type def ID, if there is a base type for this implementation and + // the implementation does not have any associated traits. + let impl_def_id = self.tcx.hir.local_def_id(item.id); + + // Subtle: it'd be better to collect these into a local map + // and then write the vector only once all items are known, + // but that leads to degenerate dep-graphs. The problem is + // that the write of that big vector winds up having reads + // from *all* impls in the krate, since we've lost the + // precision basically. This would be ok in the firewall + // model so once we've made progess towards that we can modify + // the strategy here. In the meantime, using `push` is ok + // because we are doing this as a pre-pass before anyone + // actually reads from `inherent_impls` -- and we know this is + // true beacuse we hold the refcell lock. + self.tcx.maps.inherent_impls.borrow_mut().push(def_id, impl_def_id); + } else { + struct_span_err!(self.tcx.sess, + item.span, + E0116, + "cannot define inherent `impl` for a type outside of the crate \ + where the type is defined") + .span_label(item.span, + &format!("impl for type defined outside of crate.")) + .note("define and implement a trait or new type instead") + .emit(); + } + } + + fn check_primitive_impl(&self, + impl_def_id: DefId, + lang_def_id: Option, + lang: &str, + ty: &str, + span: Span) { + match lang_def_id { + Some(lang_def_id) if lang_def_id == impl_def_id => { + // OK + } + _ => { + struct_span_err!(self.tcx.sess, + span, + E0390, + "only a single inherent implementation marked with `#[lang = \ + \"{}\"]` is allowed for the `{}` primitive", + lang, + ty) + .span_help(span, "consider using a trait to implement these methods") + .emit(); + } + } + } +} + +struct InherentOverlapChecker<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx> +} + +impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { + fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) { + #[derive(Copy, Clone, PartialEq)] + enum Namespace { + Type, + Value, + } + + let name_and_namespace = |def_id| { + let item = self.tcx.associated_item(def_id); + (item.name, match item.kind { + ty::AssociatedKind::Type => Namespace::Type, + ty::AssociatedKind::Const | + ty::AssociatedKind::Method => Namespace::Value, + }) + }; + + let impl_items1 = self.tcx.associated_item_def_ids(impl1); + let impl_items2 = self.tcx.associated_item_def_ids(impl2); + + for &item1 in &impl_items1[..] { + let (name, namespace) = name_and_namespace(item1); + + for &item2 in &impl_items2[..] { + if (name, namespace) == name_and_namespace(item2) { + let msg = format!("duplicate definitions with name `{}`", name); + let node_id = self.tcx.hir.as_local_node_id(item1).unwrap(); + self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, + node_id, + self.tcx.span_of_impl(item1).unwrap(), + msg); + } + } + } + } + + fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) { + let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id)); + + let inherent_impls = self.tcx.maps.inherent_impls.borrow(); + let impls = match inherent_impls.get(&ty_def_id) { + Some(impls) => impls, + None => return, + }; + + for (i, &impl1_def_id) in impls.iter().enumerate() { + for &impl2_def_id in &impls[(i + 1)..] { + self.tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { + if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { + self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) + } + }); + } + } + } +} + +impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> { + fn visit_item(&mut self, item: &'v hir::Item) { + match item.node { + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemTrait(..) | + hir::ItemUnion(..) => { + let type_def_id = self.tcx.hir.local_def_id(item.id); + self.check_for_overlapping_inherent_impls(type_def_id); + } + _ => {} + } + } + + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } +} + +pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, + &mut InherentCollect { tcx }); + tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial, + &mut InherentOverlapChecker { tcx }); +} diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index ed5ca79a70661..9ecf42daeaae5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -15,146 +15,72 @@ // done by the orphan and overlap modules. Then we build up various // mappings. That mapping code resides here. -use dep_graph::DepTrackingMap; -use hir::def_id::DefId; -use rustc::ty::{self, maps, TyCtxt, TypeFoldable}; -use rustc::ty::{Ty, TyBool, TyChar, TyError}; -use rustc::ty::{TyParam, TyRawPtr}; -use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple}; -use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; -use rustc::ty::{TyUint, TyClosure, TyFnDef, TyFnPtr}; -use rustc::ty::{TyProjection, TyAnon}; -use syntax_pos::Span; +use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc::ty::{self, TyCtxt, TypeFoldable}; +use rustc::ty::maps::Providers; use rustc::dep_graph::DepNode; -use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::{Item, ItemImpl}; -use rustc::hir; -use std::cell::RefMut; + +use syntax::ast; +use syntax_pos::DUMMY_SP; mod builtin; +mod inherent; mod orphan; mod overlap; mod unsafety; -struct CoherenceCollect<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - inherent_impls: RefMut<'a, DepTrackingMap>>, -} - -impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { - fn visit_item(&mut self, item: &Item) { - if let ItemImpl(..) = item.node { - self.check_implementation(item) - } - } - - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { - } -} - -impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> { - fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let inherent_impls = tcx.maps.inherent_impls.borrow_mut(); - let mut this = &mut CoherenceCollect { tcx, inherent_impls }; - - // Check implementations and traits. This populates the tables - // containing the inherent methods and extension methods. It also - // builds up the trait inheritance table. - tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, this); - } +fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { + let impl_def_id = tcx.hir.local_def_id(node_id); - // Returns the def ID of the base type, if there is one. - fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { - match ty.sty { - TyAdt(def, _) => Some(def.did), + // If there are no traits, then this implementation must have a + // base type. - TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()), + if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { + debug!("(checking implementation) adding impl for trait '{:?}', item '{}'", + trait_ref, + tcx.item_path_str(impl_def_id)); - TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) | - TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError | - TyNever | TyRawPtr(_) | TyRef(..) | TyProjection(..) => None, - - TyInfer(..) | TyClosure(..) | TyAnon(..) => { - // `ty` comes from a user declaration so we should only expect types - // that the user can type - span_bug!(span, - "coherence encountered unexpected type searching for base type: {}", - ty); - } + // Skip impls where one of the self type is an error type. + // This occurs with e.g. resolve failures (#30589). + if trait_ref.references_error() { + return; } - } - fn check_implementation(&mut self, item: &Item) { - let tcx = self.tcx; - let impl_did = tcx.hir.local_def_id(item.id); - let self_type = tcx.item_type(impl_did); - - // If there are no traits, then this implementation must have a - // base type. - - if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { - debug!("(checking implementation) adding impl for trait '{:?}', item '{}'", - trait_ref, - item.name); - - // Skip impls where one of the self type is an error type. - // This occurs with e.g. resolve failures (#30589). - if trait_ref.references_error() { - return; - } - - enforce_trait_manually_implementable(self.tcx, item.span, trait_ref.def_id); - self.add_trait_impl(trait_ref, impl_did); - } else { - // Skip inherent impls where the self type is an error - // type. This occurs with e.g. resolve failures (#30589). - if self_type.references_error() { - return; - } - - // Add the implementation to the mapping from implementation to base - // type def ID, if there is a base type for this implementation and - // the implementation does not have any associated traits. - if let Some(base_def_id) = self.get_base_type_def_id(item.span, self_type) { - self.add_inherent_impl(base_def_id, impl_did); - } - } + enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id); + let trait_def = tcx.lookup_trait_def(trait_ref.def_id); + trait_def.record_local_impl(tcx, impl_def_id, trait_ref); } +} + +fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) { + let did = Some(trait_def_id); + let li = &tcx.lang_items; - fn add_inherent_impl(&mut self, base_def_id: DefId, impl_def_id: DefId) { - // Subtle: it'd be better to collect these into a local map - // and then write the vector only once all items are known, - // but that leads to degenerate dep-graphs. The problem is - // that the write of that big vector winds up having reads - // from *all* impls in the krate, since we've lost the - // precision basically. This would be ok in the firewall - // model so once we've made progess towards that we can modify - // the strategy here. In the meantime, using `push` is ok - // because we are doing this as a pre-pass before anyone - // actually reads from `inherent_impls` -- and we know this is - // true beacuse we hold the refcell lock. - self.inherent_impls.push(base_def_id, impl_def_id); + // Disallow *all* explicit impls of `Sized` and `Unsize` for now. + if did == li.sized_trait() { + let span = tcx.span_of_impl(impl_def_id).unwrap(); + struct_span_err!(tcx.sess, + span, + E0322, + "explicit impls for the `Sized` trait are not permitted") + .span_label(span, &format!("impl of 'Sized' not allowed")) + .emit(); + return; } - fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) { - debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}", - impl_trait_ref, - impl_def_id); - let trait_def = self.tcx.lookup_trait_def(impl_trait_ref.def_id); - trait_def.record_local_impl(self.tcx, impl_def_id, impl_trait_ref); + if did == li.unsize_trait() { + let span = tcx.span_of_impl(impl_def_id).unwrap(); + span_err!(tcx.sess, + span, + E0328, + "explicit impls for the `Unsize` trait are not permitted"); + return; } -} -fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) { if tcx.sess.features.borrow().unboxed_closures { - // the feature gate allows all of them + // the feature gate allows all Fn traits return; } - let did = Some(trait_def_id); - let li = &tcx.lang_items; let trait_name = if did == li.fn_trait() { "Fn" @@ -166,7 +92,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def return; // everything OK }; let mut err = struct_span_err!(tcx.sess, - sp, + tcx.span_of_impl(impl_def_id).unwrap(), E0183, "manual implementations of `{}` are experimental", trait_name); @@ -175,12 +101,41 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def err.emit(); } -pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - CoherenceCollect::check(tcx); +pub fn provide(providers: &mut Providers) { + *providers = Providers { + coherent_trait, + coherent_inherent_impls, + ..*providers + }; +} +fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + (_, def_id): (CrateNum, DefId)) { + tcx.populate_implementations_for_trait_if_necessary(def_id); + + let impls = tcx.hir.trait_impls(def_id); + for &impl_id in impls { + check_impl(tcx, impl_id); + } + for &impl_id in impls { + overlap::check_impl(tcx, impl_id); + } + builtin::check_trait(tcx, def_id); +} + +fn coherent_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _: CrateNum) { + inherent::check(tcx); +} + +pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let _task = tcx.dep_graph.in_task(DepNode::Coherence); + for &trait_def_id in tcx.hir.krate().trait_impls.keys() { + ty::queries::coherent_trait::get(tcx, DUMMY_SP, (LOCAL_CRATE, trait_def_id)); + } + unsafety::check(tcx); orphan::check(tcx); - overlap::check(tcx); - builtin::check(tcx); + overlap::check_default_impls(tcx); + + ty::queries::coherent_inherent_impls::get(tcx, DUMMY_SP, LOCAL_CRATE); } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 9ef231499df51..ee361ab6073d4 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -11,11 +11,8 @@ //! Orphan checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. -use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::traits; use rustc::ty::{self, TyCtxt}; -use syntax::ast; -use syntax_pos::Span; use rustc::dep_graph::DepNode; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir; @@ -29,46 +26,6 @@ struct OrphanChecker<'cx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'tcx, 'tcx>, } -impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { - fn check_def_id(&self, item: &hir::Item, def_id: DefId) { - if def_id.krate != LOCAL_CRATE { - struct_span_err!(self.tcx.sess, - item.span, - E0116, - "cannot define inherent `impl` for a type outside of the crate \ - where the type is defined") - .span_label(item.span, - &format!("impl for type defined outside of crate.")) - .note("define and implement a trait or new type instead") - .emit(); - } - } - - fn check_primitive_impl(&self, - impl_def_id: DefId, - lang_def_id: Option, - lang: &str, - ty: &str, - span: Span) { - match lang_def_id { - Some(lang_def_id) if lang_def_id == impl_def_id => { - // OK - } - _ => { - struct_span_err!(self.tcx.sess, - span, - E0390, - "only a single inherent implementation marked with `#[lang = \ - \"{}\"]` is allowed for the `{}` primitive", - lang, - ty) - .span_help(span, "consider using a trait to implement these methods") - .emit(); - } - } - } -} - impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { /// Checks exactly one impl for orphan rules and other such /// restrictions. In this fn, it can happen that multiple errors @@ -78,168 +35,6 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { let def_id = self.tcx.hir.local_def_id(item.id); match item.node { - hir::ItemImpl(.., None, ref ty, _) => { - // For inherent impls, self type must be a nominal type - // defined in this crate. - debug!("coherence2::orphan check: inherent impl {}", - self.tcx.hir.node_to_string(item.id)); - let self_ty = self.tcx.item_type(def_id); - match self_ty.sty { - ty::TyAdt(def, _) => { - self.check_def_id(item, def.did); - } - ty::TyDynamic(ref data, ..) if data.principal().is_some() => { - self.check_def_id(item, data.principal().unwrap().def_id()); - } - ty::TyChar => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.char_impl(), - "char", - "char", - item.span); - } - ty::TyStr => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.str_impl(), - "str", - "str", - item.span); - } - ty::TySlice(_) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.slice_impl(), - "slice", - "[T]", - item.span); - } - ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.const_ptr_impl(), - "const_ptr", - "*const T", - item.span); - } - ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.mut_ptr_impl(), - "mut_ptr", - "*mut T", - item.span); - } - ty::TyInt(ast::IntTy::I8) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.i8_impl(), - "i8", - "i8", - item.span); - } - ty::TyInt(ast::IntTy::I16) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.i16_impl(), - "i16", - "i16", - item.span); - } - ty::TyInt(ast::IntTy::I32) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.i32_impl(), - "i32", - "i32", - item.span); - } - ty::TyInt(ast::IntTy::I64) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.i64_impl(), - "i64", - "i64", - item.span); - } - ty::TyInt(ast::IntTy::I128) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.i128_impl(), - "i128", - "i128", - item.span); - } - ty::TyInt(ast::IntTy::Is) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.isize_impl(), - "isize", - "isize", - item.span); - } - ty::TyUint(ast::UintTy::U8) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.u8_impl(), - "u8", - "u8", - item.span); - } - ty::TyUint(ast::UintTy::U16) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.u16_impl(), - "u16", - "u16", - item.span); - } - ty::TyUint(ast::UintTy::U32) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.u32_impl(), - "u32", - "u32", - item.span); - } - ty::TyUint(ast::UintTy::U64) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.u64_impl(), - "u64", - "u64", - item.span); - } - ty::TyUint(ast::UintTy::U128) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.u128_impl(), - "u128", - "u128", - item.span); - } - ty::TyUint(ast::UintTy::Us) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.usize_impl(), - "usize", - "usize", - item.span); - } - ty::TyFloat(ast::FloatTy::F32) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.f32_impl(), - "f32", - "f32", - item.span); - } - ty::TyFloat(ast::FloatTy::F64) => { - self.check_primitive_impl(def_id, - self.tcx.lang_items.f64_impl(), - "f64", - "f64", - item.span); - } - ty::TyError => { - return; - } - _ => { - struct_span_err!(self.tcx.sess, - ty.span, - E0118, - "no base type found for inherent implementation") - .span_label(ty.span, &format!("impl requires a base type")) - .note(&format!("either implement a trait on it or create a newtype \ - to wrap it instead")) - .emit(); - return; - } - } - } hir::ItemImpl(.., Some(_), _, _) => { // "Trait" impl debug!("coherence2::orphan check: trait impl {}", @@ -311,7 +106,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { trait_def_id, self.tcx.trait_has_default_impl(trait_def_id)); if self.tcx.trait_has_default_impl(trait_def_id) && - trait_def_id.krate != LOCAL_CRATE { + !trait_def_id.is_local() { let self_ty = trait_ref.self_ty(); let opt_self_def_id = match self_ty.sty { ty::TyAdt(self_def, _) => Some(self_def.did), @@ -346,31 +141,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { return; } } - - // Disallow *all* explicit impls of `Sized` and `Unsize` for now. - if Some(trait_def_id) == self.tcx.lang_items.sized_trait() { - struct_span_err!(self.tcx.sess, - item.span, - E0322, - "explicit impls for the `Sized` trait are not permitted") - .span_label(item.span, &format!("impl of 'Sized' not allowed")) - .emit(); - return; - } - if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() { - span_err!(self.tcx.sess, - item.span, - E0328, - "explicit impls for the `Unsize` trait are not permitted"); - return; - } } hir::ItemDefaultImpl(_, ref item_trait_ref) => { // "Trait" impl debug!("coherence2::orphan check: default trait impl {}", self.tcx.hir.node_to_string(item.id)); let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); - if trait_ref.def_id.krate != LOCAL_CRATE { + if !trait_ref.def_id.is_local() { struct_span_err!(self.tcx.sess, item_trait_ref.path.span, E0318, diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 45493d40eb802..d334d0c4338f9 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -12,102 +12,101 @@ //! same type. Likewise, no two inherent impls for a given type //! constructor provide a method with the same name. -use hir::def_id::DefId; -use rustc::traits::{self, Reveal}; +use rustc::traits; use rustc::ty::{self, TyCtxt, TypeFoldable}; use syntax::ast; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use util::nodemap::DefIdMap; -use lint; -pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut overlap = OverlapChecker { - tcx: tcx, - default_impls: DefIdMap(), - }; +pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let mut overlap = OverlapChecker { tcx }; // this secondary walk specifically checks for some other cases, // like defaulted traits, for which additional overlap rules exist tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial, &mut overlap); } -struct OverlapChecker<'cx, 'tcx: 'cx> { - tcx: TyCtxt<'cx, 'tcx, 'tcx>, - - // maps from a trait def-id to an impl id - default_impls: DefIdMap, -} +pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { + let impl_def_id = tcx.hir.local_def_id(node_id); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_def_id = trait_ref.def_id; -impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { - fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) { - #[derive(Copy, Clone, PartialEq)] - enum Namespace { - Type, - Value, - } + if trait_ref.references_error() { + debug!("coherence: skipping impl {:?} with error {:?}", + impl_def_id, trait_ref); + return + } - let name_and_namespace = |def_id| { - let item = self.tcx.associated_item(def_id); - (item.name, match item.kind { - ty::AssociatedKind::Type => Namespace::Type, - ty::AssociatedKind::Const | - ty::AssociatedKind::Method => Namespace::Value, - }) - }; - - let impl_items1 = self.tcx.associated_item_def_ids(impl1); - let impl_items2 = self.tcx.associated_item_def_ids(impl2); - - for &item1 in &impl_items1[..] { - let (name, namespace) = name_and_namespace(item1); - - for &item2 in &impl_items2[..] { - if (name, namespace) == name_and_namespace(item2) { - let msg = format!("duplicate definitions with name `{}`", name); - let node_id = self.tcx.hir.as_local_node_id(item1).unwrap(); - self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, - node_id, - self.tcx.span_of_impl(item1).unwrap(), - msg); - } + let _task = + tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id)); + + let def = tcx.lookup_trait_def(trait_def_id); + + // attempt to insert into the specialization graph + let insert_result = def.add_impl_for_specialization(tcx, impl_def_id); + + // insertion failed due to overlap + if let Err(overlap) = insert_result { + let mut err = struct_span_err!(tcx.sess, + tcx.span_of_impl(impl_def_id).unwrap(), + E0119, + "conflicting implementations of trait `{}`{}:", + overlap.trait_desc, + overlap.self_desc.clone().map_or(String::new(), + |ty| { + format!(" for type `{}`", ty) + })); + + match tcx.span_of_impl(overlap.with_impl) { + Ok(span) => { + err.span_label(span, &format!("first implementation here")); + err.span_label(tcx.span_of_impl(impl_def_id).unwrap(), + &format!("conflicting implementation{}", + overlap.self_desc + .map_or(String::new(), + |ty| format!(" for `{}`", ty)))); + } + Err(cname) => { + err.note(&format!("conflicting implementation in crate `{}`", cname)); } } + + err.emit(); } - fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) { - let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id)); - - let inherent_impls = self.tcx.maps.inherent_impls.borrow(); - let impls = match inherent_impls.get(&ty_def_id) { - Some(impls) => impls, - None => return, - }; - - for (i, &impl1_def_id) in impls.iter().enumerate() { - for &impl2_def_id in &impls[(i + 1)..] { - self.tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| { - if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { - self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) - } - }); + // check for overlap with the automatic `impl Trait for Trait` + if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty { + // This is something like impl Trait1 for Trait2. Illegal + // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. + + if data.principal().map_or(true, |p| !tcx.is_object_safe(p.def_id())) { + // This is an error, but it will be reported by wfcheck. Ignore it here. + // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. + } else { + let mut supertrait_def_ids = + traits::supertrait_def_ids(tcx, + data.principal().unwrap().def_id()); + if supertrait_def_ids.any(|d| d == trait_def_id) { + span_err!(tcx.sess, + tcx.span_of_impl(impl_def_id).unwrap(), + E0371, + "the object type `{}` automatically \ + implements the trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id)); } } } } +struct OverlapChecker<'cx, 'tcx: 'cx> { + tcx: TyCtxt<'cx, 'tcx, 'tcx>, +} + impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v hir::Item) { match item.node { - hir::ItemEnum(..) | - hir::ItemStruct(..) | - hir::ItemTrait(..) | - hir::ItemUnion(..) => { - let type_def_id = self.tcx.hir.local_def_id(item.id); - self.check_for_overlapping_inherent_impls(type_def_id); - } - hir::ItemDefaultImpl(..) => { // look for another default impl; note that due to the // general orphan/coherence rules, it must always be @@ -115,8 +114,8 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { let impl_def_id = self.tcx.hir.local_def_id(item.id); let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); - let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id); - if let Some(prev_id) = prev_default_impl { + let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap(); + if prev_id != item.id { let mut err = struct_span_err!(self.tcx.sess, self.tcx.span_of_impl(impl_def_id).unwrap(), E0521, @@ -131,76 +130,6 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { } } hir::ItemImpl(.., Some(_), _, _) => { - let impl_def_id = self.tcx.hir.local_def_id(item.id); - let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); - let trait_def_id = trait_ref.def_id; - - if trait_ref.references_error() { - debug!("coherence: skipping impl {:?} with error {:?}", - impl_def_id, trait_ref); - return - } - - let _task = - self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id)); - - let def = self.tcx.lookup_trait_def(trait_def_id); - - // attempt to insert into the specialization graph - let insert_result = def.add_impl_for_specialization(self.tcx, impl_def_id); - - // insertion failed due to overlap - if let Err(overlap) = insert_result { - let mut err = struct_span_err!(self.tcx.sess, - self.tcx.span_of_impl(impl_def_id).unwrap(), - E0119, - "conflicting implementations of trait `{}`{}:", - overlap.trait_desc, - overlap.self_desc.clone().map_or(String::new(), - |ty| { - format!(" for type `{}`", ty) - })); - - match self.tcx.span_of_impl(overlap.with_impl) { - Ok(span) => { - err.span_label(span, &format!("first implementation here")); - err.span_label(self.tcx.span_of_impl(impl_def_id).unwrap(), - &format!("conflicting implementation{}", - overlap.self_desc - .map_or(String::new(), - |ty| format!(" for `{}`", ty)))); - } - Err(cname) => { - err.note(&format!("conflicting implementation in crate `{}`", cname)); - } - } - - err.emit(); - } - - // check for overlap with the automatic `impl Trait for Trait` - if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty { - // This is something like impl Trait1 for Trait2. Illegal - // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - - if data.principal().map_or(true, |p| !self.tcx.is_object_safe(p.def_id())) { - // This is an error, but it will be reported by wfcheck. Ignore it here. - // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. - } else { - let mut supertrait_def_ids = - traits::supertrait_def_ids(self.tcx, - data.principal().unwrap().def_id()); - if supertrait_def_ids.any(|d| d == trait_def_id) { - span_err!(self.tcx.sess, - item.span, - E0371, - "the object type `{}` automatically \ - implements the trait `{}`", - trait_ref.self_ty(), - self.tcx.item_path_str(trait_def_id)); - } - } - } } _ => {} } diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 8c98e2952ebe9..22247d2531aec 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -31,20 +31,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { unsafety: hir::Unsafety, polarity: hir::ImplPolarity) { match self.tcx.impl_trait_ref(self.tcx.hir.local_def_id(item.id)) { - None => { - // Inherent impl. - match unsafety { - hir::Unsafety::Normal => { - // OK - } - hir::Unsafety::Unsafe => { - span_err!(self.tcx.sess, - item.span, - E0197, - "inherent impls cannot be declared as unsafe"); - } - } - } + None => {} Some(trait_ref) => { let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id); @@ -100,7 +87,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> { hir::ItemDefaultImpl(unsafety, _) => { self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive); } - hir::ItemImpl(unsafety, polarity, ref generics, ..) => { + hir::ItemImpl(unsafety, polarity, ref generics, Some(_), _, _) => { self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); } _ => {} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 83adbdaf0307d..ecdbf170702aa 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -519,9 +519,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) { convert_enum_variant_types(tcx, def_id, &enum_definition.variants); }, hir::ItemDefaultImpl(..) => { - if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { - tcx.record_trait_has_default_impl(trait_ref.def_id); - } + tcx.impl_trait_ref(def_id); } hir::ItemImpl(..) => { tcx.item_generics(def_id); @@ -869,7 +867,13 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx); - tcx.alloc_trait_def(ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash)) + let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash); + + if tcx.hir.trait_is_auto(def_id) { + def.record_has_default_impl(); + } + + tcx.alloc_trait_def(def) } fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 0f425baec10bb..2c325d46c0bc0 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -155,7 +155,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { match infcx.eq_types(false, &cause, expected, actual) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations @@ -287,6 +287,7 @@ fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { pub fn provide(providers: &mut Providers) { collect::provide(providers); + coherence::provide(providers); check::provide(providers); } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 61c2a3c9e9512..c4476483186c7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -15,6 +15,7 @@ use std::io; use std::iter::once; use syntax::ast; +use syntax_pos::DUMMY_SP; use rustc::hir; use rustc::hir::def::{Def, CtorKind}; @@ -231,7 +232,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef { pub fn build_impls(cx: &DocContext, did: DefId) -> Vec { let tcx = cx.tcx; - tcx.populate_inherent_implementations_for_type_if_necessary(did); + tcx.populate_inherent_implementations_for_type_if_necessary(DUMMY_SP, did); let mut impls = Vec::new(); if let Some(i) = tcx.maps.inherent_impls.borrow().get(&did) { diff --git a/src/test/compile-fail/E0117.rs b/src/test/compile-fail/E0117.rs index 4ba9c3382f35d..3da00da205fec 100644 --- a/src/test/compile-fail/E0117.rs +++ b/src/test/compile-fail/E0117.rs @@ -12,6 +12,8 @@ impl Drop for u32 {} //~ ERROR E0117 //~^ NOTE impl doesn't use types inside crate //~| NOTE the impl does not reference any types defined in this crate //~| NOTE define and implement a trait or new type instead +//~| ERROR the Drop trait may only be implemented on structures +//~| implementing Drop requires a struct fn main() { } diff --git a/src/test/compile-fail/coherence-cross-crate-conflict.rs b/src/test/compile-fail/coherence-cross-crate-conflict.rs index 9f74afbb2b3b5..aac870293fd55 100644 --- a/src/test/compile-fail/coherence-cross-crate-conflict.rs +++ b/src/test/compile-fail/coherence-cross-crate-conflict.rs @@ -17,6 +17,7 @@ use trait_impl_conflict::Foo; impl Foo for A { //~^ ERROR type parameter `A` must be used as the type parameter for some local type + //~| ERROR conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize` } fn main() { diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs index 3d109de76ccd1..15a80c64f8b06 100644 --- a/src/test/compile-fail/coherence-default-trait-impl.rs +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -13,9 +13,9 @@ trait MyTrait {} impl MyTrait for .. {} +//~^ ERROR redundant default implementations of trait `MyTrait` impl MyTrait for .. {} -//~^ ERROR redundant default implementations of trait `MyTrait` trait MySafeTrait {} diff --git a/src/test/compile-fail/coherence-impls-sized.rs b/src/test/compile-fail/coherence-impls-sized.rs index 79767e5157b14..60b5d14d1587a 100644 --- a/src/test/compile-fail/coherence-impls-sized.rs +++ b/src/test/compile-fail/coherence-impls-sized.rs @@ -27,14 +27,20 @@ impl Sized for TestE {} //~ ERROR E0322 impl Sized for MyType {} //~ ERROR E0322 //~^ impl of 'Sized' not allowed -impl Sized for (MyType, MyType) {} //~ ERROR E0117 +impl Sized for (MyType, MyType) {} //~ ERROR E0322 +//~^ impl of 'Sized' not allowed +//~| ERROR E0117 impl Sized for &'static NotSync {} //~ ERROR E0322 //~^ impl of 'Sized' not allowed -impl Sized for [MyType] {} //~ ERROR E0117 +impl Sized for [MyType] {} //~ ERROR E0322 +//~^ impl of 'Sized' not allowed +//~| ERROR E0117 -impl Sized for &'static [NotSync] {} //~ ERROR E0117 +impl Sized for &'static [NotSync] {} //~ ERROR E0322 +//~^ impl of 'Sized' not allowed +//~| ERROR E0117 fn main() { } diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr index 81a60a9dd3099..4fe6afaca8ec6 100644 --- a/src/test/ui/span/E0204.stderr +++ b/src/test/ui/span/E0204.stderr @@ -7,15 +7,6 @@ error[E0204]: the trait `Copy` may not be implemented for this type 15 | impl Copy for Foo { } | ^^^^ -error[E0204]: the trait `Copy` may not be implemented for this type - --> $DIR/E0204.rs:27:6 - | -23 | Bar { x: Vec }, - | ----------- this field does not implement `Copy` -... -27 | impl Copy for EFoo { } - | ^^^^ - error[E0204]: the trait `Copy` may not be implemented for this type --> $DIR/E0204.rs:17:10 | @@ -25,6 +16,15 @@ error[E0204]: the trait `Copy` may not be implemented for this type 19 | ty: &'a mut bool, | ---------------- this field does not implement `Copy` +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:27:6 + | +23 | Bar { x: Vec }, + | ----------- this field does not implement `Copy` +... +27 | impl Copy for EFoo { } + | ^^^^ + error[E0204]: the trait `Copy` may not be implemented for this type --> $DIR/E0204.rs:29:10 | From e7a48821c0d30ccd6b7ea88be24eed1bcba5f48a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 15 Feb 2017 15:00:20 +0200 Subject: [PATCH 15/17] rustc_const_eval: always demand typeck_tables for evaluating constants. --- src/librustc/diagnostics.rs | 73 -- src/librustc/lib.rs | 1 - src/librustc/middle/astconv_util.rs | 83 --- src/librustc/middle/const_val.rs | 21 +- src/librustc/mir/mod.rs | 6 +- src/librustc/ty/context.rs | 5 + src/librustc/ty/layout.rs | 7 +- src/librustc/ty/maps.rs | 2 +- src/librustc/ty/util.rs | 56 +- src/librustc_const_eval/_match.rs | 25 +- src/librustc_const_eval/check_match.rs | 2 +- src/librustc_const_eval/diagnostics.rs | 16 - src/librustc_const_eval/eval.rs | 693 ++++++------------ src/librustc_const_eval/lib.rs | 1 + src/librustc_const_eval/pattern.rs | 24 +- src/librustc_const_math/float.rs | 47 +- src/librustc_const_math/int.rs | 240 +++--- src/librustc_const_math/lib.rs | 2 +- src/librustc_lint/types.rs | 3 +- src/librustc_metadata/schema.rs | 10 +- src/librustc_mir/build/matches/mod.rs | 6 +- src/librustc_mir/build/matches/test.rs | 4 +- src/librustc_mir/build/mod.rs | 11 + src/librustc_mir/hair/cx/expr.rs | 4 +- src/librustc_mir/hair/cx/mod.rs | 4 +- src/librustc_mir/mir_map.rs | 4 +- src/librustc_passes/consts.rs | 14 +- src/librustc_trans/consts.rs | 10 +- src/librustc_trans/mir/block.rs | 2 +- src/librustc_trans/mir/constant.rs | 23 +- src/librustc_typeck/astconv.rs | 60 +- src/librustc_typeck/check/mod.rs | 8 +- src/librustc_typeck/check/writeback.rs | 52 +- src/librustc_typeck/collect.rs | 70 +- src/librustc_typeck/diagnostics.rs | 112 ++- src/test/compile-fail/E0306.rs | 24 - .../associated-const-array-len.rs | 3 +- ...ssociated-const-type-parameter-arrays-2.rs | 2 - .../associated-const-type-parameter-arrays.rs | 2 - src/test/compile-fail/const-array-oob.rs | 4 +- .../compile-fail/const-eval-overflow-4b.rs | 6 +- src/test/compile-fail/const-eval-span.rs | 7 +- .../compile-fail/const-integer-bool-ops.rs | 79 +- src/test/compile-fail/const-tup-index-span.rs | 4 +- src/test/compile-fail/discrim-ill-typed.rs | 16 +- .../compile-fail/enum-discrim-too-small.rs | 16 +- .../compile-fail/invalid-path-in-const.rs | 3 +- src/test/compile-fail/issue-22933-2.rs | 6 +- src/test/compile-fail/issue-23217.rs | 3 +- src/test/compile-fail/issue-28586.rs | 3 +- src/test/compile-fail/issue-31910.rs | 4 +- src/test/compile-fail/issue-3521.rs | 4 +- src/test/compile-fail/issue-39559.rs | 8 +- src/test/compile-fail/issue-8761.rs | 4 +- .../non-constant-expr-for-fixed-len-vec.rs | 1 - .../non-constant-expr-for-vec-repeat.rs | 2 - src/test/mir-opt/simplify_if.rs | 2 +- .../{compile-fail => run-pass}/issue-25145.rs | 6 +- .../E0079.rs => run-pass/issue-39548.rs} | 8 +- src/test/ui/resolve/levenshtein.stderr | 8 +- 60 files changed, 705 insertions(+), 1221 deletions(-) delete mode 100644 src/librustc/middle/astconv_util.rs delete mode 100644 src/test/compile-fail/E0306.rs rename src/test/{compile-fail => run-pass}/issue-25145.rs (86%) rename src/test/{compile-fail/E0079.rs => run-pass/issue-39548.rs} (75%) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 458a774c95645..b1b1b849437d1 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -390,44 +390,6 @@ RFC. It is, however, [currently unimplemented][iss15872]. [iss15872]: https://github.com/rust-lang/rust/issues/15872 "##, -E0109: r##" -You tried to give a type parameter to a type which doesn't need it. Erroneous -code example: - -```compile_fail,E0109 -type X = u32; // error: type parameters are not allowed on this type -``` - -Please check that you used the correct type and recheck its definition. Perhaps -it doesn't need the type parameter. - -Example: - -``` -type X = u32; // this compiles -``` - -Note that type parameters for enum-variant constructors go after the variant, -not after the enum (Option::None::, not Option::::None). -"##, - -E0110: r##" -You tried to give a lifetime parameter to a type which doesn't need it. -Erroneous code example: - -```compile_fail,E0110 -type X = u32<'static>; // error: lifetime parameters are not allowed on - // this type -``` - -Please check that the correct type was used and recheck its definition; perhaps -it doesn't need the lifetime parameter. Example: - -``` -type X = u32; // ok! -``` -"##, - E0133: r##" Unsafe code was used outside of an unsafe function or block. @@ -627,41 +589,6 @@ attributes: See also https://doc.rust-lang.org/book/no-stdlib.html "##, -E0229: r##" -An associated type binding was done outside of the type parameter declaration -and `where` clause. Erroneous code example: - -```compile_fail,E0229 -pub trait Foo { - type A; - fn boo(&self) -> ::A; -} - -struct Bar; - -impl Foo for isize { - type A = usize; - fn boo(&self) -> usize { 42 } -} - -fn baz(x: &>::A) {} -// error: associated type bindings are not allowed here -``` - -To solve this error, please move the type bindings in the type parameter -declaration: - -```ignore -fn baz>(x: &::A) {} // ok! -``` - -Or in the `where` clause: - -```ignore -fn baz(x: &::A) where I: Foo {} -``` -"##, - E0261: r##" When using a lifetime like `'a` in a type, it must be declared before being used. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 60d03ccfe240d..c4fccdcb9eb62 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -76,7 +76,6 @@ pub mod infer; pub mod lint; pub mod middle { - pub mod astconv_util; pub mod expr_use_visitor; pub mod const_val; pub mod cstore; diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs deleted file mode 100644 index 3418034b069d6..0000000000000 --- a/src/librustc/middle/astconv_util.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * This module contains a simple utility routine - * used by both `typeck` and `const_eval`. - * Almost certainly this could (and should) be refactored out of existence. - */ - -use hir; -use hir::def::Def; -use ty::{Ty, TyCtxt}; - -use syntax_pos::Span; - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn prohibit_type_params(self, segments: &[hir::PathSegment]) { - for segment in segments { - for typ in segment.parameters.types() { - struct_span_err!(self.sess, typ.span, E0109, - "type parameters are not allowed on this type") - .span_label(typ.span, &format!("type parameter not allowed")) - .emit(); - break; - } - for lifetime in segment.parameters.lifetimes() { - struct_span_err!(self.sess, lifetime.span, E0110, - "lifetime parameters are not allowed on this type") - .span_label(lifetime.span, - &format!("lifetime parameter not allowed on this type")) - .emit(); - break; - } - for binding in segment.parameters.bindings() { - self.prohibit_projection(binding.span); - break; - } - } - } - - pub fn prohibit_projection(self, span: Span) - { - let mut err = struct_span_err!(self.sess, span, E0229, - "associated type bindings are not allowed here"); - err.span_label(span, &format!("associate type not allowed here")).emit(); - } - - pub fn prim_ty_to_ty(self, - segments: &[hir::PathSegment], - nty: hir::PrimTy) - -> Ty<'tcx> { - self.prohibit_type_params(segments); - match nty { - hir::TyBool => self.types.bool, - hir::TyChar => self.types.char, - hir::TyInt(it) => self.mk_mach_int(it), - hir::TyUint(uit) => self.mk_mach_uint(uit), - hir::TyFloat(ft) => self.mk_mach_float(ft), - hir::TyStr => self.mk_str() - } - } - - /// If a type in the AST is a primitive type, return the ty::Ty corresponding - /// to it. - pub fn ast_ty_to_prim_ty(self, ast_ty: &hir::Ty) -> Option> { - if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = ast_ty.node { - if let Def::PrimTy(nty) = path.def { - Some(self.prim_ty_to_ty(&path.segments, nty)) - } else { - None - } - } else { - None - } - } -} diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 11919db479c1a..d81f89827d938 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -12,28 +12,30 @@ use syntax::symbol::InternedString; use syntax::ast; use std::rc::Rc; use hir::def_id::DefId; +use ty::subst::Substs; use rustc_const_math::*; + use self::ConstVal::*; pub use rustc_const_math::ConstInt; use std::collections::BTreeMap; #[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)] -pub enum ConstVal { +pub enum ConstVal<'tcx> { Float(ConstFloat), Integral(ConstInt), Str(InternedString), ByteStr(Rc>), Bool(bool), - Function(DefId), - Struct(BTreeMap), - Tuple(Vec), - Array(Vec), - Repeat(Box, u64), + Function(DefId, &'tcx Substs<'tcx>), + Struct(BTreeMap>), + Tuple(Vec>), + Array(Vec>), + Repeat(Box>, u64), Char(char), } -impl ConstVal { +impl<'tcx> ConstVal<'tcx> { pub fn description(&self) -> &'static str { match *self { Float(f) => f.description(), @@ -43,7 +45,7 @@ impl ConstVal { Bool(_) => "boolean", Struct(_) => "struct", Tuple(_) => "tuple", - Function(_) => "function definition", + Function(..) => "function definition", Array(..) => "array", Repeat(..) => "repeat", Char(..) => "char", @@ -53,8 +55,7 @@ impl ConstVal { pub fn to_const_int(&self) -> Option { match *self { ConstVal::Integral(i) => Some(i), - ConstVal::Bool(true) => Some(ConstInt::Infer(1)), - ConstVal::Bool(false) => Some(ConstInt::Infer(0)), + ConstVal::Bool(b) => Some(ConstInt::U8(b as u8)), ConstVal::Char(ch) => Some(ConstInt::U32(ch as u32)), _ => None } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d2a657e35b54a..40ebc97a78a6c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -542,7 +542,7 @@ impl<'tcx> Terminator<'tcx> { impl<'tcx> TerminatorKind<'tcx> { pub fn if_<'a, 'gcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> { - static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::Infer(0)]; + static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::U8(0)]; TerminatorKind::SwitchInt { discr: cond, switch_ty: tcx.types.bool, @@ -1224,7 +1224,7 @@ pub enum Literal<'tcx> { substs: &'tcx Substs<'tcx>, }, Value { - value: ConstVal, + value: ConstVal<'tcx>, }, Promoted { // Index into the `promoted` vector of `Mir`. @@ -1271,7 +1271,7 @@ fn fmt_const_val(fmt: &mut W, const_val: &ConstVal) -> fmt::Result { write!(fmt, "b\"{}\"", escaped) } Bool(b) => write!(fmt, "{:?}", b), - Function(def_id) => write!(fmt, "{}", item_path_str(def_id)), + Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)), Struct(_) | Tuple(_) | Array(_) | Repeat(..) => bug!("ConstVal `{:?}` should not be in MIR", const_val), Char(c) => write!(fmt, "{:?}", c), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 318c866a59fbe..6961e0da362a5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -244,6 +244,10 @@ pub struct TypeckTables<'tcx> { /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. pub used_trait_imports: DefIdSet, + + /// If any errors occurred while type-checking this body, + /// this field will be set to `true`. + pub tainted_by_errors: bool, } impl<'tcx> TypeckTables<'tcx> { @@ -262,6 +266,7 @@ impl<'tcx> TypeckTables<'tcx> { cast_kinds: NodeMap(), lints: lint::LintTable::new(), used_trait_imports: DefIdSet(), + tainted_by_errors: false, } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 3773796e47d47..e7895ca799012 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -20,7 +20,6 @@ use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; -use rustc_const_math::ConstInt; use std::cmp; use std::fmt; @@ -1183,11 +1182,7 @@ impl<'a, 'gcx, 'tcx> Layout { i64::min_value(), true); for discr in def.discriminants(tcx) { - let x = match discr.erase_type() { - ConstInt::InferSigned(i) => i as i64, - ConstInt::Infer(i) => i as u64 as i64, - _ => bug!() - }; + let x = discr.to_u128_unchecked() as i64; if x == 0 { non_zero = false; } if x < min { min = x; } if x > max { max = x; } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 358d69ff8dba9..b79ab2a26fdc9 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -381,7 +381,7 @@ define_maps! { <'tcx> /// Results of evaluating monomorphic constants embedded in /// other items, such as enum variant explicit discriminants. - pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result + pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result, ()> } fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 64480e510229e..49c25d25c604f 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -47,6 +47,35 @@ type Disr = ConstInt; } +macro_rules! typed_literal { + ($tcx:expr, $ty:expr, $lit:expr) => { + match $ty { + SignedInt(ast::IntTy::I8) => ConstInt::I8($lit), + SignedInt(ast::IntTy::I16) => ConstInt::I16($lit), + SignedInt(ast::IntTy::I32) => ConstInt::I32($lit), + SignedInt(ast::IntTy::I64) => ConstInt::I64($lit), + SignedInt(ast::IntTy::I128) => ConstInt::I128($lit), + SignedInt(ast::IntTy::Is) => match $tcx.sess.target.int_type { + ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16($lit)), + ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32($lit)), + ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64($lit)), + _ => bug!(), + }, + UnsignedInt(ast::UintTy::U8) => ConstInt::U8($lit), + UnsignedInt(ast::UintTy::U16) => ConstInt::U16($lit), + UnsignedInt(ast::UintTy::U32) => ConstInt::U32($lit), + UnsignedInt(ast::UintTy::U64) => ConstInt::U64($lit), + UnsignedInt(ast::UintTy::U128) => ConstInt::U128($lit), + UnsignedInt(ast::UintTy::Us) => match $tcx.sess.target.uint_type { + ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16($lit)), + ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32($lit)), + ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64($lit)), + _ => bug!(), + }, + } + } +} + impl IntTypeExt for attr::IntType { fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match *self { @@ -66,30 +95,7 @@ impl IntTypeExt for attr::IntType { } fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr { - match *self { - SignedInt(ast::IntTy::I8) => ConstInt::I8(0), - SignedInt(ast::IntTy::I16) => ConstInt::I16(0), - SignedInt(ast::IntTy::I32) => ConstInt::I32(0), - SignedInt(ast::IntTy::I64) => ConstInt::I64(0), - SignedInt(ast::IntTy::I128) => ConstInt::I128(0), - SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type { - ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)), - ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)), - ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)), - _ => bug!(), - }, - UnsignedInt(ast::UintTy::U8) => ConstInt::U8(0), - UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0), - UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0), - UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0), - UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0), - UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type { - ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)), - ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)), - ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)), - _ => bug!(), - }, - } + typed_literal!(tcx, *self, 0) } fn assert_ty_matches(&self, val: Disr) { @@ -114,7 +120,7 @@ impl IntTypeExt for attr::IntType { -> Option { if let Some(val) = val { self.assert_ty_matches(val); - (val + ConstInt::Infer(1)).ok() + (val + typed_literal!(tcx, *self, 1)).ok() } else { Some(self.initial_discriminant(tcx)) } diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 5a9f885719c8f..53a7e87292818 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -221,21 +221,21 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } #[derive(Clone, Debug, PartialEq)] -pub enum Constructor { +pub enum Constructor<'tcx> { /// The constructor of all patterns that don't vary by constructor, /// e.g. struct patterns and fixed-length arrays. Single, /// Enum variants. Variant(DefId), /// Literal values. - ConstantValue(ConstVal), + ConstantValue(ConstVal<'tcx>), /// Ranges of literal values (`2...5` and `2..5`). - ConstantRange(ConstVal, ConstVal, RangeEnd), + ConstantRange(ConstVal<'tcx>, ConstVal<'tcx>, RangeEnd), /// Array patterns of length n. Slice(usize), } -impl<'tcx> Constructor { +impl<'tcx> Constructor<'tcx> { fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize { match self { &Variant(vid) => adt.variant_index_with_id(vid), @@ -289,7 +289,7 @@ impl<'tcx> Witness<'tcx> { fn push_wild_constructor<'a>( mut self, cx: &MatchCheckCtxt<'a, 'tcx>, - ctor: &Constructor, + ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> Self { @@ -321,7 +321,7 @@ impl<'tcx> Witness<'tcx> { fn apply_constructor<'a>( mut self, cx: &MatchCheckCtxt<'a,'tcx>, - ctor: &Constructor, + ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> Self { @@ -399,7 +399,8 @@ impl<'tcx> Witness<'tcx> { /// We make sure to omit constructors that are statically impossible. eg for /// Option we do not include Some(_) in the returned list of constructors. fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, - pcx: PatternContext<'tcx>) -> Vec + pcx: PatternContext<'tcx>) + -> Vec> { debug!("all_constructors({:?})", pcx.ty); match pcx.ty.sty { @@ -664,7 +665,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( cx: &mut MatchCheckCtxt<'a, 'tcx>, &Matrix(ref m): &Matrix<'p, 'tcx>, v: &[&'p Pattern<'tcx>], - ctor: Constructor, + ctor: Constructor<'tcx>, lty: Ty<'tcx>, witness: WitnessPreference) -> Usefulness<'tcx> { @@ -702,10 +703,10 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( /// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on. /// /// Returns None in case of a catch-all, which can't be specialized. -fn pat_constructors(_cx: &mut MatchCheckCtxt, - pat: &Pattern, - pcx: PatternContext) - -> Option> +fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt, + pat: &Pattern<'tcx>, + pcx: PatternContext) + -> Option>> { match *pat.kind { PatternKind::Binding { .. } | PatternKind::Wild => diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index db5df72267df7..e2b9f174ff0c2 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { "statics cannot be referenced in patterns"); } PatternError::ConstEval(err) => { - report_const_eval_err(self.tcx, &err, pat_span, "pattern").emit(); + report_const_eval_err(self.tcx, &err, pat_span, "pattern"); } } } diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 8c8b2b5da36dc..9937cbbf8e10c 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -576,22 +576,6 @@ integer type: https://doc.rust-lang.org/reference.html#ffi-attributes "##, - -E0306: r##" -In an array type `[T; N]`, `N` is the number of elements in the array. This -must be an unsigned integer. Erroneous code example: - -```compile_fail,E0306 -const X: [i32; true] = [0]; // error: expected `usize` for array length, - // found boolean -``` - -Working example: - -``` -const X: [i32; 1] = [0]; -``` -"##, } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 0ab2255aab0ff..284991a11b1b9 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -11,7 +11,6 @@ use rustc::middle::const_val::ConstVal::*; use rustc::middle::const_val::ConstVal; use self::ErrKind::*; -use self::EvalHint::*; use rustc::hir::map as hir_map; use rustc::hir::map::blocks::FnLikeNode; @@ -20,7 +19,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Substs, Subst}; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; use rustc::util::nodemap::DefIdMap; @@ -28,7 +27,6 @@ use rustc::util::nodemap::DefIdMap; use graphviz::IntoCow; use syntax::ast; use rustc::hir::{self, Expr}; -use syntax::attr::IntType; use syntax_pos::Span; use std::borrow::Cow; @@ -37,18 +35,24 @@ use std::cmp::Ordering; use rustc_const_math::*; use rustc_errors::DiagnosticBuilder; +macro_rules! signal { + ($e:expr, $exn:expr) => { + return Err(ConstEvalErr { span: $e.span, kind: $exn }) + } +} + macro_rules! math { ($e:expr, $op:expr) => { match $op { Ok(val) => val, - Err(e) => signal!($e, Math(e)), + Err(e) => signal!($e, ErrKind::from(e)), } } } fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) - -> Option<(&'tcx Expr, Option<&'a ty::TypeckTables<'tcx>>)> { + -> Option<(&'tcx Expr, &'a ty::TypeckTables<'tcx>)> { if let Some(variant_node_id) = tcx.hir.as_local_node_id(variant_def) { let enum_node_id = tcx.hir.get_parent(variant_node_id); if let Some(hir_map::NodeItem(it)) = tcx.hir.find(enum_node_id) { @@ -58,7 +62,7 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return variant.node.disr_expr.map(|e| { let def_id = tcx.hir.body_owner_def_id(e); (&tcx.hir.body(e).value, - tcx.maps.typeck_tables.borrow().get(&def_id).cloned()) + tcx.item_tables(def_id)) }); } } @@ -75,55 +79,41 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// This generally happens in late/trans const evaluation. pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>) + substs: &'tcx Substs<'tcx>) -> Option<(&'tcx Expr, - Option<&'a ty::TypeckTables<'tcx>>, - Option>)> { + &'a ty::TypeckTables<'tcx>)> { if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { match tcx.hir.find(node_id) { None => None, Some(hir_map::NodeItem(&hir::Item { - node: hir::ItemConst(ref ty, body), .. + node: hir::ItemConst(_, body), .. })) | Some(hir_map::NodeImplItem(&hir::ImplItem { - node: hir::ImplItemKind::Const(ref ty, body), .. + node: hir::ImplItemKind::Const(_, body), .. })) => { Some((&tcx.hir.body(body).value, - tcx.maps.typeck_tables.borrow().get(&def_id).cloned(), - tcx.ast_ty_to_prim_ty(ty))) + tcx.item_tables(def_id))) } Some(hir_map::NodeTraitItem(ti)) => match ti.node { - hir::TraitItemKind::Const(ref ty, default) => { - if let Some(substs) = substs { - // If we have a trait item and the substitutions for it, - // `resolve_trait_associated_const` will select an impl - // or the default. - let trait_id = tcx.hir.get_parent(node_id); - let trait_id = tcx.hir.local_def_id(trait_id); - let default_value = default.map(|body| { - (&tcx.hir.body(body).value, - tcx.maps.typeck_tables.borrow().get(&def_id).cloned(), - tcx.ast_ty_to_prim_ty(ty)) - }); - resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) - } else { - // Technically, without knowing anything about the - // expression that generates the obligation, we could - // still return the default if there is one. However, - // it's safer to return `None` than to return some value - // that may differ from what you would get from - // correctly selecting an impl. - None - } + hir::TraitItemKind::Const(_, default) => { + // If we have a trait item and the substitutions for it, + // `resolve_trait_associated_const` will select an impl + // or the default. + let trait_id = tcx.hir.get_parent(node_id); + let trait_id = tcx.hir.local_def_id(trait_id); + let default_value = default.map(|body| { + (&tcx.hir.body(body).value, + tcx.item_tables(def_id)) + }); + resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) } _ => None }, Some(_) => None } } else { - let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (&body.value, Some(tcx.item_tables(def_id)), - Some(tcx.item_type(def_id))) + let expr_and_tables = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (&body.value, tcx.item_tables(def_id)) }); match tcx.sess.cstore.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { @@ -133,30 +123,26 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // trait-associated const if the caller gives us the // substitutions for the reference to it. if let Some(trait_id) = trait_id { - if let Some(substs) = substs { - resolve_trait_associated_const(tcx, def_id, expr_tables_ty, - trait_id, substs) - } else { - None - } + resolve_trait_associated_const(tcx, def_id, expr_and_tables, + trait_id, substs) } else { - expr_tables_ty + expr_and_tables } }, - Some(Def::Const(..)) => expr_tables_ty, + Some(Def::Const(..)) => expr_and_tables, _ => None } } } fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option<(&'tcx hir::Body, Option<&'a ty::TypeckTables<'tcx>>)> + -> Option<(&'tcx hir::Body, &'a ty::TypeckTables<'tcx>)> { if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { FnLikeNode::from_node(tcx.hir.get(node_id)).and_then(|fn_like| { if fn_like.constness() == hir::Constness::Const { Some((tcx.hir.body(fn_like.body()), - tcx.maps.typeck_tables.borrow().get(&def_id).cloned())) + tcx.item_tables(def_id))) } else { None } @@ -164,7 +150,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } else { if tcx.sess.cstore.is_const_fn(def_id) { tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (body, Some(tcx.item_tables(def_id))) + (body, tcx.item_tables(def_id)) }) } else { None @@ -172,7 +158,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } } -pub fn report_const_eval_err<'a, 'tcx>( +fn build_const_eval_err<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, err: &ConstEvalErr, primary_span: Span, @@ -189,6 +175,18 @@ pub fn report_const_eval_err<'a, 'tcx>( diag } +pub fn report_const_eval_err<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + err: &ConstEvalErr, + primary_span: Span, + primary_kind: &str) +{ + if let TypeckError = err.kind { + return; + } + build_const_eval_err(tcx, err, primary_span, primary_kind).emit(); +} + pub fn fatal_const_eval_err<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, err: &ConstEvalErr, @@ -196,7 +194,7 @@ pub fn fatal_const_eval_err<'a, 'tcx>( primary_kind: &str) -> ! { - report_const_eval_err(tcx, err, primary_span, primary_kind).emit(); + report_const_eval_err(tcx, err, primary_span, primary_kind); tcx.sess.abort_if_errors(); unreachable!() } @@ -222,69 +220,57 @@ pub fn note_const_eval_err<'a, 'tcx>( pub struct ConstContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - tables: Option<&'a ty::TypeckTables<'tcx>>, - fn_args: Option> + tables: &'a ty::TypeckTables<'tcx>, + substs: &'tcx Substs<'tcx>, + fn_args: Option>> } impl<'a, 'tcx> ConstContext<'a, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { let def_id = tcx.hir.body_owner_def_id(body); - ConstContext { - tcx: tcx, - tables: tcx.maps.typeck_tables.borrow().get(&def_id).cloned(), - fn_args: None - } + ConstContext::with_tables(tcx, tcx.item_tables(def_id)) } pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::TypeckTables<'tcx>) -> Self { ConstContext { tcx: tcx, - tables: Some(tables), + tables: tables, + substs: tcx.intern_substs(&[]), fn_args: None } } /// Evaluate a constant expression in a context where the expression isn't - /// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, - /// but a few places need to evaluate constants during type-checking, like - /// computing the length of an array. (See also the FIXME above EvalHint.) - pub fn eval(&self, e: &Expr, ty_hint: EvalHint<'tcx>) -> EvalResult { - eval_const_expr_partial(self, e, ty_hint) + /// guaranteed to be evaluatable. + pub fn eval(&self, e: &Expr) -> EvalResult<'tcx> { + if self.tables.tainted_by_errors { + signal!(e, TypeckError); + } + eval_const_expr_partial(self, e) } } #[derive(Clone, Debug)] -pub struct ConstEvalErr { +pub struct ConstEvalErr<'tcx> { pub span: Span, - pub kind: ErrKind, + pub kind: ErrKind<'tcx>, } #[derive(Clone, Debug)] -pub enum ErrKind { +pub enum ErrKind<'tcx> { CannotCast, - CannotCastTo(&'static str), - InvalidOpForInts(hir::BinOp_), - InvalidOpForBools(hir::BinOp_), - InvalidOpForFloats(hir::BinOp_), - InvalidOpForIntUint(hir::BinOp_), - InvalidOpForUintInt(hir::BinOp_), - NegateOn(ConstVal), - NotOn(ConstVal), - CallOn(ConstVal), - MissingStructField, + NegateOn(ConstVal<'tcx>), + NotOn(ConstVal<'tcx>), + CallOn(ConstVal<'tcx>), + NonConstPath, UnimplementedConstVal(&'static str), - UnresolvedPath, ExpectedConstTuple, ExpectedConstStruct, - TupleIndexOutOfBounds, IndexedNonVec, - IndexNegative, - IndexNotInt, + IndexNotUsize, IndexOutOfBounds { len: u64, index: u64 }, - RepeatCountNotNatural, - RepeatCountNotInt, MiscBinaryOp, MiscCatchAll, @@ -292,18 +278,17 @@ pub enum ErrKind { IndexOpFeatureGated, Math(ConstMathErr), - IntermediateUnsignedNegative, - /// Expected, Got - TypeMismatch(String, ConstInt), + ErroneousReferencedConstant(Box>), - BadType(ConstVal), - ErroneousReferencedConstant(Box), - CharCast(ConstInt), + TypeckError } -impl From for ErrKind { - fn from(err: ConstMathErr) -> ErrKind { - Math(err) +impl<'tcx> From for ErrKind<'tcx> { + fn from(err: ConstMathErr) -> ErrKind<'tcx> { + match err { + ConstMathErr::UnsignedNegation => TypeckError, + _ => Math(err) + } } } @@ -321,7 +306,7 @@ impl<'a> ConstEvalErrDescription<'a> { } } -impl ConstEvalErr { +impl<'tcx> ConstEvalErr<'tcx> { pub fn description(&self) -> ConstEvalErrDescription { use self::ErrKind::*; use self::ConstEvalErrDescription::*; @@ -335,12 +320,6 @@ impl ConstEvalErr { match self.kind { CannotCast => simple!("can't cast this type"), - CannotCastTo(s) => simple!("can't cast this type to {}", s), - InvalidOpForInts(_) => simple!("can't do this op on integrals"), - InvalidOpForBools(_) => simple!("can't do this op on bools"), - InvalidOpForFloats(_) => simple!("can't do this op on floats"), - InvalidOpForIntUint(..) => simple!("can't do this op on an isize and usize"), - InvalidOpForUintInt(..) => simple!("can't do this op on a usize and isize"), NegateOn(ref const_val) => simple!("negate on {}", const_val.description()), NotOn(ref const_val) => simple!("not on {}", const_val.description()), CallOn(ref const_val) => simple!("call on {}", const_val.description()), @@ -349,111 +328,42 @@ impl ConstEvalErr { NonConstPath => simple!("non-constant path in constant expression"), UnimplementedConstVal(what) => simple!("unimplemented constant expression: {}", what), - UnresolvedPath => simple!("unresolved path in constant expression"), ExpectedConstTuple => simple!("expected constant tuple"), ExpectedConstStruct => simple!("expected constant struct"), - TupleIndexOutOfBounds => simple!("tuple index out of bounds"), IndexedNonVec => simple!("indexing is only supported for arrays"), - IndexNegative => simple!("indices must be non-negative integers"), - IndexNotInt => simple!("indices must be integers"), + IndexNotUsize => simple!("indices must be of type `usize`"), IndexOutOfBounds { len, index } => { simple!("index out of bounds: the len is {} but the index is {}", len, index) } - RepeatCountNotNatural => simple!("repeat count must be a natural number"), - RepeatCountNotInt => simple!("repeat count must be integers"), MiscBinaryOp => simple!("bad operands for binary"), MiscCatchAll => simple!("unsupported constant expr"), IndexOpFeatureGated => simple!("the index operation on const values is unstable"), Math(ref err) => Simple(err.description().into_cow()), - IntermediateUnsignedNegative => simple!( - "during the computation of an unsigned a negative \ - number was encountered. This is most likely a bug in\ - the constant evaluator"), - - TypeMismatch(ref expected, ref got) => { - simple!("expected {}, found {}", expected, got.description()) - }, - BadType(ref i) => simple!("value of wrong type: {:?}", i), ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"), - CharCast(ref got) => { - simple!("only `u8` can be cast as `char`, not `{}`", got.description()) - }, - } - } -} - -pub type EvalResult = Result; -pub type CastResult = Result; - -// FIXME: Long-term, this enum should go away: trying to evaluate -// an expression which hasn't been type-checked is a recipe for -// disaster. That said, it's not clear how to fix ast_ty_to_ty -// to avoid the ordering issue. - -/// Hint to determine how to evaluate constant expressions which -/// might not be type-checked. -#[derive(Copy, Clone, Debug)] -pub enum EvalHint<'tcx> { - /// We have a type-checked expression. - ExprTypeChecked, - /// We have an expression which hasn't been type-checked, but we have - /// an idea of what the type will be because of the context. For example, - /// the length of an array is always `usize`. (This is referred to as - /// a hint because it isn't guaranteed to be consistent with what - /// type-checking would compute.) - UncheckedExprHint(Ty<'tcx>), - /// We have an expression which has not yet been type-checked, and - /// and we have no clue what the type will be. - UncheckedExprNoHint, -} -impl<'tcx> EvalHint<'tcx> { - fn erase_hint(&self) -> EvalHint<'tcx> { - match *self { - ExprTypeChecked => ExprTypeChecked, - UncheckedExprHint(_) | UncheckedExprNoHint => UncheckedExprNoHint, - } - } - fn checked_or(&self, ty: Ty<'tcx>) -> EvalHint<'tcx> { - match *self { - ExprTypeChecked => ExprTypeChecked, - _ => UncheckedExprHint(ty), + TypeckError => simple!("type-checking failed"), } } } -macro_rules! signal { - ($e:expr, $exn:expr) => { - return Err(ConstEvalErr { span: $e.span, kind: $exn }) - } -} +pub type EvalResult<'tcx> = Result, ConstEvalErr<'tcx>>; +pub type CastResult<'tcx> = Result, ErrKind<'tcx>>; fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, - e: &Expr, - ty_hint: EvalHint<'tcx>) -> EvalResult { + e: &Expr) -> EvalResult<'tcx> { let tcx = cx.tcx; - // Try to compute the type of the expression based on the EvalHint. - // (See also the definition of EvalHint, and the FIXME above EvalHint.) - let ety = match ty_hint { - ExprTypeChecked => { - // After type-checking, expr_ty is guaranteed to succeed. - cx.tables.map(|tables| tables.expr_ty(e)) - } - UncheckedExprHint(ty) => { - // Use the type hint; it's not guaranteed to be right, but it's - // usually good enough. - Some(ty) - } - UncheckedExprNoHint => { - // This expression might not be type-checked, and we have no hint. - // Try to query the context for a type anyway; we might get lucky - // (for example, if the expression was imported from another crate). - cx.tables.and_then(|tables| tables.expr_ty_opt(e)) - } + let ety = cx.tables.expr_ty(e); + + // Avoid applying substitutions if they're empty, that'd ICE. + let ety = if cx.substs.is_empty() { + ety + } else { + ety.subst(tcx, cx.substs) }; + let result = match e.node { hir::ExprUnary(hir::UnNeg, ref inner) => { // unary neg literals already got their sign during creation @@ -465,28 +375,28 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128; const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128; const I128_OVERFLOW: u128 = i128::min_value() as u128; - match (&lit.node, ety.map(|t| &t.sty)) { - (&LitKind::Int(I8_OVERFLOW, _), Some(&ty::TyInt(IntTy::I8))) | + match (&lit.node, &ety.sty) { + (&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) | (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => { return Ok(Integral(I8(i8::min_value()))) }, - (&LitKind::Int(I16_OVERFLOW, _), Some(&ty::TyInt(IntTy::I16))) | + (&LitKind::Int(I16_OVERFLOW, _), &ty::TyInt(IntTy::I16)) | (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => { return Ok(Integral(I16(i16::min_value()))) }, - (&LitKind::Int(I32_OVERFLOW, _), Some(&ty::TyInt(IntTy::I32))) | + (&LitKind::Int(I32_OVERFLOW, _), &ty::TyInt(IntTy::I32)) | (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => { return Ok(Integral(I32(i32::min_value()))) }, - (&LitKind::Int(I64_OVERFLOW, _), Some(&ty::TyInt(IntTy::I64))) | + (&LitKind::Int(I64_OVERFLOW, _), &ty::TyInt(IntTy::I64)) | (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { return Ok(Integral(I64(i64::min_value()))) }, - (&LitKind::Int(I128_OVERFLOW, _), Some(&ty::TyInt(IntTy::I128))) | + (&LitKind::Int(I128_OVERFLOW, _), &ty::TyInt(IntTy::I128)) | (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => { return Ok(Integral(I128(i128::min_value()))) }, - (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::Is))) | + (&LitKind::Int(n, _), &ty::TyInt(IntTy::Is)) | (&LitKind::Int(n, Signed(IntTy::Is)), _) => { match tcx.sess.target.int_type { IntTy::I16 => if n == I16_OVERFLOW { @@ -498,20 +408,20 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, IntTy::I64 => if n == I64_OVERFLOW { return Ok(Integral(Isize(Is64(i64::min_value())))); }, - _ => bug!(), + _ => span_bug!(e.span, "typeck error") } }, _ => {}, } } - match cx.eval(inner, ty_hint)? { + match cx.eval(inner)? { Float(f) => Float(-f), Integral(i) => Integral(math!(e, -i)), const_val => signal!(e, NegateOn(const_val)), } } hir::ExprUnary(hir::UnNot, ref inner) => { - match cx.eval(inner, ty_hint)? { + match cx.eval(inner)? { Integral(i) => Integral(math!(e, !i)), Bool(b) => Bool(!b), const_val => signal!(e, NotOn(const_val)), @@ -519,16 +429,11 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")), hir::ExprBinary(op, ref a, ref b) => { - let b_ty = match op.node { - hir::BiShl | hir::BiShr => ty_hint.erase_hint(), - _ => ty_hint - }; // technically, if we don't have type hints, but integral eval // gives us a type through a type-suffix, cast or const def type // we need to re-eval the other value of the BinOp if it was // not inferred - match (cx.eval(a, ty_hint)?, - cx.eval(b, b_ty)?) { + match (cx.eval(a)?, cx.eval(b)?) { (Float(a), Float(b)) => { use std::cmp::Ordering::*; match op.node { @@ -543,7 +448,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, hir::BiNe => Bool(math!(e, a.try_cmp(b)) != Equal), hir::BiGe => Bool(math!(e, a.try_cmp(b)) != Less), hir::BiGt => Bool(math!(e, a.try_cmp(b)) == Greater), - _ => signal!(e, InvalidOpForFloats(op.node)), + _ => span_bug!(e.span, "typeck error"), } } (Integral(a), Integral(b)) => { @@ -565,7 +470,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, hir::BiNe => Bool(math!(e, a.try_cmp(b)) != Equal), hir::BiGe => Bool(math!(e, a.try_cmp(b)) != Less), hir::BiGt => Bool(math!(e, a.try_cmp(b)) == Greater), - _ => signal!(e, InvalidOpForInts(op.node)), + _ => span_bug!(e.span, "typeck error"), } } (Bool(a), Bool(b)) => { @@ -581,90 +486,57 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, hir::BiLe => a <= b, hir::BiGe => a >= b, hir::BiGt => a > b, - _ => signal!(e, InvalidOpForBools(op.node)), + _ => span_bug!(e.span, "typeck error"), }) } _ => signal!(e, MiscBinaryOp), } } - hir::ExprCast(ref base, ref target_ty) => { - let ety = tcx.ast_ty_to_prim_ty(&target_ty).or(ety) - .unwrap_or_else(|| { - tcx.sess.span_fatal(target_ty.span, - "target type not found for const cast") - }); - - let base_hint = if let ExprTypeChecked = ty_hint { - ExprTypeChecked - } else { - match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) { - Some(t) => UncheckedExprHint(t), - None => ty_hint - } - }; - - let val = match cx.eval(base, base_hint) { - Ok(val) => val, - Err(ConstEvalErr { kind: ErroneousReferencedConstant( - box ConstEvalErr { kind: TypeMismatch(_, val), .. }), .. }) | - Err(ConstEvalErr { kind: TypeMismatch(_, val), .. }) => { - // Something like `5i8 as usize` doesn't need a type hint for the base - // instead take the type hint from the inner value - let hint = match val.int_type() { - Some(IntType::UnsignedInt(ty)) => ty_hint.checked_or(tcx.mk_mach_uint(ty)), - Some(IntType::SignedInt(ty)) => ty_hint.checked_or(tcx.mk_mach_int(ty)), - // we had a type hint, so we can't have an unknown type - None => bug!(), - }; - cx.eval(base, hint)? - }, - Err(e) => return Err(e), - }; - match cast_const(tcx, val, ety) { + hir::ExprCast(ref base, _) => { + match cast_const(tcx, cx.eval(base)?, ety) { Ok(val) => val, Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }), } } hir::ExprPath(ref qpath) => { - let def = cx.tables.map(|tables| tables.qpath_def(qpath, e.id)).unwrap_or_else(|| { - // There are no tables so we can only handle already-resolved HIR. - match *qpath { - hir::QPath::Resolved(_, ref path) => path.def, - hir::QPath::TypeRelative(..) => Def::Err - } - }); - match def { + let substs = cx.tables.node_id_item_substs(e.id) + .unwrap_or_else(|| tcx.intern_substs(&[])); + + // Avoid applying substitutions if they're empty, that'd ICE. + let substs = if cx.substs.is_empty() { + substs + } else { + substs.subst(tcx, cx.substs) + }; + + match cx.tables.qpath_def(qpath, e.id) { Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let substs = if let ExprTypeChecked = ty_hint { - Some(cx.tables.and_then(|tables| tables.node_id_item_substs(e.id)) - .unwrap_or_else(|| tcx.intern_substs(&[]))) - } else { - None - }; - if let Some((expr, tables, ty)) = lookup_const_by_id(tcx, def_id, substs) { - let item_hint = match ty { - Some(ty) => ty_hint.checked_or(ty), - None => ty_hint, - }; - let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; - match cx.eval(expr, item_hint) { + if let Some((expr, tables)) = lookup_const_by_id(tcx, def_id, substs) { + let cx = ConstContext::with_tables(tcx, tables); + match cx.eval(expr) { Ok(val) => val, + Err(ConstEvalErr { kind: TypeckError, .. }) => { + signal!(e, TypeckError); + } Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); signal!(e, ErroneousReferencedConstant(box err)) }, } } else { - signal!(e, NonConstPath); + signal!(e, TypeckError); } }, Def::VariantCtor(variant_def, ..) => { if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) { - let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; - match cx.eval(expr, ty_hint) { + let cx = ConstContext::with_tables(tcx, tables); + match cx.eval(expr) { Ok(val) => val, + Err(ConstEvalErr { kind: TypeckError, .. }) => { + signal!(e, TypeckError); + } Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); signal!(e, ErroneousReferencedConstant(box err)) @@ -685,16 +557,14 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, signal!(e, NonConstPath); } }, - Def::Method(id) | Def::Fn(id) => Function(id), - Def::Err => signal!(e, UnresolvedPath), + Def::Method(id) | Def::Fn(id) => Function(id, substs), + Def::Err => span_bug!(e.span, "typeck error"), _ => signal!(e, NonConstPath), } } hir::ExprCall(ref callee, ref args) => { - let sub_ty_hint = ty_hint.erase_hint(); - let callee_val = cx.eval(callee, sub_ty_hint)?; - let did = match callee_val { - Function(did) => did, + let (did, substs) = match cx.eval(callee)? { + Function(did, substs) => (did, substs), Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")), callee => signal!(e, CallOn(callee)), }; @@ -711,8 +581,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, let mut call_args = DefIdMap(); for (arg, arg_expr) in arg_defs.into_iter().zip(args.iter()) { - let arg_hint = ty_hint.erase_hint(); - let arg_val = cx.eval(arg_expr, arg_hint)?; + let arg_val = cx.eval(arg_expr)?; debug!("const call arg: {:?}", arg); if let Some(def_id) = arg { assert!(call_args.insert(def_id, arg_val).is_none()); @@ -722,9 +591,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, let callee_cx = ConstContext { tcx: tcx, tables: tables, + substs: substs, fn_args: Some(call_args) }; - callee_cx.eval(&body.value, ty_hint)? + callee_cx.eval(&body.value)? }, hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) { Ok(val) => val, @@ -732,32 +602,27 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, }, hir::ExprBlock(ref block) => { match block.expr { - Some(ref expr) => cx.eval(expr, ty_hint)?, - None => signal!(e, UnimplementedConstVal("empty block")), + Some(ref expr) => cx.eval(expr)?, + None => Tuple(vec![]), } } - hir::ExprType(ref e, _) => cx.eval(e, ty_hint)?, + hir::ExprType(ref e, _) => cx.eval(e)?, hir::ExprTup(ref fields) => { - let field_hint = ty_hint.erase_hint(); - Tuple(fields.iter().map(|e| cx.eval(e, field_hint)).collect::>()?) + Tuple(fields.iter().map(|e| cx.eval(e)).collect::>()?) } hir::ExprStruct(_, ref fields, _) => { - let field_hint = ty_hint.erase_hint(); Struct(fields.iter().map(|f| { - cx.eval(&f.expr, field_hint).map(|v| (f.name.node, v)) + cx.eval(&f.expr).map(|v| (f.name.node, v)) }).collect::>()?) } hir::ExprIndex(ref arr, ref idx) => { if !tcx.sess.features.borrow().const_indexing { signal!(e, IndexOpFeatureGated); } - let arr_hint = ty_hint.erase_hint(); - let arr = cx.eval(arr, arr_hint)?; - let idx_hint = ty_hint.checked_or(tcx.types.usize); - let idx = match cx.eval(idx, idx_hint)? { + let arr = cx.eval(arr)?; + let idx = match cx.eval(idx)? { Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), - Integral(_) => bug!(), - _ => signal!(idx, IndexNotInt), + _ => signal!(idx, IndexNotUsize), }; assert_eq!(idx as usize as u64, idx); match arr { @@ -787,45 +652,25 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } } hir::ExprArray(ref v) => { - let elem_hint = ty_hint.erase_hint(); - Array(v.iter().map(|e| cx.eval(e, elem_hint)).collect::>()?) + Array(v.iter().map(|e| cx.eval(e)).collect::>()?) } - hir::ExprRepeat(ref elem, count) => { - let elem_hint = ty_hint.erase_hint(); - let len_hint = ty_hint.checked_or(tcx.types.usize); - let n = if let Some(ty) = ety { - // For cross-crate constants, we have the type already, - // but not the body for `count`, so use the type. - match ty.sty { - ty::TyArray(_, n) => n as u64, - _ => bug!() - } - } else { - let n = &tcx.hir.body(count).value; - match ConstContext::new(tcx, count).eval(n, len_hint)? { - Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), - Integral(_) => signal!(e, RepeatCountNotNatural), - _ => signal!(e, RepeatCountNotInt), - } + hir::ExprRepeat(ref elem, _) => { + let n = match ety.sty { + ty::TyArray(_, n) => n as u64, + _ => span_bug!(e.span, "typeck error") }; - Repeat(Box::new(cx.eval(elem, elem_hint)?), n) + Repeat(Box::new(cx.eval(elem)?), n) }, hir::ExprTupField(ref base, index) => { - let base_hint = ty_hint.erase_hint(); - let c = cx.eval(base, base_hint)?; + let c = cx.eval(base)?; if let Tuple(ref fields) = c { - if let Some(elem) = fields.get(index.node) { - elem.clone() - } else { - signal!(e, TupleIndexOutOfBounds); - } + fields[index.node].clone() } else { signal!(base, ExpectedConstTuple); } } hir::ExprField(ref base, field_name) => { - let base_hint = ty_hint.erase_hint(); - let c = cx.eval(base, base_hint)?; + let c = cx.eval(base)?; if let Struct(ref fields) = c { if let Some(f) = fields.get(&field_name.node) { f.clone() @@ -840,82 +685,16 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, _ => signal!(e, MiscCatchAll) }; - match (ety.map(|t| &t.sty), result) { - (Some(ref ty_hint), Integral(i)) => match infer(i, tcx, ty_hint) { - Ok(inferred) => Ok(Integral(inferred)), - Err(err) => signal!(e, err), - }, - (_, result) => Ok(result), - } -} - -fn infer<'a, 'tcx>(i: ConstInt, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty_hint: &ty::TypeVariants<'tcx>) - -> Result { - use syntax::ast::*; - - match (ty_hint, i) { - (&ty::TyInt(IntTy::I8), result @ I8(_)) => Ok(result), - (&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result), - (&ty::TyInt(IntTy::I32), result @ I32(_)) => Ok(result), - (&ty::TyInt(IntTy::I64), result @ I64(_)) => Ok(result), - (&ty::TyInt(IntTy::I128), result @ I128(_)) => Ok(result), - (&ty::TyInt(IntTy::Is), result @ Isize(_)) => Ok(result), - - (&ty::TyUint(UintTy::U8), result @ U8(_)) => Ok(result), - (&ty::TyUint(UintTy::U16), result @ U16(_)) => Ok(result), - (&ty::TyUint(UintTy::U32), result @ U32(_)) => Ok(result), - (&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result), - (&ty::TyUint(UintTy::U128), result @ U128(_)) => Ok(result), - (&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result), - - (&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i128 as i8)), - (&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i128 as i16)), - (&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i128 as i32)), - (&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i128 as i64)), - (&ty::TyInt(IntTy::I128), Infer(i)) => Ok(I128(i as i128)), - (&ty::TyInt(IntTy::Is), Infer(i)) => { - Ok(Isize(ConstIsize::new_truncating(i as i128, tcx.sess.target.int_type))) - }, - - (&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)), - (&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)), - (&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)), - (&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i as i64)), - (&ty::TyInt(IntTy::I128), InferSigned(i)) => Ok(I128(i)), - (&ty::TyInt(IntTy::Is), InferSigned(i)) => { - Ok(Isize(ConstIsize::new_truncating(i, tcx.sess.target.int_type))) - }, - - (&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)), - (&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)), - (&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)), - (&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i as u64)), - (&ty::TyUint(UintTy::U128), Infer(i)) => Ok(U128(i)), - (&ty::TyUint(UintTy::Us), Infer(i)) => { - Ok(Usize(ConstUsize::new_truncating(i, tcx.sess.target.uint_type))) - }, - (&ty::TyUint(_), InferSigned(_)) => Err(IntermediateUnsignedNegative), - - (&ty::TyInt(ity), i) => Err(TypeMismatch(ity.to_string(), i)), - (&ty::TyUint(ity), i) => Err(TypeMismatch(ity.to_string(), i)), - - (&ty::TyAdt(adt, _), i) if adt.is_enum() => { - let int_ty = adt.repr.discr_type(); - infer(i, tcx, &int_ty.to_ty(tcx).sty) - }, - (_, i) => Err(BadType(ConstVal::Integral(i))), - } + Ok(result) } fn resolve_trait_associated_const<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: DefId, - default_value: Option<(&'tcx Expr, Option<&'a ty::TypeckTables<'tcx>>, Option>)>, + default_value: Option<(&'tcx Expr, &'a ty::TypeckTables<'tcx>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, Option<&'a ty::TypeckTables<'tcx>>, Option>)> +) -> Option<(&'tcx Expr, &'a ty::TypeckTables<'tcx>)> { let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", @@ -950,7 +729,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>( let ac = tcx.associated_items(impl_data.impl_def_id) .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name); match ac { - Some(ic) => lookup_const_by_id(tcx, ic.def_id, None), + Some(ic) => lookup_const_by_id(tcx, ic.def_id, Substs::empty()), None => default_value, } } @@ -961,7 +740,10 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>( }) } -fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult { +fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + val: ConstInt, + ty: Ty<'tcx>) + -> CastResult<'tcx> { let v = val.to_u128_unchecked(); match ty.sty { ty::TyBool if v == 0 => Ok(Bool(false)), @@ -982,42 +764,31 @@ fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty:: ty::TyUint(ast::UintTy::Us) => { Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.uint_type)))) }, - ty::TyFloat(ast::FloatTy::F64) => match val.erase_type() { - Infer(u) => Ok(Float(F64(u as f64))), - InferSigned(i) => Ok(Float(F64(i as f64))), - _ => bug!("ConstInt::erase_type returned something other than Infer/InferSigned"), - }, - ty::TyFloat(ast::FloatTy::F32) => match val.erase_type() { - Infer(u) => Ok(Float(F32(u as f32))), - InferSigned(i) => Ok(Float(F32(i as f32))), - _ => bug!("ConstInt::erase_type returned something other than Infer/InferSigned"), - }, + ty::TyFloat(ast::FloatTy::F64) => Ok(Float(F64(val.to_f64()))), + ty::TyFloat(ast::FloatTy::F32) => Ok(Float(F32(val.to_f32()))), ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting an address to a raw ptr")), - ty::TyChar => match infer(val, tcx, &ty::TyUint(ast::UintTy::U8)) { - Ok(U8(u)) => Ok(Char(u as char)), - // can only occur before typeck, typeck blocks `T as char` for `T` != `u8` - _ => Err(CharCast(val)), + ty::TyChar => match val { + U8(u) => Ok(Char(u as char)), + _ => bug!(), }, - _ => Err(CannotCast), + _ => bug!(), } } fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstFloat, - ty: ty::Ty) -> CastResult { + ty: Ty<'tcx>) -> CastResult<'tcx> { match ty.sty { ty::TyInt(_) | ty::TyUint(_) => { let i = match val { - F32(f) if f >= 0.0 => Infer(f as u128), - FInfer { f64: f, .. } | - F64(f) if f >= 0.0 => Infer(f as u128), + F32(f) if f >= 0.0 => U128(f as u128), + F64(f) if f >= 0.0 => U128(f as u128), - F32(f) => InferSigned(f as i128), - FInfer { f64: f, .. } | - F64(f) => InferSigned(f as i128) + F32(f) => I128(f as i128), + F64(f) => I128(f as i128) }; - if let (InferSigned(_), &ty::TyUint(_)) = (i, &ty.sty) { + if let (I128(_), &ty::TyUint(_)) = (i, &ty.sty) { return Err(CannotCast); } @@ -1025,23 +796,26 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } ty::TyFloat(ast::FloatTy::F64) => Ok(Float(F64(match val { F32(f) => f as f64, - FInfer { f64: f, .. } | F64(f) => f + F64(f) => f }))), ty::TyFloat(ast::FloatTy::F32) => Ok(Float(F32(match val { F64(f) => f as f32, - FInfer { f32: f, .. } | F32(f) => f + F32(f) => f }))), _ => Err(CannotCast), } } -fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult { +fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + val: ConstVal<'tcx>, + ty: Ty<'tcx>) + -> CastResult<'tcx> { match val { Integral(i) => cast_const_int(tcx, i, ty), - Bool(b) => cast_const_int(tcx, Infer(b as u128), ty), + Bool(b) => cast_const_int(tcx, U8(b as u8), ty), Float(f) => cast_const_float(tcx, f, ty), - Char(c) => cast_const_int(tcx, Infer(c as u128), ty), - Function(_) => Err(UnimplementedConstVal("casting fn pointers")), + Char(c) => cast_const_int(tcx, U32(c as u32), ty), + Function(..) => Err(UnimplementedConstVal("casting fn pointers")), ByteStr(b) => match ty.sty { ty::TyRawPtr(_) => { Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr")) @@ -1069,66 +843,56 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty_hint: Option>) - -> Result { + mut ty: Ty<'tcx>) + -> Result, ErrKind<'tcx>> { use syntax::ast::*; use syntax::ast::LitIntType::*; + + if let ty::TyAdt(adt, _) = ty.sty { + if adt.is_enum() { + ty = adt.repr.discr_type().to_ty(tcx) + } + } + match *lit { LitKind::Str(ref s, _) => Ok(Str(s.as_str())), LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())), LitKind::Byte(n) => Ok(Integral(U8(n))), - LitKind::Int(n, Signed(ity)) => { - infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral) - }, - - // FIXME: this should become u128. - LitKind::Int(n, Unsuffixed) => { - match ty_hint.map(|t| &t.sty) { - Some(&ty::TyInt(ity)) => { - infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral) - }, - Some(&ty::TyUint(uty)) => { - infer(Infer(n as u128), tcx, &ty::TyUint(uty)).map(Integral) - }, - None => Ok(Integral(Infer(n as u128))), - Some(&ty::TyAdt(adt, _)) => { - let int_ty = adt.repr.discr_type(); - infer(Infer(n as u128), tcx, &int_ty.to_ty(tcx).sty).map(Integral) - }, - Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit), + LitKind::Int(n, hint) => { + match (&ty.sty, hint) { + (&ty::TyInt(ity), _) | + (_, Signed(ity)) => { + Ok(Integral(ConstInt::new_signed_truncating(n as i128, + ity, tcx.sess.target.int_type))) + } + (&ty::TyUint(uty), _) | + (_, Unsigned(uty)) => { + Ok(Integral(ConstInt::new_unsigned_truncating(n as u128, + uty, tcx.sess.target.uint_type))) + } + _ => bug!() } - }, - LitKind::Int(n, Unsigned(ity)) => { - infer(Infer(n as u128), tcx, &ty::TyUint(ity)).map(Integral) - }, - + } LitKind::Float(n, fty) => { - parse_float(&n.as_str(), Some(fty)).map(Float) + parse_float(&n.as_str(), fty).map(Float) } LitKind::FloatUnsuffixed(n) => { - let fty_hint = match ty_hint.map(|t| &t.sty) { - Some(&ty::TyFloat(fty)) => Some(fty), - _ => None + let fty = match ty.sty { + ty::TyFloat(fty) => fty, + _ => bug!() }; - parse_float(&n.as_str(), fty_hint).map(Float) + parse_float(&n.as_str(), fty).map(Float) } LitKind::Bool(b) => Ok(Bool(b)), LitKind::Char(c) => Ok(Char(c)), } } -fn parse_float(num: &str, fty_hint: Option) - -> Result { - let val = match fty_hint { - Some(ast::FloatTy::F32) => num.parse::().map(F32), - Some(ast::FloatTy::F64) => num.parse::().map(F64), - None => { - num.parse::().and_then(|f32| { - num.parse::().map(|f64| { - FInfer { f32: f32, f64: f64 } - }) - }) - } +fn parse_float<'tcx>(num: &str, fty: ast::FloatTy) + -> Result> { + let val = match fty { + ast::FloatTy::F32 => num.parse::().map(F32), + ast::FloatTy::F64 => num.parse::().map(F64) }; val.map_err(|_| { // FIXME(#31407) this is only necessary because float parsing is buggy @@ -1168,17 +932,17 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> { a: &Expr, b: &Expr) -> Result { let tcx = self.tcx; - let a = match self.eval(a, ExprTypeChecked) { + let a = match self.eval(a) { Ok(a) => a, Err(e) => { - report_const_eval_err(tcx, &e, a.span, "expression").emit(); + report_const_eval_err(tcx, &e, a.span, "expression"); return Err(ErrorReported); } }; - let b = match self.eval(b, ExprTypeChecked) { + let b = match self.eval(b) { Ok(b) => b, Err(e) => { - report_const_eval_err(tcx, &e, b.span, "expression").emit(); + report_const_eval_err(tcx, &e, b.span, "expression"); return Err(ErrorReported); } }; @@ -1193,26 +957,17 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reason: &str) -> Result { - let hint = UncheckedExprHint(tcx.types.usize); let count_expr = &tcx.hir.body(count).value; - match ConstContext::new(tcx, count).eval(count_expr, hint) { + match ConstContext::new(tcx, count).eval(count_expr) { Ok(Integral(Usize(count))) => { let val = count.as_u64(tcx.sess.target.uint_type); assert_eq!(val as usize as u64, val); Ok(val as usize) }, - Ok(const_val) => { - struct_span_err!(tcx.sess, count_expr.span, E0306, - "expected `usize` for {}, found {}", - reason, - const_val.description()) - .span_label(count_expr.span, &format!("expected `usize`")) - .emit(); - - Err(ErrorReported) - } + Ok(_) | + Err(ConstEvalErr { kind: TypeckError, .. }) => Err(ErrorReported), Err(err) => { - let mut diag = report_const_eval_err( + let mut diag = build_const_eval_err( tcx, &err, count_expr.span, reason); if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node { diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 198e49daabc63..4434a901f9412 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -21,6 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![deny(warnings)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 609fb3e39d62c..72a47c0028162 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -27,9 +27,9 @@ use syntax::ptr::P; use syntax_pos::Span; #[derive(Clone, Debug)] -pub enum PatternError { +pub enum PatternError<'tcx> { StaticInPattern(Span), - ConstEval(eval::ConstEvalErr), + ConstEval(eval::ConstEvalErr<'tcx>), } #[derive(Copy, Clone, Debug)] @@ -84,12 +84,12 @@ pub enum PatternKind<'tcx> { }, Constant { - value: ConstVal, + value: ConstVal<'tcx>, }, Range { - lo: ConstVal, - hi: ConstVal, + lo: ConstVal<'tcx>, + hi: ConstVal<'tcx>, end: RangeEnd, }, @@ -118,7 +118,7 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result { ConstVal::Char(c) => write!(f, "{:?}", c), ConstVal::Struct(_) | ConstVal::Tuple(_) | - ConstVal::Function(_) | + ConstVal::Function(..) | ConstVal::Array(..) | ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value) } @@ -265,7 +265,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub tables: &'a ty::TypeckTables<'gcx>, - pub errors: Vec, + pub errors: Vec>, } impl<'a, 'gcx, 'tcx> Pattern<'tcx> { @@ -582,11 +582,11 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { let tcx = self.tcx.global_tcx(); let substs = self.tables.node_id_item_substs(id) .unwrap_or_else(|| tcx.intern_substs(&[])); - match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { - Some((const_expr, const_tables, _const_ty)) => { + match eval::lookup_const_by_id(tcx, def_id, substs) { + Some((const_expr, const_tables)) => { // Enter the inlined constant's tables temporarily. let old_tables = self.tables; - self.tables = const_tables.expect("missing tables after typeck"); + self.tables = const_tables; let pat = self.lower_const_expr(const_expr, pat_id, span); self.tables = old_tables; return pat; @@ -609,7 +609,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> { let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables); - match const_cx.eval(expr, eval::EvalHint::ExprTypeChecked) { + match const_cx.eval(expr) { Ok(value) => { PatternKind::Constant { value: value } } @@ -796,7 +796,7 @@ macro_rules! CloneImpls { } CloneImpls!{ <'tcx> - Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal, Region, + Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal<'tcx>, Region, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef, &'tcx Substs<'tcx>, &'tcx Kind<'tcx> } diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs index 4610c183e1b1f..f557edffbda46 100644 --- a/src/librustc_const_math/float.rs +++ b/src/librustc_const_math/float.rs @@ -17,13 +17,7 @@ use super::err::*; #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] pub enum ConstFloat { F32(f32), - F64(f64), - - // When the type isn't known, we have to operate on both possibilities. - FInfer { - f32: f32, - f64: f64 - } + F64(f64) } pub use self::ConstFloat::*; @@ -31,7 +25,6 @@ impl ConstFloat { /// Description of the type, not the value pub fn description(&self) -> &'static str { match *self { - FInfer {..} => "float", F32(_) => "f32", F64(_) => "f64", } @@ -41,17 +34,13 @@ impl ConstFloat { match *self { F32(f) => f.is_nan(), F64(f) => f.is_nan(), - FInfer { f32, f64 } => f32.is_nan() || f64.is_nan() } } /// Compares the values if they are of the same type pub fn try_cmp(self, rhs: Self) -> Result { match (self, rhs) { - (F64(a), F64(b)) | - (F64(a), FInfer { f64: b, .. }) | - (FInfer { f64: a, .. }, F64(b)) | - (FInfer { f64: a, .. }, FInfer { f64: b, .. }) => { + (F64(a), F64(b)) => { // This is pretty bad but it is the existing behavior. Ok(if a == b { Ordering::Equal @@ -62,9 +51,7 @@ impl ConstFloat { }) } - (F32(a), F32(b)) | - (F32(a), FInfer { f32: b, .. }) | - (FInfer { f32: a, .. }, F32(b)) => { + (F32(a), F32(b)) => { Ok(if a == b { Ordering::Equal } else if a < b { @@ -86,10 +73,7 @@ impl ConstFloat { impl PartialEq for ConstFloat { fn eq(&self, other: &Self) -> bool { match (*self, *other) { - (F64(a), F64(b)) | - (F64(a), FInfer { f64: b, .. }) | - (FInfer { f64: a, .. }, F64(b)) | - (FInfer { f64: a, .. }, FInfer { f64: b, .. }) => { + (F64(a), F64(b)) => { unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)} } (F32(a), F32(b)) => { @@ -105,7 +89,7 @@ impl Eq for ConstFloat {} impl hash::Hash for ConstFloat { fn hash(&self, state: &mut H) { match *self { - F64(a) | FInfer { f64: a, .. } => { + F64(a) => { unsafe { transmute::<_,u64>(a) }.hash(state) } F32(a) => { @@ -118,7 +102,6 @@ impl hash::Hash for ConstFloat { impl ::std::fmt::Display for ConstFloat { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { match *self { - FInfer { f64, .. } => write!(fmt, "{}", f64), F32(f) => write!(fmt, "{}f32", f), F64(f) => write!(fmt, "{}f64", f), } @@ -131,20 +114,8 @@ macro_rules! derive_binop { type Output = Result; fn $func(self, rhs: Self) -> Result { match (self, rhs) { - (F32(a), F32(b)) | - (F32(a), FInfer { f32: b, .. }) | - (FInfer { f32: a, .. }, F32(b)) => Ok(F32(a.$func(b))), - - (F64(a), F64(b)) | - (FInfer { f64: a, .. }, F64(b)) | - (F64(a), FInfer { f64: b, .. }) => Ok(F64(a.$func(b))), - - (FInfer { f32: a32, f64: a64 }, - FInfer { f32: b32, f64: b64 }) => Ok(FInfer { - f32: a32.$func(b32), - f64: a64.$func(b64) - }), - + (F32(a), F32(b)) => Ok(F32(a.$func(b))), + (F64(a), F64(b)) => Ok(F64(a.$func(b))), _ => Err(UnequalTypes(Op::$op)), } } @@ -164,10 +135,6 @@ impl ::std::ops::Neg for ConstFloat { match self { F32(f) => F32(-f), F64(f) => F64(-f), - FInfer { f32, f64 } => FInfer { - f32: -f32, - f64: -f64 - } } } } diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index 17714f2fb2d6c..d97276da9bf34 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -30,8 +30,6 @@ pub enum ConstInt { U64(u64), U128(u128), Usize(ConstUsize), - Infer(u128), - InferSigned(i128), } pub use self::ConstInt::*; @@ -92,7 +90,7 @@ impl ConstInt { } } - /// Creates a new unsigned ConstInt with matching type while also checking that overflow does + /// Creates a new signed ConstInt with matching type while also checking that overflow does /// not happen. pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option { match ty { @@ -107,103 +105,33 @@ impl ConstInt { } } - /// If either value is `Infer` or `InferSigned`, try to turn the value into the type of - /// the other value. If both values have no type, don't do anything - pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> { - let inferred = match (self, other) { - (InferSigned(_), InferSigned(_)) - | (Infer(_), Infer(_)) => self, // no inference possible - // kindof wrong, you could have had values > I64MAX during computation of a - (Infer(a @ 0...ubounds::I64MAX), InferSigned(_)) => InferSigned(a as i128), - (Infer(_), InferSigned(_)) => return Err(ConstMathErr::NotInRange), - (_, InferSigned(_)) - | (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)), - - (Infer(a @ 0...ubounds::I8MAX), I8(_)) => I8(a as i64 as i8), - (Infer(a @ 0...ubounds::I16MAX), I16(_)) => I16(a as i64 as i16), - (Infer(a @ 0...ubounds::I32MAX), I32(_)) => I32(a as i64 as i32), - (Infer(a @ 0...ubounds::I64MAX), I64(_)) => I64(a as i64), - (Infer(a @ 0...ubounds::I128MAX), I128(_)) => I128(a as i128), - (Infer(a @ 0...ubounds::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)), - (Infer(a @ 0...ubounds::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)), - (Infer(a @ 0...ubounds::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)), - (Infer(a @ 0...ubounds::U8MAX), U8(_)) => U8(a as u8), - (Infer(a @ 0...ubounds::U16MAX), U16(_)) => U16(a as u16), - (Infer(a @ 0...ubounds::U32MAX), U32(_)) => U32(a as u32), - (Infer(a @ 0...ubounds::U64MAX), U64(_)) => U64(a as u64), - (Infer(a @ 0...ubounds::U128MAX), U128(_)) => U128(a as u128), - (Infer(a @ 0...ubounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), - (Infer(a @ 0...ubounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), - (Infer(a @ 0...ubounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), - - (Infer(_), _) => return Err(ConstMathErr::NotInRange), - - (InferSigned(a @ ibounds::I8MIN...ibounds::I8MAX), I8(_)) => I8(a as i8), - (InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), I16(_)) => I16(a as i16), - (InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), I32(_)) => I32(a as i32), - (InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), I64(_)) => I64(a as i64), - (InferSigned(a @ ibounds::I128MIN...ibounds::I128MAX), I128(_)) => I128(a as i128), - (InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), Isize(Is16(_))) => { - Isize(Is16(a as i16)) - }, - (InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), Isize(Is32(_))) => { - Isize(Is32(a as i32)) - }, - (InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), Isize(Is64(_))) => { - Isize(Is64(a as i64)) - }, - (InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8), - (InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16), - (InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32), - (InferSigned(a @ 0...ibounds::U64MAX), U64(_)) => U64(a as u64), - (InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128), - (InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), - (InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), - (InferSigned(a @ 0...ibounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), - (InferSigned(_), _) => return Err(ConstMathErr::NotInRange), - _ => self, // already known types - }; - Ok((inferred, other)) + /// Creates a new unsigned ConstInt with matching type. + pub fn new_unsigned_truncating(val: u128, ty: UintTy, usize_ty: UintTy) -> ConstInt { + match ty { + UintTy::U8 => U8(val as u8), + UintTy::U16 => U16(val as u16), + UintTy::U32 => U32(val as u32), + UintTy::U64 => U64(val as u64), + UintTy::Us => Usize(ConstUsize::new_truncating(val, usize_ty)), + UintTy::U128 => U128(val) + } } - /// Turn this value into an `Infer` or an `InferSigned` - pub fn erase_type(self) -> Self { - match self { - Infer(i) => Infer(i), - InferSigned(i) if i < 0 => InferSigned(i), - I8(i) if i < 0 => InferSigned(i as i128), - I16(i) if i < 0 => InferSigned(i as i128), - I32(i) if i < 0 => InferSigned(i as i128), - I64(i) if i < 0 => InferSigned(i as i128), - I128(i) if i < 0 => InferSigned(i as i128), - Isize(Is16(i)) if i < 0 => InferSigned(i as i128), - Isize(Is32(i)) if i < 0 => InferSigned(i as i128), - Isize(Is64(i)) if i < 0 => InferSigned(i as i128), - InferSigned(i) => Infer(i as u128), - I8(i) => Infer(i as u128), - I16(i) => Infer(i as u128), - I32(i) => Infer(i as u128), - I64(i) => Infer(i as u128), - I128(i) => Infer(i as u128), - Isize(Is16(i)) => Infer(i as u128), - Isize(Is32(i)) => Infer(i as u128), - Isize(Is64(i)) => Infer(i as u128), - U8(i) => Infer(i as u128), - U16(i) => Infer(i as u128), - U32(i) => Infer(i as u128), - U64(i) => Infer(i as u128), - U128(i) => Infer(i as u128), - Usize(Us16(i)) => Infer(i as u128), - Usize(Us32(i)) => Infer(i as u128), - Usize(Us64(i)) => Infer(i as u128), + /// Creates a new signed ConstInt with matching type. + pub fn new_signed_truncating(val: i128, ty: IntTy, isize_ty: IntTy) -> ConstInt { + match ty { + IntTy::I8 => I8(val as i8), + IntTy::I16 => I16(val as i16), + IntTy::I32 => I32(val as i32), + IntTy::I64 => I64(val as i64), + IntTy::Is => Isize(ConstIsize::new_truncating(val, isize_ty)), + IntTy::I128 => I128(val) } } /// Description of the type, not the value pub fn description(&self) -> &'static str { match *self { - Infer(_) => "not yet inferred integral", - InferSigned(_) => "not yet inferred signed integral", I8(_) => "i8", I16(_) => "i16", I32(_) => "i32", @@ -222,10 +150,23 @@ impl ConstInt { /// Erases the type and returns a u128. /// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128` pub fn to_u128_unchecked(self) -> u128 { - match self.erase_type() { - ConstInt::Infer(i) => i, - ConstInt::InferSigned(i) => i as u128, - _ => unreachable!(), + match self { + I8(i) => i as i128 as u128, + I16(i) => i as i128 as u128, + I32(i) => i as i128 as u128, + I64(i) => i as i128 as u128, + I128(i) => i as i128 as u128, + Isize(Is16(i)) => i as i128 as u128, + Isize(Is32(i)) => i as i128 as u128, + Isize(Is64(i)) => i as i128 as u128, + U8(i) => i as u128, + U16(i) => i as u128, + U32(i) => i as u128, + U64(i) => i as u128, + U128(i) => i as u128, + Usize(Us16(i)) => i as u128, + Usize(Us32(i)) => i as u128, + Usize(Us64(i)) => i as u128, } } @@ -250,8 +191,6 @@ impl ConstInt { /// Converts the value to a `u128` if it's in the range 0...std::u128::MAX pub fn to_u128(&self) -> Option { match *self { - Infer(v) => Some(v), - InferSigned(v) if v >= 0 => Some(v as u128), I8(v) if v >= 0 => Some(v as u128), I16(v) if v >= 0 => Some(v as u128), I32(v) if v >= 0 => Some(v as u128), @@ -272,6 +211,48 @@ impl ConstInt { } } + pub fn to_f32(self) -> f32 { + match self { + I8(i) => i as f32, + I16(i) => i as f32, + I32(i) => i as f32, + I64(i) => i as f32, + I128(i) => i as f32, + Isize(Is16(i)) => i as f32, + Isize(Is32(i)) => i as f32, + Isize(Is64(i)) => i as f32, + U8(i) => i as f32, + U16(i) => i as f32, + U32(i) => i as f32, + U64(i) => i as f32, + U128(i) => i as f32, + Usize(Us16(i)) => i as f32, + Usize(Us32(i)) => i as f32, + Usize(Us64(i)) => i as f32, + } + } + + pub fn to_f64(self) -> f64 { + match self { + I8(i) => i as f64, + I16(i) => i as f64, + I32(i) => i as f64, + I64(i) => i as f64, + I128(i) => i as f64, + Isize(Is16(i)) => i as f64, + Isize(Is32(i)) => i as f64, + Isize(Is64(i)) => i as f64, + U8(i) => i as f64, + U16(i) => i as f64, + U32(i) => i as f64, + U64(i) => i as f64, + U128(i) => i as f64, + Usize(Us16(i)) => i as f64, + Usize(Us32(i)) => i as f64, + Usize(Us64(i)) => i as f64, + } + } + pub fn is_negative(&self) -> bool { match *self { I8(v) => v < 0, @@ -282,14 +263,13 @@ impl ConstInt { Isize(Is16(v)) => v < 0, Isize(Is32(v)) => v < 0, Isize(Is64(v)) => v < 0, - InferSigned(v) => v < 0, _ => false, } } /// Compares the values if they are of the same type pub fn try_cmp(self, rhs: Self) -> Result<::std::cmp::Ordering, ConstMathErr> { - match self.infer(rhs)? { + match (self, rhs) { (I8(a), I8(b)) => Ok(a.cmp(&b)), (I16(a), I16(b)) => Ok(a.cmp(&b)), (I32(a), I32(b)) => Ok(a.cmp(&b)), @@ -306,8 +286,6 @@ impl ConstInt { (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)), (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)), (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)), - (Infer(a), Infer(b)) => Ok(a.cmp(&b)), - (InferSigned(a), InferSigned(b)) => Ok(a.cmp(&b)), _ => Err(CmpBetweenUnequalTypes), } } @@ -334,25 +312,23 @@ impl ConstInt { ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))), ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))), ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))), - ConstInt::Infer(_) | ConstInt::InferSigned(_) => panic!("no type info for const int"), } } - pub fn int_type(self) -> Option { + pub fn int_type(self) -> IntType { match self { - ConstInt::I8(_) => Some(IntType::SignedInt(IntTy::I8)), - ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)), - ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)), - ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)), - ConstInt::I128(_) => Some(IntType::SignedInt(IntTy::I128)), - ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)), - ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)), - ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)), - ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)), - ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)), - ConstInt::U128(_) => Some(IntType::UnsignedInt(UintTy::U128)), - ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)), - _ => None, + ConstInt::I8(_) => IntType::SignedInt(IntTy::I8), + ConstInt::I16(_) => IntType::SignedInt(IntTy::I16), + ConstInt::I32(_) => IntType::SignedInt(IntTy::I32), + ConstInt::I64(_) => IntType::SignedInt(IntTy::I64), + ConstInt::I128(_) => IntType::SignedInt(IntTy::I128), + ConstInt::Isize(_) => IntType::SignedInt(IntTy::Is), + ConstInt::U8(_) => IntType::UnsignedInt(UintTy::U8), + ConstInt::U16(_) => IntType::UnsignedInt(UintTy::U16), + ConstInt::U32(_) => IntType::UnsignedInt(UintTy::U32), + ConstInt::U64(_) => IntType::UnsignedInt(UintTy::U64), + ConstInt::U128(_) => IntType::UnsignedInt(UintTy::U128), + ConstInt::Usize(_) => IntType::UnsignedInt(UintTy::Us), } } } @@ -372,8 +348,6 @@ impl ::std::cmp::Ord for ConstInt { impl ::std::fmt::Display for ConstInt { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { match *self { - Infer(i) => write!(fmt, "{}", i), - InferSigned(i) => write!(fmt, "{}", i), I8(i) => write!(fmt, "{}i8", i), I16(i) => write!(fmt, "{}i16", i), I32(i) => write!(fmt, "{}i32", i), @@ -409,7 +383,7 @@ macro_rules! impl_binop { impl ::std::ops::$op for ConstInt { type Output = Result; fn $func(self, rhs: Self) -> Result { - match self.infer(rhs)? { + match (self, rhs) { (I8(a), I8(b)) => a.$checked_func(b).map(I8), (I16(a), I16(b)) => a.$checked_func(b).map(I16), (I32(a), I32(b)) => a.$checked_func(b).map(I32), @@ -426,8 +400,6 @@ macro_rules! impl_binop { (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize), (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize), (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize), - (Infer(a), Infer(b)) => a.$checked_func(b).map(Infer), - (InferSigned(a), InferSigned(b)) => a.$checked_func(b).map(InferSigned), _ => return Err(UnequalTypes(Op::$op)), }.ok_or(Overflow(Op::$op)) } @@ -440,7 +412,7 @@ macro_rules! derive_binop { impl ::std::ops::$op for ConstInt { type Output = Result; fn $func(self, rhs: Self) -> Result { - match self.infer(rhs)? { + match (self, rhs) { (I8(a), I8(b)) => Ok(I8(a.$func(b))), (I16(a), I16(b)) => Ok(I16(a.$func(b))), (I32(a), I32(b)) => Ok(I32(a.$func(b))), @@ -457,8 +429,6 @@ macro_rules! derive_binop { (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))), (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))), (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))), - (Infer(a), Infer(b)) => Ok(Infer(a.$func(b))), - (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a.$func(b))), _ => Err(UnequalTypes(Op::$op)), } } @@ -490,7 +460,6 @@ fn check_division( (Isize(_), Isize(Is16(0))) => Err(zerr), (Isize(_), Isize(Is32(0))) => Err(zerr), (Isize(_), Isize(Is64(0))) => Err(zerr), - (InferSigned(_), InferSigned(0)) => Err(zerr), (U8(_), U8(0)) => Err(zerr), (U16(_), U16(0)) => Err(zerr), @@ -500,7 +469,6 @@ fn check_division( (Usize(_), Usize(Us16(0))) => Err(zerr), (Usize(_), Usize(Us32(0))) => Err(zerr), (Usize(_), Usize(Us64(0))) => Err(zerr), - (Infer(_), Infer(0)) => Err(zerr), (I8(::std::i8::MIN), I8(-1)) => Err(Overflow(op)), (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)), @@ -510,7 +478,6 @@ fn check_division( (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)), (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)), (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)), - (InferSigned(I128_MIN), InferSigned(-1)) => Err(Overflow(op)), _ => Ok(()), } @@ -519,7 +486,7 @@ fn check_division( impl ::std::ops::Div for ConstInt { type Output = Result; fn div(self, rhs: Self) -> Result { - let (lhs, rhs) = self.infer(rhs)?; + let (lhs, rhs) = (self, rhs); check_division(lhs, rhs, Op::Div, DivisionByZero)?; match (lhs, rhs) { (I8(a), I8(b)) => Ok(I8(a/b)), @@ -530,7 +497,6 @@ impl ::std::ops::Div for ConstInt { (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))), (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))), (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))), - (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a/b)), (U8(a), U8(b)) => Ok(U8(a/b)), (U16(a), U16(b)) => Ok(U16(a/b)), @@ -540,7 +506,6 @@ impl ::std::ops::Div for ConstInt { (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))), (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))), (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))), - (Infer(a), Infer(b)) => Ok(Infer(a/b)), _ => Err(UnequalTypes(Op::Div)), } @@ -550,7 +515,7 @@ impl ::std::ops::Div for ConstInt { impl ::std::ops::Rem for ConstInt { type Output = Result; fn rem(self, rhs: Self) -> Result { - let (lhs, rhs) = self.infer(rhs)?; + let (lhs, rhs) = (self, rhs); // should INT_MIN%-1 be zero or an error? check_division(lhs, rhs, Op::Rem, RemainderByZero)?; match (lhs, rhs) { @@ -562,7 +527,6 @@ impl ::std::ops::Rem for ConstInt { (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))), (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))), (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))), - (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a%b)), (U8(a), U8(b)) => Ok(U8(a%b)), (U16(a), U16(b)) => Ok(U16(a%b)), @@ -572,7 +536,6 @@ impl ::std::ops::Rem for ConstInt { (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))), (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))), (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))), - (Infer(a), Infer(b)) => Ok(Infer(a%b)), _ => Err(UnequalTypes(Op::Rem)), } @@ -600,8 +563,6 @@ impl ::std::ops::Shl for ConstInt { Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))), Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))), Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))), - Infer(a) => Ok(Infer(overflowing!(a.overflowing_shl(b), Op::Shl))), - InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_shl(b), Op::Shl))), } } } @@ -627,8 +588,6 @@ impl ::std::ops::Shr for ConstInt { Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))), Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))), Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))), - Infer(a) => Ok(Infer(overflowing!(a.overflowing_shr(b), Op::Shr))), - InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_shr(b), Op::Shr))), } } } @@ -648,9 +607,6 @@ impl ::std::ops::Neg for ConstInt { a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) | a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a), U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation), - Infer(a @ 0...ubounds::I128MAX) => Ok(InferSigned(-(a as i128))), - Infer(_) => Err(Overflow(Op::Neg)), - InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))), } } } @@ -675,8 +631,6 @@ impl ::std::ops::Not for ConstInt { Usize(Us16(a)) => Ok(Usize(Us16(!a))), Usize(Us32(a)) => Ok(Usize(Us32(!a))), Usize(Us64(a)) => Ok(Usize(Us64(!a))), - Infer(a) => Ok(Infer(!a)), - InferSigned(a) => Ok(InferSigned(!a)), } } } diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 13764ce5bbbfd..b7833a5440321 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -21,7 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] - +#![deny(warnings)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 3301a98968ee8..529afe0215e53 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -17,7 +17,6 @@ use rustc::ty::layout::{Layout, Primitive}; use rustc::traits::Reveal; use middle::const_val::ConstVal; use rustc_const_eval::ConstContext; -use rustc_const_eval::EvalHint::ExprTypeChecked; use util::nodemap::FxHashSet; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass}; @@ -109,7 +108,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } else { let const_cx = ConstContext::with_tables(cx.tcx, cx.tables); - match const_cx.eval(&r, ExprTypeChecked) { + match const_cx.eval(&r) { Ok(ConstVal::Integral(i)) => { i.is_negative() || i.to_u64() diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index fa39b687355bf..26d907523a886 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -230,9 +230,9 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy), - Struct(Lazy, ReprOptions), - Union(Lazy, ReprOptions), + Variant(Lazy>), + Struct(Lazy>, ReprOptions), + Union(Lazy>, ReprOptions), Fn(Lazy), ForeignFn(Lazy), Mod(Lazy), @@ -263,10 +263,10 @@ pub struct FnData { } #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData { +pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, - pub evaluated_discr: Option, + pub evaluated_discr: Option>, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index a28bc5d6ce36d..6b6acb054b1b0 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -309,13 +309,13 @@ enum TestKind<'tcx> { // test the branches of enum SwitchInt { switch_ty: Ty<'tcx>, - options: Vec, - indices: FxHashMap, + options: Vec>, + indices: FxHashMap, usize>, }, // test for equality Eq { - value: ConstVal, + value: ConstVal<'tcx>, ty: Ty<'tcx>, }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index fa8d7ffccde40..f4fdf8ade900a 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -112,8 +112,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { test_lvalue: &Lvalue<'tcx>, candidate: &Candidate<'pat, 'tcx>, switch_ty: Ty<'tcx>, - options: &mut Vec, - indices: &mut FxHashMap) + options: &mut Vec>, + indices: &mut FxHashMap, usize>) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index ecdc58ba55d6c..41374a0012327 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -223,6 +223,17 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, builder.finish(vec![], ty) } +pub fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, + body_id: hir::BodyId) + -> Mir<'tcx> { + let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id)); + let ty = hir.tcx().types.err; + let mut builder = Builder::new(hir, span, 0, ty); + let source_info = builder.source_info(span); + builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); + builder.finish(vec![], ty) +} + impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn new(hir: Cx<'a, 'gcx, 'tcx>, span: Span, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 2cb26eed1fff1..f2b89309e4ab1 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -17,7 +17,7 @@ use hair::cx::to_ref::ToRef; use rustc::hir::map; use rustc::hir::def::{Def, CtorKind}; use rustc::middle::const_val::ConstVal; -use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; +use rustc_const_eval::{ConstContext, fatal_const_eval_err}; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; @@ -594,7 +594,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprRepeat(ref v, count) => { let tcx = cx.tcx.global_tcx(); let c = &cx.tcx.hir.body(count).value; - let count = match ConstContext::new(tcx, count).eval(c, EvalHint::ExprTypeChecked) { + let count = match ConstContext::new(tcx, count).eval(c) { Ok(ConstVal::Integral(ConstInt::Usize(u))) => u, Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other), Err(s) => fatal_const_eval_err(tcx, &s, c.span, "expression") diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 852c34a544a97..c555ce1ab9c42 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,7 +18,7 @@ use hair::*; use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; -use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; +use rustc_const_eval::{ConstContext, fatal_const_eval_err}; use rustc_data_structures::indexed_vec::Idx; use rustc::hir::def_id::DefId; use rustc::hir::map::blocks::FnLikeNode; @@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { let tcx = self.tcx.global_tcx(); - match ConstContext::with_tables(tcx, self.tables()).eval(e, EvalHint::ExprTypeChecked) { + match ConstContext::with_tables(tcx, self.tables()).eval(e) { Ok(value) => Literal::Value { value: value }, Err(s) => fatal_const_eval_err(tcx, &s, e.span, "expression") } diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 0d7be189f883a..e0eb09fbf5d6f 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -98,7 +98,9 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let src = MirSource::from_node(tcx, id); tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| { let cx = Cx::new(&infcx, src); - let mut mir = if let MirSource::Fn(id) = src { + let mut mir = if cx.tables().tainted_by_errors { + build::construct_error(cx, body_id) + } else if let MirSource::Fn(id) = src { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) let fn_sig = cx.tables().liberated_fn_sigs[&id].clone(); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index e3a77a9359980..930a13e36bdca 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -28,9 +28,8 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::CastKind; use rustc_const_eval::{ConstEvalErr, ConstContext}; use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; -use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath, BadType}; -use rustc_const_eval::ErrKind::UnresolvedPath; -use rustc_const_eval::EvalHint::ExprTypeChecked; +use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; +use rustc_const_eval::ErrKind::{TypeckError}; use rustc_const_math::{ConstMathErr, Op}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; @@ -66,12 +65,12 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn check_const_eval(&self, expr: &'gcx hir::Expr) { let const_cx = ConstContext::with_tables(self.tcx, self.tables); - if let Err(err) = const_cx.eval(expr, ExprTypeChecked) { + if let Err(err) = const_cx.eval(expr) { match err.kind { UnimplementedConstVal(_) => {} IndexOpFeatureGated => {} ErroneousReferencedConstant(_) => {} - BadType(_) => {} + TypeckError => {} _ => { self.tcx.sess.add_lint(CONST_ERR, expr.id, @@ -240,18 +239,17 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { if self.in_fn && self.promotable { let const_cx = ConstContext::with_tables(self.tcx, self.tables); - match const_cx.eval(ex, ExprTypeChecked) { + match const_cx.eval(ex) { Ok(_) => {} Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) | Err(ConstEvalErr { kind: MiscCatchAll, .. }) | Err(ConstEvalErr { kind: MiscBinaryOp, .. }) | Err(ConstEvalErr { kind: NonConstPath, .. }) | - Err(ConstEvalErr { kind: UnresolvedPath, .. }) | Err(ConstEvalErr { kind: ErroneousReferencedConstant(_), .. }) | Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), .. }) | Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), .. }) | Err(ConstEvalErr { kind: IndexOpFeatureGated, .. }) => {} - Err(ConstEvalErr { kind: BadType(_), .. }) => {} + Err(ConstEvalErr { kind: TypeckError, .. }) => {} Err(msg) => { self.tcx.sess.add_lint(CONST_ERR, ex.id, diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index b68de7b46c82e..011f7748f2c98 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -213,11 +213,11 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { g } -pub fn trans_static(ccx: &CrateContext, - m: hir::Mutability, - id: ast::NodeId, - attrs: &[ast::Attribute]) - -> Result { +pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + m: hir::Mutability, + id: ast::NodeId, + attrs: &[ast::Attribute]) + -> Result> { unsafe { let def_id = ccx.tcx().hir.local_def_id(id); let g = get_static(ccx, def_id); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index d34b1aa206044..3cad2bc1d8423 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { if switch_ty == bcx.tcx().types.bool { let lltrue = llblock(self, targets[0]); let llfalse = llblock(self, targets[1]); - if let [ConstInt::Infer(0)] = values[..] { + if let [ConstInt::U8(0)] = values[..] { bcx.cond_br(discr.immediate(), llfalse, lltrue); } else { bcx.cond_br(discr.immediate(), lltrue, llfalse); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 1f595cae6a805..771a5b7f366a1 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -83,7 +83,6 @@ impl<'tcx> Const<'tcx> { let u = v.as_u64(ccx.tcx().sess.target.uint_type); (C_integral(Type::int(ccx), u, false), tcx.types.usize) }, - Infer(_) | InferSigned(_) => bug!("MIR must not use `{:?}`", ci), }; Const { llval: llval, ty: ty } } @@ -97,14 +96,13 @@ impl<'tcx> Const<'tcx> { let val = match cv { ConstVal::Float(F32(v)) => C_floating_f64(v as f64, llty), ConstVal::Float(F64(v)) => C_floating_f64(v, llty), - ConstVal::Float(FInfer {..}) => bug!("MIR must not use `{:?}`", cv), ConstVal::Bool(v) => C_bool(ccx, v), ConstVal::Integral(ref i) => return Const::from_constint(ccx, i), ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()), ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"), ConstVal::Struct(_) | ConstVal::Tuple(_) | ConstVal::Array(..) | ConstVal::Repeat(..) | - ConstVal::Function(_) => { + ConstVal::Function(..) => { bug!("MIR must not use `{:?}` (which refers to a local ID)", cv) } ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false), @@ -249,7 +247,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { fn trans_def(ccx: &'a CrateContext<'a, 'tcx>, instance: Instance<'tcx>, args: IndexVec>) - -> Result, ConstEvalErr> { + -> Result, ConstEvalErr<'tcx>> { let instance = instance.resolve_const(ccx.shared()); let mir = ccx.tcx().item_mir(instance.def); MirConstContext::new(ccx, &mir, instance.substs, args).trans() @@ -263,7 +261,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { value) } - fn trans(&mut self) -> Result, ConstEvalErr> { + fn trans(&mut self) -> Result, ConstEvalErr<'tcx>> { let tcx = self.ccx.tcx(); let mut bb = mir::START_BLOCK; @@ -325,7 +323,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { }; let err = ConstEvalErr{ span: span, kind: err }; - report_const_eval_err(tcx, &err, span, "expression").emit(); + report_const_eval_err(tcx, &err, span, "expression"); failure = Err(err); } target @@ -373,7 +371,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span) - -> Result, ConstEvalErr> { + -> Result, ConstEvalErr<'tcx>> { let tcx = self.ccx.tcx(); if let mir::Lvalue::Local(index) = *lvalue { @@ -468,7 +466,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span) - -> Result, ConstEvalErr> { + -> Result, ConstEvalErr<'tcx>> { debug!("const_operand({:?} @ {:?})", operand, span); let result = match *operand { mir::Operand::Consume(ref lvalue) => { @@ -523,7 +521,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>, dest_ty: Ty<'tcx>, span: Span) - -> Result, ConstEvalErr> { + -> Result, ConstEvalErr<'tcx>> { let tcx = self.ccx.tcx(); debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span); let val = match *rvalue { @@ -961,8 +959,11 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } -pub fn trans_static_initializer(ccx: &CrateContext, def_id: DefId) - -> Result { +pub fn trans_static_initializer<'a, 'tcx>( + ccx: &CrateContext<'a, 'tcx>, + def_id: DefId) + -> Result> +{ let instance = Instance::mono(ccx.shared(), def_id); MirConstContext::trans_def(ccx, instance, IndexVec::new()).map(|c| c.llval) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index aae3947df1424..577fe31eab02a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -189,7 +189,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { &item_segment.parameters, None); - assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span)); + assoc_bindings.first().map(|b| self.prohibit_projection(b.span)); substs } @@ -446,7 +446,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_def_id, self_ty, trait_segment); - assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span)); + assoc_bindings.first().map(|b| self.prohibit_projection(b.span)); ty::TraitRef::new(trait_def_id, substs) } @@ -844,7 +844,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name); - tcx.prohibit_type_params(slice::ref_slice(item_segment)); + self.prohibit_type_params(slice::ref_slice(item_segment)); // Find the type of the associated item, and the trait where the associated // item is declared. @@ -917,7 +917,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { let tcx = self.tcx(); - tcx.prohibit_type_params(slice::ref_slice(item_segment)); + self.prohibit_type_params(slice::ref_slice(item_segment)); let self_ty = if let Some(ty) = opt_self_ty { ty @@ -942,6 +942,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.projected_ty(span, trait_ref, item_segment.name) } + pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { + for segment in segments { + for typ in segment.parameters.types() { + struct_span_err!(self.tcx().sess, typ.span, E0109, + "type parameters are not allowed on this type") + .span_label(typ.span, &format!("type parameter not allowed")) + .emit(); + break; + } + for lifetime in segment.parameters.lifetimes() { + struct_span_err!(self.tcx().sess, lifetime.span, E0110, + "lifetime parameters are not allowed on this type") + .span_label(lifetime.span, + &format!("lifetime parameter not allowed on this type")) + .emit(); + break; + } + for binding in segment.parameters.bindings() { + self.prohibit_projection(binding.span); + break; + } + } + } + + pub fn prohibit_projection(&self, span: Span) { + let mut err = struct_span_err!(self.tcx().sess, span, E0229, + "associated type bindings are not allowed here"); + err.span_label(span, &format!("associate type not allowed here")).emit(); + } + // Check a type Path and convert it to a Ty. pub fn def_to_ty(&self, opt_self_ty: Option>, @@ -957,21 +987,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { match path.def { Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => { assert_eq!(opt_self_ty, None); - tcx.prohibit_type_params(path.segments.split_last().unwrap().1); + self.prohibit_type_params(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, did, path.segments.last().unwrap()) } Def::Variant(did) if permit_variants => { // Convert "variant type" as if it were a real type. // The resulting `Ty` is type of the variant's enum for now. assert_eq!(opt_self_ty, None); - tcx.prohibit_type_params(path.segments.split_last().unwrap().1); + self.prohibit_type_params(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, tcx.parent_def_id(did).unwrap(), path.segments.last().unwrap()) } Def::TyParam(did) => { assert_eq!(opt_self_ty, None); - tcx.prohibit_type_params(&path.segments); + self.prohibit_type_params(&path.segments); let node_id = tcx.hir.as_local_node_id(did).unwrap(); let item_id = tcx.hir.get_parent_node(node_id); @@ -984,7 +1014,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Self in impl (we know the concrete type). assert_eq!(opt_self_ty, None); - tcx.prohibit_type_params(&path.segments); + self.prohibit_type_params(&path.segments); let ty = ty::queries::ty::get(tcx, span, def_id); if let Some(free_substs) = self.get_free_substs() { @@ -996,11 +1026,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::SelfTy(Some(_), None) => { // Self in trait. assert_eq!(opt_self_ty, None); - tcx.prohibit_type_params(&path.segments); + self.prohibit_type_params(&path.segments); tcx.mk_self_type() } Def::AssociatedTy(def_id) => { - tcx.prohibit_type_params(&path.segments[..path.segments.len()-2]); + self.prohibit_type_params(&path.segments[..path.segments.len()-2]); let trait_did = tcx.parent_def_id(def_id).unwrap(); self.qpath_to_ty(span, opt_self_ty, @@ -1010,7 +1040,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } Def::PrimTy(prim_ty) => { assert_eq!(opt_self_ty, None); - tcx.prim_ty_to_ty(&path.segments, prim_ty) + self.prohibit_type_params(&path.segments); + match prim_ty { + hir::TyBool => tcx.types.bool, + hir::TyChar => tcx.types.char, + hir::TyInt(it) => tcx.mk_mach_int(it), + hir::TyUint(uit) => tcx.mk_mach_uint(uit), + hir::TyFloat(ft) => tcx.mk_mach_float(ft), + hir::TyStr => tcx.mk_str() + } } Def::Err => { self.set_tainted_by_errors(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index aa1fc0f8579da..0337727dcba9a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -432,10 +432,6 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { body_id: ast::NodeId, - // This flag is set to true if, during the writeback phase, we encounter - // a type error in this function. - writeback_errors: Cell, - // Number of errors that had been reported when we started // checking this function. On exit, if we find that *more* errors // have been reported, we will skip regionck and other work that @@ -1493,7 +1489,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { FnCtxt { ast_ty_to_ty_cache: RefCell::new(NodeMap()), body_id: body_id, - writeback_errors: Cell::new(false), err_count_on_creation: inh.tcx.sess.err_count(), ret_ty: rty, ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, @@ -1609,6 +1604,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if ty.references_error() { self.has_errors.set(true); + self.set_tainted_by_errors(); } // FIXME(canndrew): This is_never should probably be an is_uninhabited @@ -4326,7 +4322,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // errors if type parameters are provided in an inappropriate place. let poly_segments = type_segment.is_some() as usize + fn_segment.is_some() as usize; - self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]); + AstConv::prohibit_type_params(self, &segments[..segments.len() - poly_segments]); match def { Def::Local(def_id) | Def::Upvar(def_id, ..) => { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 4f0cfa8d014e6..1382ab34ca520 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -20,7 +20,6 @@ use rustc::ty::fold::{TypeFolder,TypeFoldable}; use rustc::infer::{InferCtxt, FixupError}; use rustc::util::nodemap::{DefIdMap, DefIdSet}; -use std::cell::Cell; use std::mem; use syntax::ast; @@ -35,8 +34,6 @@ use rustc::hir; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> { - assert_eq!(self.writeback_errors.get(), false); - let item_id = self.tcx.hir.body_owner(body.id()); let item_def_id = self.tcx.hir.local_def_id(item_id); @@ -59,6 +56,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); wbcx.tables.used_trait_imports = used_trait_imports; + wbcx.tables.tainted_by_errors = self.is_tainted_by_errors(); + self.tcx.alloc_tables(wbcx.tables) } } @@ -195,19 +194,11 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_stmt(&mut self, s: &'gcx hir::Stmt) { - if self.fcx.writeback_errors.get() { - return; - } - self.visit_node_id(ResolvingExpr(s.span), s.node.id()); intravisit::walk_stmt(self, s); } fn visit_expr(&mut self, e: &'gcx hir::Expr) { - if self.fcx.writeback_errors.get() { - return; - } - self.fix_scalar_builtin_expr(e); self.visit_node_id(ResolvingExpr(e.span), e.id); @@ -227,29 +218,16 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_block(&mut self, b: &'gcx hir::Block) { - if self.fcx.writeback_errors.get() { - return; - } - self.visit_node_id(ResolvingExpr(b.span), b.id); intravisit::walk_block(self, b); } fn visit_pat(&mut self, p: &'gcx hir::Pat) { - if self.fcx.writeback_errors.get() { - return; - } - self.visit_node_id(ResolvingPattern(p.span), p.id); - intravisit::walk_pat(self, p); } fn visit_local(&mut self, l: &'gcx hir::Local) { - if self.fcx.writeback_errors.get() { - return; - } - let var_ty = self.fcx.local_ty(l.span, l.id); let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); self.write_ty_to_tables(l.id, var_ty); @@ -259,10 +237,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn visit_upvar_borrow_map(&mut self) { - if self.fcx.writeback_errors.get() { - return; - } - for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, @@ -281,10 +255,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_closures(&mut self) { - if self.fcx.writeback_errors.get() { - return - } - for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); self.tables.closure_tys.insert(id, closure_ty); @@ -296,27 +266,15 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } fn visit_cast_types(&mut self) { - if self.fcx.writeback_errors.get() { - return - } - self.tables.cast_kinds.extend( self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value))); } fn visit_lints(&mut self) { - if self.fcx.writeback_errors.get() { - return - } - self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints); } fn visit_anon_types(&mut self) { - if self.fcx.writeback_errors.get() { - return - } - let gcx = self.tcx().global_tcx(); for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() { let reason = ResolvingAnonTy(node_id); @@ -542,7 +500,6 @@ impl<'a, 'gcx, 'tcx> ResolveReason { struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - writeback_errors: &'cx Cell, reason: ResolveReason, } @@ -551,22 +508,19 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { reason: ResolveReason) -> Resolver<'cx, 'gcx, 'tcx> { - Resolver::from_infcx(fcx, &fcx.writeback_errors, reason) + Resolver::from_infcx(fcx, reason) } fn from_infcx(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - writeback_errors: &'cx Cell, reason: ResolveReason) -> Resolver<'cx, 'gcx, 'tcx> { Resolver { infcx: infcx, tcx: infcx.tcx, - writeback_errors: writeback_errors, reason: reason } } fn report_error(&self, e: FixupError) { - self.writeback_errors.set(true); if !self.tcx.sess.has_errors() { match self.reason { ResolvingExpr(span) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ecdbf170702aa..7f413a0dfc3ab 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -59,7 +59,6 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use middle::resolve_lifetime as rl; -use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ReprOptions}; @@ -75,7 +74,7 @@ use rustc_const_math::ConstInt; use std::cell::RefCell; use std::collections::BTreeMap; -use syntax::{abi, ast, attr}; +use syntax::{abi, ast}; use syntax::codemap::Spanned; use syntax::symbol::{Symbol, keywords}; use syntax_pos::{Span, DUMMY_SP}; @@ -596,6 +595,17 @@ fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.item_predicates(def_id); } +fn evaluate_disr_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + body: hir::BodyId) + -> Result, ()> { + let e = &tcx.hir.body(body).value; + ConstContext::new(tcx, body).eval(e).map_err(|err| { + // enum variant evaluation happens before the global constant check + // so we need to report the real error + report_const_eval_err(tcx, &err, e.span, "enum discriminant"); + }) +} + fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, variants: &[hir::Variant]) { @@ -610,7 +620,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, prev_discr = Some(if let Some(e) = variant.node.disr_expr { let expr_did = tcx.hir.local_def_id(e.node_id); let result = tcx.maps.monomorphic_const_eval.memoize(expr_did, || { - evaluate_disr_expr(tcx, repr_type, e).map(ConstVal::Integral) + evaluate_disr_expr(tcx, e) }); match result { @@ -738,60 +748,6 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.alloc_adt_def(def_id, kind, variants, repr) } -fn evaluate_disr_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - repr_ty: attr::IntType, - body: hir::BodyId) - -> Result { - let e = &tcx.hir.body(body).value; - debug!("disr expr, checking {}", tcx.hir.node_to_pretty_string(e.id)); - - let ty_hint = repr_ty.to_ty(tcx); - let print_err = |cv: ConstVal| { - struct_span_err!(tcx.sess, e.span, E0079, "mismatched types") - .note_expected_found(&"type", &ty_hint, &format!("{}", cv.description())) - .span_label(e.span, &format!("expected '{}' type", ty_hint)) - .emit(); - }; - - let hint = UncheckedExprHint(ty_hint); - match ConstContext::new(tcx, body).eval(e, hint) { - Ok(ConstVal::Integral(i)) => { - // FIXME: eval should return an error if the hint does not match the type of the body. - // i.e. eventually the match below would not exist. - match (repr_ty, i) { - (attr::SignedInt(ast::IntTy::I8), ConstInt::I8(_)) | - (attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) | - (attr::SignedInt(ast::IntTy::I32), ConstInt::I32(_)) | - (attr::SignedInt(ast::IntTy::I64), ConstInt::I64(_)) | - (attr::SignedInt(ast::IntTy::I128), ConstInt::I128(_)) | - (attr::SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) | - (attr::UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) | - (attr::UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) | - (attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) | - (attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) | - (attr::UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) | - (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Ok(i), - (_, i) => { - print_err(ConstVal::Integral(i)); - Err(()) - }, - } - }, - Ok(cv) => { - print_err(cv); - Err(()) - }, - // enum variant evaluation happens before the global constant check - // so we need to report the real error - Err(err) => { - let mut diag = report_const_eval_err( - tcx, &err, e.span, "enum discriminant"); - diag.emit(); - Err(()) - } - } -} - /// Ensures that the super-predicates of the trait with def-id /// trait_def_id are converted and stored. This also ensures that /// the transitive super-predicates are converted; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index e8cb25cec4f25..644e323a8dbf2 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1039,45 +1039,6 @@ struct Good(u32, u32, u32); ``` "##, -E0079: r##" -Enum variants which contain no data can be given a custom integer -representation. This error indicates that the value provided is not an integer -literal and is therefore invalid. - -For example, in the following code: - -```compile_fail,E0079 -enum Foo { - Q = "32", -} -``` - -We try to set the representation to a string. - -There's no general fix for this; if you can work with an integer then just set -it to one: - -``` -enum Foo { - Q = 32, -} -``` - -However if you actually wanted a mapping between variants and non-integer -objects, it may be preferable to use a method with a match instead: - -``` -enum Foo { Q } -impl Foo { - fn get_str(&self) -> &'static str { - match *self { - Foo::Q => "32", - } - } -} -``` -"##, - E0081: r##" Enum discriminants are used to differentiate enum variants stored in memory. This error indicates that the same value was used for two or more variants, @@ -1427,6 +1388,44 @@ struct Baz<'a> { ``` "##, +E0109: r##" +You tried to give a type parameter to a type which doesn't need it. Erroneous +code example: + +```compile_fail,E0109 +type X = u32; // error: type parameters are not allowed on this type +``` + +Please check that you used the correct type and recheck its definition. Perhaps +it doesn't need the type parameter. + +Example: + +``` +type X = u32; // this compiles +``` + +Note that type parameters for enum-variant constructors go after the variant, +not after the enum (Option::None::, not Option::::None). +"##, + +E0110: r##" +You tried to give a lifetime parameter to a type which doesn't need it. +Erroneous code example: + +```compile_fail,E0110 +type X = u32<'static>; // error: lifetime parameters are not allowed on + // this type +``` + +Please check that the correct type was used and recheck its definition; perhaps +it doesn't need the lifetime parameter. Example: + +``` +type X = u32; // ok! +``` +"##, + E0116: r##" You can only define an inherent implementation for a type in the same crate where the type was defined. For example, an `impl` block as below is not allowed @@ -2649,6 +2648,41 @@ fn main() { ``` "##, +E0229: r##" +An associated type binding was done outside of the type parameter declaration +and `where` clause. Erroneous code example: + +```compile_fail,E0229 +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +fn baz(x: &>::A) {} +// error: associated type bindings are not allowed here +``` + +To solve this error, please move the type bindings in the type parameter +declaration: + +```ignore +fn baz>(x: &::A) {} // ok! +``` + +Or in the `where` clause: + +```ignore +fn baz(x: &::A) where I: Foo {} +``` +"##, + E0230: r##" The trait has more type parameters specified than appear in its definition. diff --git a/src/test/compile-fail/E0306.rs b/src/test/compile-fail/E0306.rs deleted file mode 100644 index 9ffaef7472b78..0000000000000 --- a/src/test/compile-fail/E0306.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -const A: [u32; "hello"] = []; -//~^ ERROR expected `usize` for array length, found string literal [E0306] -//~| NOTE expected `usize` - -const B: [u32; true] = []; -//~^ ERROR expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` - -const C: [u32; 0.0] = []; -//~^ ERROR expected `usize` for array length, found float [E0306] -//~| NOTE expected `usize` - -fn main() { -} diff --git a/src/test/compile-fail/associated-const-array-len.rs b/src/test/compile-fail/associated-const-array-len.rs index 0239986f5ad3a..7f77ae2ec1f10 100644 --- a/src/test/compile-fail/associated-const-array-len.rs +++ b/src/test/compile-fail/associated-const-array-len.rs @@ -14,7 +14,8 @@ trait Foo { const ID: usize; } -const X: [i32; ::ID] = [0, 1, 2]; //~ ERROR E0080 +const X: [i32; ::ID] = [0, 1, 2]; +//~^ ERROR the trait bound `i32: Foo` is not satisfied fn main() { assert_eq!(1, X); diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs index 7c3f7a1d574f9..7fd9605ef2cdc 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs @@ -27,8 +27,6 @@ impl Foo for Def { pub fn test() { let _array = [4; ::Y]; //~^ ERROR cannot use an outer type parameter in this context [E0402] - //~| ERROR constant evaluation error [E0080] - //~| non-constant path in constant } fn main() { diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays.rs b/src/test/compile-fail/associated-const-type-parameter-arrays.rs index dcf87d5f0fc44..71c7a3965ec3c 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays.rs @@ -27,8 +27,6 @@ impl Foo for Def { pub fn test() { let _array: [u32; ::Y]; //~^ ERROR cannot use an outer type parameter in this context [E0402] - //~| ERROR constant evaluation error [E0080] - //~| non-constant path in constant } fn main() { diff --git a/src/test/compile-fail/const-array-oob.rs b/src/test/compile-fail/const-array-oob.rs index b980bc02c85a2..108b7948dfcc2 100644 --- a/src/test/compile-fail/const-array-oob.rs +++ b/src/test/compile-fail/const-array-oob.rs @@ -12,8 +12,8 @@ #![feature(const_indexing)] -const FOO: [u32; 3] = [1, 2, 3]; -const BAR: u32 = FOO[5]; // no error, because the error below occurs before regular const eval +const FOO: [usize; 3] = [1, 2, 3]; +const BAR: usize = FOO[5]; // no error, because the error below occurs before regular const eval const BLUB: [u32; FOO[4]] = [5, 6]; //~^ ERROR constant evaluation error [E0080] diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs index 9e7a5ecae105a..02072e9a1a1f6 100644 --- a/src/test/compile-fail/const-eval-overflow-4b.rs +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -20,8 +20,9 @@ use std::{u8, u16, u32, u64, usize}; const A_I8_T : [u32; (i8::MAX as i8 + 1u8) as usize] - //~^ ERROR constant evaluation error [E0080] + //~^ ERROR mismatched types //~| expected i8, found u8 + //~| ERROR the trait bound `i8: std::ops::Add` is not satisfied = [0; (i8::MAX as usize) + 1]; @@ -32,8 +33,7 @@ const A_CHAR_USIZE const A_BAD_CHAR_USIZE : [u32; 5i8 as char as usize] - //~^ ERROR constant evaluation error - //~| only `u8` can be cast as `char`, not `i8` + //~^ ERROR only `u8` can be cast as `char`, not `i8` = [0; 5]; fn main() {} diff --git a/src/test/compile-fail/const-eval-span.rs b/src/test/compile-fail/const-eval-span.rs index 73351429b5060..16f89606b01e6 100644 --- a/src/test/compile-fail/const-eval-span.rs +++ b/src/test/compile-fail/const-eval-span.rs @@ -14,12 +14,13 @@ struct S(i32); const CONSTANT: S = S(0); -//~^ ERROR E0080 -//~| unimplemented constant expression: tuple struct constructors enum E { V = CONSTANT, - //~^ NOTE: for enum discriminant here + //~^ ERROR mismatched types + //~| expected isize, found struct `S` + //~| NOTE expected type `isize` + //~| found type `S` } fn main() {} diff --git a/src/test/compile-fail/const-integer-bool-ops.rs b/src/test/compile-fail/const-integer-bool-ops.rs index 398dc2f22150c..29bc665a22e7b 100644 --- a/src/test/compile-fail/const-integer-bool-ops.rs +++ b/src/test/compile-fail/const-integer-bool-ops.rs @@ -8,52 +8,71 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const X: usize = 42 && 39; //~ ERROR E0080 - //~| can't do this op on integrals -const ARR: [i32; X] = [99; 34]; //~ NOTE: for array length here +const X: usize = 42 && 39; +//~^ ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected usize, found bool +const ARR: [i32; X] = [99; 34]; -const X1: usize = 42 || 39; //~ ERROR E0080 - //~| can't do this op on integrals -const ARR1: [i32; X1] = [99; 47]; //~ NOTE: for array length here +const X1: usize = 42 || 39; +//~^ ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected usize, found bool +const ARR1: [i32; X1] = [99; 47]; -const X2: usize = -42 || -39; //~ ERROR E0080 - //~| unary negation of unsigned integer -const ARR2: [i32; X2] = [99; 18446744073709551607]; //~ NOTE: for array length here +const X2: usize = -42 || -39; +//~^ ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected usize, found bool +const ARR2: [i32; X2] = [99; 18446744073709551607]; -const X3: usize = -42 && -39; //~ ERROR E0080 - //~| unary negation of unsigned integer -const ARR3: [i32; X3] = [99; 6]; //~ NOTE: for array length here +const X3: usize = -42 && -39; +//~^ ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected bool, found integral variable +//~| ERROR mismatched types +//~| expected usize, found bool +const ARR3: [i32; X3] = [99; 6]; const Y: usize = 42.0 == 42.0; +//~^ ERROR mismatched types +//~| expected usize, found bool const ARRR: [i32; Y] = [99; 1]; -//~^ ERROR: expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` const Y1: usize = 42.0 >= 42.0; -const ARRR1: [i32; Y] = [99; 1]; -//~^ ERROR: expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` +//~^ ERROR mismatched types +//~| expected usize, found bool +const ARRR1: [i32; Y1] = [99; 1]; const Y2: usize = 42.0 <= 42.0; -const ARRR2: [i32; Y] = [99; 1]; -//~^ ERROR: expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` +//~^ ERROR mismatched types +//~| expected usize, found bool +const ARRR2: [i32; Y2] = [99; 1]; const Y3: usize = 42.0 > 42.0; -const ARRR3: [i32; Y] = [99; 0]; -//~^ ERROR: expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` +//~^ ERROR mismatched types +//~| expected usize, found bool +const ARRR3: [i32; Y3] = [99; 0]; const Y4: usize = 42.0 < 42.0; -const ARRR4: [i32; Y] = [99; 0]; -//~^ ERROR: expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` +//~^ ERROR mismatched types +//~| expected usize, found bool +const ARRR4: [i32; Y4] = [99; 0]; const Y5: usize = 42.0 != 42.0; -const ARRR5: [i32; Y] = [99; 0]; -//~^ ERROR: expected `usize` for array length, found boolean [E0306] -//~| NOTE expected `usize` - +//~^ ERROR mismatched types +//~| expected usize, found bool +const ARRR5: [i32; Y5] = [99; 0]; fn main() { let _ = ARR; diff --git a/src/test/compile-fail/const-tup-index-span.rs b/src/test/compile-fail/const-tup-index-span.rs index f3fb92e2b2206..b42c440f87d74 100644 --- a/src/test/compile-fail/const-tup-index-span.rs +++ b/src/test/compile-fail/const-tup-index-span.rs @@ -11,8 +11,8 @@ // Test spans of errors const TUP: (usize,) = 5usize << 64; -//~^ ERROR E0080 -//~| attempt to shift left with overflow +//~^ ERROR mismatched types +//~| expected tuple, found usize const ARR: [i32; TUP.0] = []; fn main() { diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs index c73b7e831b321..62e54c3f23773 100644 --- a/src/test/compile-fail/discrim-ill-typed.rs +++ b/src/test/compile-fail/discrim-ill-typed.rs @@ -25,7 +25,7 @@ fn f_i8() { Ok = i8::MAX - 1, Ok2, OhNo = 0_u8, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected i8, found u8 } @@ -38,7 +38,7 @@ fn f_u8() { Ok = u8::MAX - 1, Ok2, OhNo = 0_i8, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected u8, found i8 } @@ -51,7 +51,7 @@ fn f_i16() { Ok = i16::MAX - 1, Ok2, OhNo = 0_u16, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected i16, found u16 } @@ -64,7 +64,7 @@ fn f_u16() { Ok = u16::MAX - 1, Ok2, OhNo = 0_i16, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected u16, found i16 } @@ -77,7 +77,7 @@ fn f_i32() { Ok = i32::MAX - 1, Ok2, OhNo = 0_u32, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected i32, found u32 } @@ -90,7 +90,7 @@ fn f_u32() { Ok = u32::MAX - 1, Ok2, OhNo = 0_i32, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected u32, found i32 } @@ -103,7 +103,7 @@ fn f_i64() { Ok = i64::MAX - 1, Ok2, OhNo = 0_u64, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected i64, found u64 } @@ -116,7 +116,7 @@ fn f_u64() { Ok = u64::MAX - 1, Ok2, OhNo = 0_i64, - //~^ ERROR E0080 + //~^ ERROR mismatched types //~| expected u64, found i64 } diff --git a/src/test/compile-fail/enum-discrim-too-small.rs b/src/test/compile-fail/enum-discrim-too-small.rs index bbdb3891d9980..393a67be57fe6 100644 --- a/src/test/compile-fail/enum-discrim-too-small.rs +++ b/src/test/compile-fail/enum-discrim-too-small.rs @@ -13,32 +13,32 @@ enum Eu8 { Au8 = 23, Bu8 = 223, - Cu8 = -23, //~ ERROR E0080 - //~| unary negation of unsigned integer + Cu8 = -23, + //~^ ERROR cannot apply unary operator `-` to type `u8` } #[repr(u16)] enum Eu16 { Au16 = 23, Bu16 = 55555, - Cu16 = -22333, //~ ERROR E0080 - //~| unary negation of unsigned integer + Cu16 = -22333, + //~^ ERROR cannot apply unary operator `-` to type `u16` } #[repr(u32)] enum Eu32 { Au32 = 23, Bu32 = 3_000_000_000, - Cu32 = -2_000_000_000, //~ ERROR E0080 - //~| unary negation of unsigned integer + Cu32 = -2_000_000_000, + //~^ ERROR cannot apply unary operator `-` to type `u32` } #[repr(u64)] enum Eu64 { Au32 = 23, Bu32 = 3_000_000_000, - Cu32 = -2_000_000_000, //~ ERROR E0080 - //~| unary negation of unsigned integer + Cu32 = -2_000_000_000, + //~^ ERROR cannot apply unary operator `-` to type `u64` } // u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a diff --git a/src/test/compile-fail/invalid-path-in-const.rs b/src/test/compile-fail/invalid-path-in-const.rs index 9a9358b787f53..ab839e7630de9 100644 --- a/src/test/compile-fail/invalid-path-in-const.rs +++ b/src/test/compile-fail/invalid-path-in-const.rs @@ -10,6 +10,5 @@ fn main() { fn f(a: [u8; u32::DOESNOTEXIST]) {} - //~^ ERROR constant evaluation error - //~| unresolved path in constant expression + //~^ ERROR no associated item named `DOESNOTEXIST` found for type `u32` } diff --git a/src/test/compile-fail/issue-22933-2.rs b/src/test/compile-fail/issue-22933-2.rs index 54a2408935461..c78e1f7f53095 100644 --- a/src/test/compile-fail/issue-22933-2.rs +++ b/src/test/compile-fail/issue-22933-2.rs @@ -12,12 +12,10 @@ enum Delicious { Pie = 0x1, Apple = 0x2, ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, - //~^ ERROR constant evaluation error - //~| unresolved path in constant expression + //~^ ERROR no associated item named `PIE` found for type `Delicious` } const FOO: [u32; u8::MIN as usize] = []; -//~^ ERROR constant evaluation error -//~| unresolved path in constant expression +//~^ ERROR no associated item named `MIN` found for type `u8` fn main() {} diff --git a/src/test/compile-fail/issue-23217.rs b/src/test/compile-fail/issue-23217.rs index c2bcbb9d54a9a..95f6526f11559 100644 --- a/src/test/compile-fail/issue-23217.rs +++ b/src/test/compile-fail/issue-23217.rs @@ -10,8 +10,7 @@ pub enum SomeEnum { B = SomeEnum::A, - //~^ ERROR constant evaluation error - //~| unresolved path in constant expression + //~^ ERROR no associated item named `A` found for type `SomeEnum` } fn main() {} diff --git a/src/test/compile-fail/issue-28586.rs b/src/test/compile-fail/issue-28586.rs index 1dfd146985ff4..b8571d2e85e2c 100644 --- a/src/test/compile-fail/issue-28586.rs +++ b/src/test/compile-fail/issue-28586.rs @@ -11,6 +11,7 @@ // Regression test for issue #28586 pub trait Foo {} -impl Foo for [u8; usize::BYTES] {} //~ ERROR E0080 +impl Foo for [u8; usize::BYTES] {} +//~^ ERROR no associated item named `BYTES` found for type `usize` fn main() { } diff --git a/src/test/compile-fail/issue-31910.rs b/src/test/compile-fail/issue-31910.rs index 65fcd7df77ebe..aac8b89e882b3 100644 --- a/src/test/compile-fail/issue-31910.rs +++ b/src/test/compile-fail/issue-31910.rs @@ -11,7 +11,9 @@ #![feature(associated_consts)] enum Enum { - X = Trait::Number, //~ ERROR constant evaluation error + X = Trait::Number, + //~^ ERROR mismatched types + //~| expected isize, found i32 } trait Trait { diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs index e2acdcee3de8f..78af11a0b5813 100644 --- a/src/test/compile-fail/issue-3521.rs +++ b/src/test/compile-fail/issue-3521.rs @@ -15,9 +15,7 @@ fn main() { enum Stuff { Bar = foo //~^ ERROR attempt to use a non-constant value in a constant - //~^^ ERROR constant evaluation error - //~| unresolved path in constant expression } - println!("{}", Stuff::Bar); + println!("{:?}", Stuff::Bar); } diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs index a56a5e8548944..bc492806b96c1 100644 --- a/src/test/compile-fail/issue-39559.rs +++ b/src/test/compile-fail/issue-39559.rs @@ -23,9 +23,13 @@ impl Dim for Dim3 { pub struct Vector { entries: [T; D::dim()] //~^ ERROR cannot use an outer type parameter in this context - //~| ERROR constant evaluation error } fn main() { - let array: [usize; Dim3::dim()] = [0; Dim3::dim()]; + let array: [usize; Dim3::dim()] + //~^ ERROR constant evaluation error + //~| non-constant path in constant expression + = [0; Dim3::dim()]; + //~^ ERROR constant evaluation error + //~| non-constant path in constant expression } diff --git a/src/test/compile-fail/issue-8761.rs b/src/test/compile-fail/issue-8761.rs index 91a07dd9ba6dd..f8424ea64ef9e 100644 --- a/src/test/compile-fail/issue-8761.rs +++ b/src/test/compile-fail/issue-8761.rs @@ -10,10 +10,10 @@ enum Foo { A = 1i64, - //~^ ERROR constant evaluation error + //~^ ERROR mismatched types //~| expected isize, found i64 B = 2u8 - //~^ ERROR constant evaluation error + //~^ ERROR mismatched types //~| expected isize, found u8 } diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index 691d8d31b412d..52cd4e8a3ed95 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -14,6 +14,5 @@ fn main() { fn bar(n: isize) { let _x: [isize; n]; //~^ ERROR attempt to use a non-constant value in a constant [E0435] - //~| ERROR constant evaluation error [E0080] } } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index f4769a7858728..1eda508778402 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -15,7 +15,5 @@ fn main() { let _x = [0; n]; //~^ ERROR attempt to use a non-constant value in a constant [E0435] //~| NOTE non-constant used with constant - //~| NOTE unresolved path in constant expression - //~| ERROR constant evaluation error [E0080] } } diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index 0e8971269b007..6e80a9174676a 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -17,7 +17,7 @@ fn main() { // END RUST SOURCE // START rustc.node4.SimplifyBranches.initial-before.mir // bb0: { -// switchInt(const false) -> [0: bb2, otherwise: bb1]; +// switchInt(const false) -> [0u8: bb2, otherwise: bb1]; // } // END rustc.node4.SimplifyBranches.initial-before.mir // START rustc.node4.SimplifyBranches.initial-after.mir diff --git a/src/test/compile-fail/issue-25145.rs b/src/test/run-pass/issue-25145.rs similarity index 86% rename from src/test/compile-fail/issue-25145.rs rename to src/test/run-pass/issue-25145.rs index 93f75e9bfed0d..6f02f2783818e 100644 --- a/src/test/compile-fail/issue-25145.rs +++ b/src/test/run-pass/issue-25145.rs @@ -17,7 +17,7 @@ impl S { } static STUFF: [u8; S::N] = [0; S::N]; -//~^ ERROR constant evaluation error -//~| unresolved path in constant expression -fn main() {} +fn main() { + assert_eq!(STUFF, [0; 3]); +} diff --git a/src/test/compile-fail/E0079.rs b/src/test/run-pass/issue-39548.rs similarity index 75% rename from src/test/compile-fail/E0079.rs rename to src/test/run-pass/issue-39548.rs index c9b7f549d5aaa..7da50670d1dee 100644 --- a/src/test/compile-fail/E0079.rs +++ b/src/test/run-pass/issue-39548.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum Foo { - Q = "32" //~ ERROR E0079 - //~^ expected 'isize' type -} +type Array = [(); ((1 < 2) == false) as usize]; fn main() { + let _: Array = []; } diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index d01ffcb2839b4..c7c42bcf23940 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -46,11 +46,5 @@ error[E0425]: cannot find value `second` in module `m` 32 | let b: m::first = m::second; // Misspelled item in module. | ^^^^^^^^^ did you mean `m::Second`? -error[E0080]: constant evaluation error - --> $DIR/levenshtein.rs:30:20 - | -30 | let v = [0u32; MAXITEM]; // Misspelled constant name. - | ^^^^^^^ unresolved path in constant expression - -error: aborting due to previous error +error: aborting due to 8 previous errors From d9f0a949fd6b74641b12afc0f8a17f00919ebcef Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 20 Feb 2017 03:55:28 +0200 Subject: [PATCH 16/17] rustc_const_eval: demand that the MIR qualify_consts ran on each evaluated body. --- src/librustc/ty/maps.rs | 5 + src/librustc_const_eval/eval.rs | 3 +- src/librustc_driver/driver.rs | 5 +- src/librustc_metadata/cstore_impl.rs | 1 + src/librustc_metadata/decoder.rs | 17 +- src/librustc_metadata/encoder.rs | 13 +- src/librustc_metadata/schema.rs | 4 +- src/librustc_mir/lib.rs | 6 + src/librustc_mir/transform/qualify_consts.rs | 147 +++++++++--------- .../const-block-non-item-statement-2.rs | 26 ++++ .../const-block-non-item-statement.rs | 21 +-- src/test/compile-fail/const-call.rs | 6 +- src/test/compile-fail/issue-39559.rs | 6 +- 13 files changed, 148 insertions(+), 112 deletions(-) create mode 100644 src/test/compile-fail/const-block-non-item-statement-2.rs diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index b79ab2a26fdc9..fd1403b15bc89 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -361,6 +361,11 @@ define_maps! { <'tcx> /// (in the `RefCell` sense) to prevent accidental mutation. pub mir: Mir(DefId) -> &'tcx RefCell>, + /// Maps DefId's that have an associated Mir to the result + /// of the MIR qualify_consts pass. The actual meaning of + /// the value isn't known except to the pass itself. + pub mir_const_qualif: Mir(DefId) -> u8, + /// Records the type of each closure. The def ID is the ID of the /// expression defining the closure. pub closure_kind: ItemSignature(DefId) -> ty::ClosureKind, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 284991a11b1b9..c5d577ce571d4 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -27,7 +27,7 @@ use rustc::util::nodemap::DefIdMap; use graphviz::IntoCow; use syntax::ast; use rustc::hir::{self, Expr}; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; use std::borrow::Cow; use std::cmp::Ordering; @@ -228,6 +228,7 @@ pub struct ConstContext<'a, 'tcx: 'a> { impl<'a, 'tcx> ConstContext<'a, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { let def_id = tcx.hir.body_owner_def_id(body); + ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); ConstContext::with_tables(tcx, tcx.item_tables(def_id)) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 96824d19b900d..ddf09f5cfe0e0 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -872,7 +872,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let index = stability::Index::new(&hir_map); let mut local_providers = ty::maps::Providers::default(); - mir::mir_map::provide(&mut local_providers); + mir::provide(&mut local_providers); typeck::provide(&mut local_providers); let mut extern_providers = ty::maps::Providers::default(); @@ -958,8 +958,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // in stage 4 below. passes.push_hook(box mir::transform::dump_mir::DumpMir); passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial")); - passes.push_pass( - box mir::transform::qualify_consts::QualifyAndPromoteConstants::default()); + passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants); passes.push_pass(box mir::transform::type_check::TypeckMir); passes.push_pass( box mir::transform::simplify_branches::SimplifyBranches::new("initial")); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 443e75e63d3dd..7b02280ef904b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -101,6 +101,7 @@ provide! { <'tcx> tcx, def_id, cdata mir } + mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } typeck_tables => { cdata.item_body_tables(def_id.index, tcx) } closure_kind => { cdata.closure_kind(def_id.index) } closure_type => { cdata.closure_ty(def_id.index, tcx) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1627b22cd5fa1..b4b9966cbe47b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -411,8 +411,8 @@ impl<'a, 'tcx> MetadataBlob { impl<'tcx> EntryKind<'tcx> { fn to_def(&self, did: DefId) -> Option { Some(match *self { - EntryKind::Const => Def::Const(did), - EntryKind::AssociatedConst(_) => Def::AssociatedConst(did), + EntryKind::Const(_) => Def::Const(did), + EntryKind::AssociatedConst(..) => Def::AssociatedConst(did), EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Def::Static(did, false), EntryKind::MutStatic | @@ -825,6 +825,17 @@ impl<'a, 'tcx> CrateMetadata { } } + pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { + match self.entry(id).kind { + EntryKind::Const(qualif) | + EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) | + EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => { + qualif + } + _ => bug!(), + } + } + pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem { let item = self.entry(id); let def_key = self.def_key(id); @@ -832,7 +843,7 @@ impl<'a, 'tcx> CrateMetadata { let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); let (kind, container, has_self) = match item.kind { - EntryKind::AssociatedConst(container) => { + EntryKind::AssociatedConst(container, _) => { (ty::AssociatedKind::Const, container, false) } EntryKind::Method(data) => { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e73700f04fa4e..af0edab7a83bd 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -457,7 +457,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; let kind = match trait_item.kind { - ty::AssociatedKind::Const => EntryKind::AssociatedConst(container), + ty::AssociatedKind::Const => { + EntryKind::AssociatedConst(container, 0) + } ty::AssociatedKind::Method => { let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { let arg_names = match *m { @@ -533,7 +535,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; let kind = match impl_item.kind { - ty::AssociatedKind::Const => EntryKind::AssociatedConst(container), + ty::AssociatedKind::Const => { + EntryKind::AssociatedConst(container, + ty::queries::mir_const_qualif::get(self.tcx, ast_item.span, def_id)) + } ty::AssociatedKind::Method => { let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { FnData { @@ -637,7 +642,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let kind = match item.node { hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic, - hir::ItemConst(..) => EntryKind::Const, + hir::ItemConst(..) => { + EntryKind::Const(ty::queries::mir_const_qualif::get(tcx, item.span, def_id)) + } hir::ItemFn(_, _, constness, .., body) => { let data = FnData { constness: constness, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 26d907523a886..4a20913d0b3fd 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -221,7 +221,7 @@ pub struct Entry<'tcx> { #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum EntryKind<'tcx> { - Const, + Const(u8), ImmStatic, MutStatic, ForeignImmStatic, @@ -243,7 +243,7 @@ pub enum EntryKind<'tcx> { DefaultImpl(Lazy>), Method(Lazy), AssociatedType(AssociatedContainer), - AssociatedConst(AssociatedContainer), + AssociatedConst(AssociatedContainer, u8), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 9a8fb1099d04b..a97495a0ebcc4 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -53,3 +53,9 @@ pub mod mir_map; pub mod pretty; pub mod transform; +use rustc::ty::maps::Providers; + +pub fn provide(providers: &mut Providers) { + mir_map::provide(providers); + transform::qualify_consts::provide(providers); +} diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 9f38564d1e2f3..441a9add883dd 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -16,24 +16,24 @@ use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::hir::map::blocks::FnLikeNode; use rustc::traits::{self, Reveal}; -use rustc::ty::{self, TyCtxt, Ty}; +use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; +use rustc::ty::maps::Providers; use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; -use rustc::mir::transform::{Pass, MirPass, MirSource}; +use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; -use rustc::util::nodemap::DefIdMap; use rustc::middle::lang_items; use syntax::abi::Abi; use syntax::feature_gate::UnstableFeatures; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; -use std::collections::hash_map::Entry; use std::fmt; use std::usize; @@ -41,36 +41,32 @@ use super::promote_consts::{self, Candidate, TempState}; bitflags! { flags Qualif: u8 { - // Const item's qualification while recursing. - // Recursive consts are an error. - const RECURSIVE = 1 << 0, - // Constant containing interior mutability (UnsafeCell). - const MUTABLE_INTERIOR = 1 << 1, + const MUTABLE_INTERIOR = 1 << 0, // Constant containing an ADT that implements Drop. - const NEEDS_DROP = 1 << 2, + const NEEDS_DROP = 1 << 1, // Function argument. - const FN_ARGUMENT = 1 << 3, + const FN_ARGUMENT = 1 << 2, // Static lvalue or move from a static. - const STATIC = 1 << 4, + const STATIC = 1 << 3, // Reference to a static. - const STATIC_REF = 1 << 5, + const STATIC_REF = 1 << 4, // Not constant at all - non-`const fn` calls, asm!, // pointer comparisons, ptr-to-int casts, etc. - const NOT_CONST = 1 << 6, + const NOT_CONST = 1 << 5, // Refers to temporaries which cannot be promoted as // promote_consts decided they weren't simple enough. - const NOT_PROMOTABLE = 1 << 7, + const NOT_PROMOTABLE = 1 << 6, // Borrows of temporaries can be promoted only // if they have none of the above qualifications. - const NEVER_PROMOTE = !0, + const NEVER_PROMOTE = 0b111_1111, // Const items can only have MUTABLE_INTERIOR // and NOT_PROMOTABLE without producing an error. @@ -134,7 +130,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { rpo: ReversePostorder<'a, 'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>, - qualif_map: &'a mut DefIdMap, temp_qualif: IndexVec>, return_qualif: Option, qualif: Qualif, @@ -146,7 +141,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>, - qualif_map: &'a mut DefIdMap, def_id: DefId, mir: &'a Mir<'tcx>, mode: Mode) @@ -162,7 +156,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { rpo: rpo, tcx: tcx, param_env: param_env, - qualif_map: qualif_map, temp_qualif: IndexVec::from_elem(None, &mir.local_decls), return_qualif: None, qualif: Qualif::empty(), @@ -585,17 +578,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if substs.types().next().is_some() { self.add_type(constant.ty); } else { - let qualif = qualify_const_item_cached(self.tcx, - self.qualif_map, - def_id); - self.add(qualif); - } + let bits = ty::queries::mir_const_qualif::get(self.tcx, + constant.span, + def_id); - // FIXME(eddyb) check recursive constants here, - // instead of rustc_passes::static_recursion. - if self.qualif.intersects(Qualif::RECURSIVE) { - span_bug!(constant.span, - "recursive constant wasn't caught earlier"); + let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif"); + self.add(qualif); } // Let `const fn` transitively have destructors, @@ -944,41 +932,64 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } -fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - qualif_map: &mut DefIdMap, - def_id: DefId) - -> Qualif { - match qualif_map.entry(def_id) { - Entry::Occupied(entry) => return *entry.get(), - Entry::Vacant(entry) => { - // Guard against `const` recursion. - entry.insert(Qualif::RECURSIVE); - } +pub fn provide(providers: &mut Providers) { + providers.mir_const_qualif = qualify_const_item; +} + +fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> u8 { + let mir = &tcx.item_mir(def_id); + if mir.return_ty.references_error() { + return Qualif::NOT_CONST.bits(); } - let param_env = if def_id.is_local() { - let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); - ty::ParameterEnvironment::for_item(tcx, node_id) - } else { - // These should only be monomorphic constants. - tcx.empty_parameter_environment() - }; + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let param_env = ty::ParameterEnvironment::for_item(tcx, node_id); - let mir = &tcx.item_mir(def_id); - let mut qualifier = Qualifier::new(tcx, param_env, qualif_map, def_id, mir, Mode::Const); - let qualif = qualifier.qualify_const(); - qualifier.qualif_map.insert(def_id, qualif); - qualif + let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const); + qualifier.qualify_const().bits() } -#[derive(Default)] -pub struct QualifyAndPromoteConstants { - qualif_map: DefIdMap -} +pub struct QualifyAndPromoteConstants; impl Pass for QualifyAndPromoteConstants {} -impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { +impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants { + fn run_pass<'a>(&mut self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + hooks: &mut [Box MirPassHook<'s>>]) + { + let def_ids = tcx.maps.mir.borrow().keys(); + for def_id in def_ids { + if !def_id.is_local() { + continue; + } + + let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id)); + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let src = MirSource::from_node(tcx, id); + + if let MirSource::Const(_) = src { + ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); + continue; + } + + let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut(); + tcx.dep_graph.write(DepNode::Mir(def_id)); + + for hook in &mut *hooks { + hook.on_mir_pass(tcx, src, mir, self, false); + } + self.run_pass(tcx, src, mir); + for hook in &mut *hooks { + hook.on_mir_pass(tcx, src, mir, self, true); + } + } + } +} + +impl<'tcx> QualifyAndPromoteConstants { fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { let id = src.item_id(); @@ -991,18 +1002,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { Mode::Fn } } - MirSource::Const(_) => { - match self.qualif_map.entry(def_id) { - Entry::Occupied(_) => return, - Entry::Vacant(entry) => { - // Guard against `const` recursion. - entry.insert(Qualif::RECURSIVE); - Mode::Const - } - } - } MirSource::Static(_, hir::MutImmutable) => Mode::Static, MirSource::Static(_, hir::MutMutable) => Mode::StaticMut, + MirSource::Const(_) | MirSource::Promoted(..) => return }; let param_env = ty::ParameterEnvironment::for_item(tcx, id); @@ -1012,7 +1014,6 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { // which can't be mutated until its scope ends. let (temps, candidates) = { let mut qualifier = Qualifier::new(tcx, param_env, - &mut self.qualif_map, def_id, mir, mode); if mode == Mode::ConstFn { // Enforce a constant-like CFG for `const fn`. @@ -1029,14 +1030,8 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { // Do the actual promotion, now that we know what's viable. promote_consts::promote_candidates(mir, tcx, temps, candidates); } else { - let mut qualifier = Qualifier::new(tcx, param_env, - &mut self.qualif_map, - def_id, mir, mode); - let qualif = qualifier.qualify_const(); - - if mode == Mode::Const { - qualifier.qualif_map.insert(def_id, qualif); - } + let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, mode); + qualifier.qualify_const(); } // Statics must be Sync. diff --git a/src/test/compile-fail/const-block-non-item-statement-2.rs b/src/test/compile-fail/const-block-non-item-statement-2.rs new file mode 100644 index 0000000000000..83166c9bd4b5e --- /dev/null +++ b/src/test/compile-fail/const-block-non-item-statement-2.rs @@ -0,0 +1,26 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const A: usize = { 1; 2 }; +//~^ ERROR: blocks in constants are limited to items and tail expressions + +const B: usize = { { } 2 }; +//~^ ERROR: blocks in constants are limited to items and tail expressions + +macro_rules! foo { + () => (()) //~ ERROR: blocks in constants are limited to items and tail expressions +} +const C: usize = { foo!(); 2 }; + +const D: usize = { let x = 4; 2 }; +//~^ ERROR: blocks in constants are limited to items and tail expressions +//~^^ ERROR: blocks in constants are limited to items and tail expressions + +pub fn main() {} diff --git a/src/test/compile-fail/const-block-non-item-statement.rs b/src/test/compile-fail/const-block-non-item-statement.rs index edb85023c9ba7..bdc69c937c637 100644 --- a/src/test/compile-fail/const-block-non-item-statement.rs +++ b/src/test/compile-fail/const-block-non-item-statement.rs @@ -8,21 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const A: usize = { 1; 2 }; -//~^ ERROR: blocks in constants are limited to items and tail expressions - -const B: usize = { { } 2 }; -//~^ ERROR: blocks in constants are limited to items and tail expressions - -macro_rules! foo { - () => (()) //~ ERROR: blocks in constants are limited to items and tail expressions -} -const C: usize = { foo!(); 2 }; - -const D: usize = { let x = 4; 2 }; -//~^ ERROR: blocks in constants are limited to items and tail expressions -//~^^ ERROR: blocks in constants are limited to items and tail expressions - enum Foo { Bar = { let x = 1; 3 } //~^ ERROR: blocks in constants are limited to items and tail expressions @@ -33,8 +18,4 @@ type Array = [u32; { let x = 2; 5 }]; //~^ ERROR: blocks in constants are limited to items and tail expressions //~^^ ERROR: blocks in constants are limited to items and tail expressions -pub fn main() { - let _: Array = [0; { let x = 3; 5 }]; - //~^ ERROR: blocks in constants are limited to items and tail expressions - //~^^ ERROR: blocks in constants are limited to items and tail expressions -} +pub fn main() {} diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs index 7e2eabf412d6c..ff83dd004a257 100644 --- a/src/test/compile-fail/const-call.rs +++ b/src/test/compile-fail/const-call.rs @@ -15,6 +15,8 @@ fn f(x: usize) -> usize { } fn main() { - let _ = [0; f(2)]; //~ ERROR constant evaluation error [E0080] - //~| non-constant path in constant expression + let _ = [0; f(2)]; + //~^ ERROR calls in constants are limited to constant functions + //~| ERROR constant evaluation error [E0080] + //~| non-constant path in constant expression } diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs index bc492806b96c1..06e8406cbc0bd 100644 --- a/src/test/compile-fail/issue-39559.rs +++ b/src/test/compile-fail/issue-39559.rs @@ -27,9 +27,11 @@ pub struct Vector { fn main() { let array: [usize; Dim3::dim()] - //~^ ERROR constant evaluation error + //~^ ERROR calls in constants are limited to constant functions + //~| ERROR constant evaluation error //~| non-constant path in constant expression = [0; Dim3::dim()]; - //~^ ERROR constant evaluation error + //~^ ERROR calls in constants are limited to constant functions + //~| ERROR constant evaluation error //~| non-constant path in constant expression } From f702b20dfd22990a326af9221cb3ed9b389c8307 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 10 Jun 2016 13:00:21 +0300 Subject: [PATCH 17/17] rustc_save_analysis: don't pollute the codemap with fake files. --- src/librustc_save_analysis/span_utils.rs | 67 ++++++------------------ src/libsyntax/parse/lexer/mod.rs | 46 +++++++++++++--- 2 files changed, 54 insertions(+), 59 deletions(-) diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 89525b27ed36a..b5add6404fc9f 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -17,7 +17,6 @@ use std::env; use std::path::Path; use syntax::ast; -use syntax::parse::filemap_to_tts; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; use syntax::symbol::keywords; @@ -49,23 +48,6 @@ impl<'a> SpanUtils<'a> { } } - // sub_span starts at span.lo, so we need to adjust the positions etc. - // If sub_span is None, we don't need to adjust. - pub fn make_sub_span(&self, span: Span, sub_span: Option) -> Option { - match sub_span { - None => None, - Some(sub) => { - let FileMapAndBytePos {fm, pos} = self.sess.codemap().lookup_byte_offset(span.lo); - let base = pos + fm.start_pos; - Some(Span { - lo: base + self.sess.codemap().lookup_byte_offset(sub.lo).pos, - hi: base + self.sess.codemap().lookup_byte_offset(sub.hi).pos, - expn_id: span.expn_id, - }) - } - } - } - pub fn snippet(&self, span: Span) -> String { match self.sess.codemap().span_to_snippet(span) { Ok(s) => s, @@ -74,24 +56,7 @@ impl<'a> SpanUtils<'a> { } pub fn retokenise_span(&self, span: Span) -> StringReader<'a> { - // sadness - we don't have spans for sub-expressions nor access to the tokens - // so in order to get extents for the function name itself (which dxr expects) - // we need to re-tokenise the fn definition - - // Note: this is a bit awful - it adds the contents of span to the end of - // the codemap as a new filemap. This is mostly OK, but means we should - // not iterate over the codemap. Also, any spans over the new filemap - // are incompatible with spans over other filemaps. - let filemap = self.sess - .codemap() - .new_filemap(String::from(""), None, self.snippet(span)); - lexer::StringReader::new(&self.sess.parse_sess, filemap) - } - - fn span_to_tts(&self, span: Span) -> Vec { - let filename = String::from(""); - let filemap = self.sess.codemap().new_filemap(filename, None, self.snippet(span)); - filemap_to_tts(&self.sess.parse_sess, filemap) + lexer::StringReader::retokenize(&self.sess.parse_sess, span) } // Re-parses a path and returns the span for the last identifier in the path @@ -103,7 +68,7 @@ impl<'a> SpanUtils<'a> { loop { let ts = toks.real_token(); if ts.tok == token::Eof { - return self.make_sub_span(span, result) + return result } if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { result = Some(ts.sp); @@ -128,7 +93,7 @@ impl<'a> SpanUtils<'a> { return None; } if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { - return self.make_sub_span(span, Some(ts.sp)); + return Some(ts.sp); } bracket_count += match ts.tok { @@ -178,10 +143,7 @@ impl<'a> SpanUtils<'a> { } prev = next; } - if result.is_none() && prev_span.is_some() { - return self.make_sub_span(span, prev_span); - } - return self.make_sub_span(span, result); + result.or(prev_span) } // Return the span for the last ident before a `<` and outside any @@ -241,9 +203,9 @@ impl<'a> SpanUtils<'a> { loc.line); } if result.is_none() && prev.tok.is_ident() && angle_count == 0 { - return self.make_sub_span(span, Some(prev.sp)); + return Some(prev.sp); } - self.make_sub_span(span, result) + result } // Reparse span and return an owned vector of sub spans of the first limit @@ -310,7 +272,7 @@ impl<'a> SpanUtils<'a> { angle_count += 1; } if ts.tok.is_ident() && angle_count == nesting { - result.push(self.make_sub_span(span, Some(ts.sp)).unwrap()); + result.push(ts.sp); } } } @@ -320,8 +282,11 @@ impl<'a> SpanUtils<'a> { /// end of the 'signature' part, that is up to, but not including an opening /// brace or semicolon. pub fn signature_string_for_span(&self, span: Span) -> String { - let mut toks = self.span_to_tts(span).into_iter(); + let mut toks = self.retokenise_span(span); + toks.real_token(); + let mut toks = toks.parse_all_token_trees().unwrap().into_iter(); let mut prev = toks.next().unwrap(); + let first_span = prev.get_span(); let mut angle_count = 0; for tok in toks { @@ -360,7 +325,7 @@ impl<'a> SpanUtils<'a> { } let next = toks.real_token(); if next.tok == tok { - return self.make_sub_span(span, Some(prev.sp)); + return Some(prev.sp); } prev = next; } @@ -374,7 +339,7 @@ impl<'a> SpanUtils<'a> { return None; } if next.tok == tok { - return self.make_sub_span(span, Some(next.sp)); + return Some(next.sp); } } } @@ -399,7 +364,7 @@ impl<'a> SpanUtils<'a> { if ts.tok == token::Eof { return None } else { - return self.make_sub_span(span, Some(ts.sp)); + return Some(ts.sp); } } } @@ -444,7 +409,7 @@ impl<'a> SpanUtils<'a> { if ts.tok == token::Not { let ts = toks.real_token(); if ts.tok.is_ident() { - return self.make_sub_span(span, Some(ts.sp)); + return Some(ts.sp); } else { return None; } @@ -463,7 +428,7 @@ impl<'a> SpanUtils<'a> { let ts = toks.real_token(); if ts.tok == token::Not { if prev.tok.is_ident() { - return self.make_sub_span(span, Some(prev.sp)); + return Some(prev.sp); } else { return None; } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 6bc15115b09d3..b7f6e6a2384f7 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -51,10 +51,10 @@ pub struct StringReader<'a> { pub filemap: Rc, /// If Some, stop reading the source at this position (inclusive). pub terminator: Option, - /// Whether to record new-lines in filemap. This is only necessary the first - /// time a filemap is lexed. If part of a filemap is being re-lexed, this - /// should be set to false. - pub save_new_lines: bool, + /// Whether to record new-lines and multibyte chars in filemap. + /// This is only necessary the first time a filemap is lexed. + /// If part of a filemap is being re-lexed, this should be set to false. + pub save_new_lines_and_multibyte: bool, // cached: pub peek_tok: token::Token, pub peek_span: Span, @@ -162,7 +162,7 @@ impl<'a> StringReader<'a> { ch: Some('\n'), filemap: filemap, terminator: None, - save_new_lines: true, + save_new_lines_and_multibyte: true, // dummy values; not read peek_tok: token::Eof, peek_span: syntax_pos::DUMMY_SP, @@ -183,6 +183,31 @@ impl<'a> StringReader<'a> { sr } + pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self { + let begin = sess.codemap().lookup_byte_offset(span.lo); + let end = sess.codemap().lookup_byte_offset(span.hi); + + // Make the range zero-length if the span is invalid. + if span.lo > span.hi || begin.fm.start_pos != end.fm.start_pos { + span.hi = span.lo; + } + + let mut sr = StringReader::new_raw_internal(sess, begin.fm); + + // Seek the lexer to the right byte range. + sr.save_new_lines_and_multibyte = false; + sr.next_pos = span.lo; + sr.terminator = Some(span.hi); + + sr.bump(); + + if let Err(_) = sr.advance_token() { + sr.emit_fatal_errors(); + panic!(FatalError); + } + sr + } + pub fn ch_is(&self, c: char) -> bool { self.ch == Some(c) } @@ -378,7 +403,10 @@ impl<'a> StringReader<'a> { pub fn bump(&mut self) { let new_pos = self.next_pos; let new_byte_offset = self.byte_offset(new_pos).to_usize(); - if new_byte_offset < self.source_text.len() { + let end = self.terminator.map_or(self.source_text.len(), |t| { + self.byte_offset(t).to_usize() + }); + if new_byte_offset < end { let old_ch_is_newline = self.ch.unwrap() == '\n'; let new_ch = char_at(&self.source_text, new_byte_offset); let new_ch_len = new_ch.len_utf8(); @@ -387,7 +415,7 @@ impl<'a> StringReader<'a> { self.pos = new_pos; self.next_pos = new_pos + Pos::from_usize(new_ch_len); if old_ch_is_newline { - if self.save_new_lines { + if self.save_new_lines_and_multibyte { self.filemap.next_line(self.pos); } self.col = CharPos(0); @@ -395,7 +423,9 @@ impl<'a> StringReader<'a> { self.col = self.col + CharPos(1); } if new_ch_len > 1 { - self.filemap.record_multibyte_char(self.pos, new_ch_len); + if self.save_new_lines_and_multibyte { + self.filemap.record_multibyte_char(self.pos, new_ch_len); + } } } else { self.ch = None;