summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-01-16 11:58:00 +0530
committerGitHub <noreply@github.com>2020-01-16 11:58:00 +0530
commit6b83862d09fe3cb04de50c335428b2ac5b2307ce (patch)
tree9b30bcd14b60d27e7ea93048b4d7e7a000615514
parentAuto merge of #67339 - CAD97:rc-provenance, r=sfackler (diff)
parentDo not forget to provide queries. (diff)
downloadrust-6b83862d09fe3cb04de50c335428b2ac5b2307ce.tar.gz
rust-6b83862d09fe3cb04de50c335428b2ac5b2307ce.tar.bz2
rust-6b83862d09fe3cb04de50c335428b2ac5b2307ce.tar.xz
Rollup merge of #67780 - cjgillot:passes-ty, r=Zoxc
Move some queries from rustc::ty to librustc_ty. cc #65031
-rw-r--r--Cargo.lock12
-rw-r--r--src/librustc/ty/mod.rs356
-rw-r--r--src/librustc_interface/Cargo.toml1
-rw-r--r--src/librustc_interface/passes.rs1
-rw-r--r--src/librustc_ty/Cargo.toml16
-rw-r--r--src/librustc_ty/lib.rs25
-rw-r--r--src/librustc_ty/ty.rs369
7 files changed, 426 insertions, 354 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3359fe4..f33d7ff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3652,6 +3652,7 @@ dependencies = [
3652 "rustc_span", 3652 "rustc_span",
3653 "rustc_target", 3653 "rustc_target",
3654 "rustc_traits", 3654 "rustc_traits",
3655 "rustc_ty",
3655 "rustc_typeck", 3656 "rustc_typeck",
3656 "serialize", 3657 "serialize",
3657 "smallvec 1.0.0", 3658 "smallvec 1.0.0",
@@ -3954,6 +3955,17 @@ dependencies = [
3954] 3955]
3955 3956
3956[[package]] 3957[[package]]
3958name = "rustc_ty"
3959version = "0.0.0"
3960dependencies = [
3961 "log",
3962 "rustc",
3963 "rustc_data_structures",
3964 "rustc_hir",
3965 "rustc_span",
3966]
3967
3968[[package]]
3957name = "rustc_typeck" 3969name = "rustc_typeck"
3958version = "0.0.0" 3970version = "0.0.0"
3959dependencies = [ 3971dependencies = [
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index d1e37a4..e6acb6b 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -18,7 +18,6 @@ use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
18use crate::mir::interpret::ErrorHandled; 18use crate::mir::interpret::ErrorHandled;
19use crate::mir::GeneratorLayout; 19use crate::mir::GeneratorLayout;
20use crate::mir::ReadOnlyBodyAndCache; 20use crate::mir::ReadOnlyBodyAndCache;
21use crate::session::CrateDisambiguator;
22use crate::session::DataTypeKind; 21use crate::session::DataTypeKind;
23use crate::traits::{self, Reveal}; 22use crate::traits::{self, Reveal};
24use crate::ty; 23use crate::ty;
@@ -31,7 +30,6 @@ use rustc_data_structures::captures::Captures;
31use rustc_data_structures::fx::FxHashMap; 30use rustc_data_structures::fx::FxHashMap;
32use rustc_data_structures::fx::FxIndexMap; 31use rustc_data_structures::fx::FxIndexMap;
33use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 32use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
34use rustc_data_structures::svh::Svh;
35use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; 33use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
36use rustc_hir as hir; 34use rustc_hir as hir;
37use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; 35use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -2423,70 +2421,6 @@ impl<'tcx> AdtDef {
2423 pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] { 2421 pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
2424 tcx.adt_sized_constraint(self.did).0 2422 tcx.adt_sized_constraint(self.did).0
2425 } 2423 }
2426
2427 fn sized_constraint_for_ty(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
2428 let result = match ty.kind {
2429 Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
2430 | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
2431
2432 Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
2433 // these are never sized - return the target type
2434 vec![ty]
2435 }
2436
2437 Tuple(ref tys) => match tys.last() {
2438 None => vec![],
2439 Some(ty) => self.sized_constraint_for_ty(tcx, ty.expect_ty()),
2440 },
2441
2442 Adt(adt, substs) => {
2443 // recursive case
2444 let adt_tys = adt.sized_constraint(tcx);
2445 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
2446 adt_tys
2447 .iter()
2448 .map(|ty| ty.subst(tcx, substs))
2449 .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
2450 .collect()
2451 }
2452
2453 Projection(..) | Opaque(..) => {
2454 // must calculate explicitly.
2455 // FIXME: consider special-casing always-Sized projections
2456 vec![ty]
2457 }
2458
2459 UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
2460
2461 Param(..) => {
2462 // perf hack: if there is a `T: Sized` bound, then
2463 // we know that `T` is Sized and do not need to check
2464 // it on the impl.
2465
2466 let sized_trait = match tcx.lang_items().sized_trait() {
2467 Some(x) => x,
2468 _ => return vec![ty],
2469 };
2470 let sized_predicate = Binder::dummy(TraitRef {
2471 def_id: sized_trait,
2472 substs: tcx.mk_substs_trait(ty, &[]),
2473 })
2474 .to_predicate();
2475 let predicates = tcx.predicates_of(self.did).predicates;
2476 if predicates.iter().any(|(p, _)| *p == sized_predicate) {
2477 vec![]
2478 } else {
2479 vec![ty]
2480 }
2481 }
2482
2483 Placeholder(..) | Bound(..) | Infer(..) => {
2484 bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
2485 }
2486 };
2487 debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
2488 result
2489 }
2490} 2424}
2491 2425
2492impl<'tcx> FieldDef { 2426impl<'tcx> FieldDef {
@@ -2742,57 +2676,6 @@ impl<'tcx> TyCtxt<'tcx> {
2742 is_associated_item.then(|| self.associated_item(def_id)) 2676 is_associated_item.then(|| self.associated_item(def_id))
2743 } 2677 }
2744 2678
2745 fn associated_item_from_trait_item_ref(
2746 self,
2747 parent_def_id: DefId,
2748 parent_vis: &hir::Visibility<'_>,
2749 trait_item_ref: &hir::TraitItemRef,
2750 ) -> AssocItem {
2751 let def_id = self.hir().local_def_id(trait_item_ref.id.hir_id);
2752 let (kind, has_self) = match trait_item_ref.kind {
2753 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
2754 hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
2755 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
2756 hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
2757 };
2758
2759 AssocItem {
2760 ident: trait_item_ref.ident,
2761 kind,
2762 // Visibility of trait items is inherited from their traits.
2763 vis: Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, self),
2764 defaultness: trait_item_ref.defaultness,
2765 def_id,
2766 container: TraitContainer(parent_def_id),
2767 method_has_self_argument: has_self,
2768 }
2769 }
2770
2771 fn associated_item_from_impl_item_ref(
2772 self,
2773 parent_def_id: DefId,
2774 impl_item_ref: &hir::ImplItemRef<'_>,
2775 ) -> AssocItem {
2776 let def_id = self.hir().local_def_id(impl_item_ref.id.hir_id);
2777 let (kind, has_self) = match impl_item_ref.kind {
2778 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
2779 hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
2780 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
2781 hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
2782 };
2783
2784 AssocItem {
2785 ident: impl_item_ref.ident,
2786 kind,
2787 // Visibility of trait impl items doesn't matter.
2788 vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, self),
2789 defaultness: impl_item_ref.defaultness,
2790 def_id,
2791 container: ImplContainer(parent_def_id),
2792 method_has_self_argument: has_self,
2793 }
2794 }
2795
2796 pub fn field_index(self, hir_id: hir::HirId, tables: &TypeckTables<'_>) -> usize { 2679 pub fn field_index(self, hir_id: hir::HirId, tables: &TypeckTables<'_>) -> usize {
2797 tables.field_indices().get(hir_id).cloned().expect("no index for a field") 2680 tables.field_indices().get(hir_id).cloned().expect("no index for a field")
2798 } 2681 }
@@ -3070,105 +2953,9 @@ impl Iterator for AssocItemsIterator<'_> {
3070 } 2953 }
3071} 2954}
3072 2955
3073fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> AssocItem {
3074 let id = tcx.hir().as_local_hir_id(def_id).unwrap();
3075 let parent_id = tcx.hir().get_parent_item(id);
3076 let parent_def_id = tcx.hir().local_def_id(parent_id);
3077 let parent_item = tcx.hir().expect_item(parent_id);
3078 match parent_item.kind {
3079 hir::ItemKind::Impl(.., ref impl_item_refs) => {
3080 if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
3081 let assoc_item =
3082 tcx.associated_item_from_impl_item_ref(parent_def_id, impl_item_ref);
3083 debug_assert_eq!(assoc_item.def_id, def_id);
3084 return assoc_item;
3085 }
3086 }
3087
3088 hir::ItemKind::Trait(.., ref trait_item_refs) => {
3089 if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
3090 let assoc_item = tcx.associated_item_from_trait_item_ref(
3091 parent_def_id,
3092 &parent_item.vis,
3093 trait_item_ref,
3094 );
3095 debug_assert_eq!(assoc_item.def_id, def_id);
3096 return assoc_item;
3097 }
3098 }
3099
3100 _ => {}
3101 }
3102
3103 span_bug!(
3104 parent_item.span,
3105 "unexpected parent of trait or impl item or item not found: {:?}",
3106 parent_item.kind
3107 )
3108}
3109
3110#[derive(Clone, HashStable)] 2956#[derive(Clone, HashStable)]
3111pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); 2957pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);
3112 2958
3113/// Calculates the `Sized` constraint.
3114///
3115/// In fact, there are only a few options for the types in the constraint:
3116/// - an obviously-unsized type
3117/// - a type parameter or projection whose Sizedness can't be known
3118/// - a tuple of type parameters or projections, if there are multiple
3119/// such.
3120/// - a Error, if a type contained itself. The representability
3121/// check should catch this case.
3122fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> AdtSizedConstraint<'_> {
3123 let def = tcx.adt_def(def_id);
3124
3125 let result = tcx.mk_type_list(
3126 def.variants
3127 .iter()
3128 .flat_map(|v| v.fields.last())
3129 .flat_map(|f| def.sized_constraint_for_ty(tcx, tcx.type_of(f.did))),
3130 );
3131
3132 debug!("adt_sized_constraint: {:?} => {:?}", def, result);
3133
3134 AdtSizedConstraint(result)
3135}
3136
3137fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
3138 let id = tcx.hir().as_local_hir_id(def_id).unwrap();
3139 let item = tcx.hir().expect_item(id);
3140 match item.kind {
3141 hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
3142 trait_item_refs
3143 .iter()
3144 .map(|trait_item_ref| trait_item_ref.id)
3145 .map(|id| tcx.hir().local_def_id(id.hir_id)),
3146 ),
3147 hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter(
3148 impl_item_refs
3149 .iter()
3150 .map(|impl_item_ref| impl_item_ref.id)
3151 .map(|id| tcx.hir().local_def_id(id.hir_id)),
3152 ),
3153 hir::ItemKind::TraitAlias(..) => &[],
3154 _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
3155 }
3156}
3157
3158fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
3159 tcx.hir().span_if_local(def_id).unwrap()
3160}
3161
3162/// If the given `DefId` describes an item belonging to a trait,
3163/// returns the `DefId` of the trait that the trait item belongs to;
3164/// otherwise, returns `None`.
3165fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
3166 tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
3167 TraitContainer(def_id) => Some(def_id),
3168 ImplContainer(_) => None,
3169 })
3170}
3171
3172/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. 2959/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
3173pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> { 2960pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
3174 if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { 2961 if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
@@ -3181,151 +2968,12 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
3181 None 2968 None
3182} 2969}
3183 2970
3184/// See `ParamEnv` struct definition for details.
3185fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ParamEnv<'_> {
3186 // The param_env of an impl Trait type is its defining function's param_env
3187 if let Some(parent) = is_impl_trait_defn(tcx, def_id) {
3188 return param_env(tcx, parent);
3189 }
3190 // Compute the bounds on Self and the type parameters.
3191
3192 let InstantiatedPredicates { predicates } = tcx.predicates_of(def_id).instantiate_identity(tcx);
3193
3194 // Finally, we have to normalize the bounds in the environment, in
3195 // case they contain any associated type projections. This process
3196 // can yield errors if the put in illegal associated types, like
3197 // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
3198 // report these errors right here; this doesn't actually feel
3199 // right to me, because constructing the environment feels like a
3200 // kind of a "idempotent" action, but I'm not sure where would be
3201 // a better place. In practice, we construct environments for
3202 // every fn once during type checking, and we'll abort if there
3203 // are any errors at that point, so after type checking you can be
3204 // sure that this will succeed without errors anyway.
3205
3206 let unnormalized_env = ty::ParamEnv::new(
3207 tcx.intern_predicates(&predicates),
3208 traits::Reveal::UserFacing,
3209 tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
3210 );
3211
3212 let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
3213 tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
3214 });
3215 let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
3216 traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
3217}
3218
3219fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
3220 assert_eq!(crate_num, LOCAL_CRATE);
3221 tcx.sess.local_crate_disambiguator()
3222}
3223
3224fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
3225 assert_eq!(crate_num, LOCAL_CRATE);
3226 tcx.crate_name.clone()
3227}
3228
3229fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
3230 assert_eq!(crate_num, LOCAL_CRATE);
3231 tcx.hir().crate_hash
3232}
3233
3234fn instance_def_size_estimate<'tcx>(tcx: TyCtxt<'tcx>, instance_def: InstanceDef<'tcx>) -> usize {
3235 match instance_def {
3236 InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
3237 let mir = tcx.instance_mir(instance_def);
3238 mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
3239 }
3240 // Estimate the size of other compiler-generated shims to be 1.
3241 _ => 1,
3242 }
3243}
3244
3245/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
3246///
3247/// See [`ImplOverlapKind::Issue33140`] for more details.
3248fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
3249 debug!("issue33140_self_ty({:?})", def_id);
3250
3251 let trait_ref = tcx
3252 .impl_trait_ref(def_id)
3253 .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
3254
3255 debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
3256
3257 let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
3258 && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
3259
3260 // Check whether these impls would be ok for a marker trait.
3261 if !is_marker_like {
3262 debug!("issue33140_self_ty - not marker-like!");
3263 return None;
3264 }
3265
3266 // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
3267 if trait_ref.substs.len() != 1 {
3268 debug!("issue33140_self_ty - impl has substs!");
3269 return None;
3270 }
3271
3272 let predicates = tcx.predicates_of(def_id);
3273 if predicates.parent.is_some() || !predicates.predicates.is_empty() {
3274 debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
3275 return None;
3276 }
3277
3278 let self_ty = trait_ref.self_ty();
3279 let self_ty_matches = match self_ty.kind {
3280 ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
3281 _ => false,
3282 };
3283
3284 if self_ty_matches {
3285 debug!("issue33140_self_ty - MATCHES!");
3286 Some(self_ty)
3287 } else {
3288 debug!("issue33140_self_ty - non-matching self type");
3289 None
3290 }
3291}
3292
3293/// Check if a function is async.
3294fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
3295 let hir_id = tcx
3296 .hir()
3297 .as_local_hir_id(def_id)
3298 .unwrap_or_else(|| bug!("asyncness: expected local `DefId`, got `{:?}`", def_id));
3299
3300 let node = tcx.hir().get(hir_id);
3301
3302 let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
3303 bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
3304 });
3305
3306 fn_like.asyncness()
3307}
3308
3309pub fn provide(providers: &mut ty::query::Providers<'_>) { 2971pub fn provide(providers: &mut ty::query::Providers<'_>) {
3310 context::provide(providers); 2972 context::provide(providers);
3311 erase_regions::provide(providers); 2973 erase_regions::provide(providers);
3312 layout::provide(providers); 2974 layout::provide(providers);
3313 *providers = ty::query::Providers { 2975 *providers =
3314 asyncness, 2976 ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers };
3315 associated_item,
3316 associated_item_def_ids,
3317 adt_sized_constraint,
3318 def_span,
3319 param_env,
3320 trait_of_item,
3321 crate_disambiguator,
3322 original_crate_name,
3323 crate_hash,
3324 trait_impls_of: trait_def::trait_impls_of_provider,
3325 instance_def_size_estimate,
3326 issue33140_self_ty,
3327 ..*providers
3328 };
3329} 2977}
3330 2978
3331/// A map for the local crate mapping each type to a vector of its 2979/// A map for the local crate mapping each type to a vector of its
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index 7baae90..1fe5248 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -40,6 +40,7 @@ rustc_errors = { path = "../librustc_errors" }
40rustc_plugin_impl = { path = "../librustc_plugin_impl" } 40rustc_plugin_impl = { path = "../librustc_plugin_impl" }
41rustc_privacy = { path = "../librustc_privacy" } 41rustc_privacy = { path = "../librustc_privacy" }
42rustc_resolve = { path = "../librustc_resolve" } 42rustc_resolve = { path = "../librustc_resolve" }
43rustc_ty = { path = "../librustc_ty" }
43tempfile = "3.0.5" 44tempfile = "3.0.5"
44once_cell = "1" 45once_cell = "1"
45 46
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 5f0d9ed..c4444fb 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -680,6 +680,7 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
680 rustc_passes::provide(providers); 680 rustc_passes::provide(providers);
681 rustc_resolve::provide(providers); 681 rustc_resolve::provide(providers);
682 rustc_traits::provide(providers); 682 rustc_traits::provide(providers);
683 rustc_ty::provide(providers);
683 rustc_metadata::provide(providers); 684 rustc_metadata::provide(providers);
684 rustc_lint::provide(providers); 685 rustc_lint::provide(providers);
685 rustc_codegen_utils::provide(providers); 686 rustc_codegen_utils::provide(providers);
diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml
new file mode 100644
index 0000000..fb0d93f
--- /dev/null
+++ b/src/librustc_ty/Cargo.toml
@@ -0,0 +1,16 @@
1[package]
2authors = ["The Rust Project Developers"]
3name = "rustc_ty"
4version = "0.0.0"
5edition = "2018"
6
7[lib]
8name = "rustc_ty"
9path = "lib.rs"
10
11[dependencies]
12log = "0.4"
13rustc = { path = "../librustc" }
14rustc_data_structures = { path = "../librustc_data_structures" }
15rustc_hir = { path = "../librustc_hir" }
16rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs
new file mode 100644
index 0000000..2548d2c
--- /dev/null
+++ b/src/librustc_ty/lib.rs
@@ -0,0 +1,25 @@
1//! Various checks
2//!
3//! # Note
4//!
5//! This API is completely unstable and subject to change.
6
7#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
8#![feature(bool_to_option)]
9#![feature(in_band_lifetimes)]
10#![feature(nll)]
11#![feature(slice_patterns)]
12#![recursion_limit = "256"]
13
14#[macro_use]
15extern crate rustc;
16#[macro_use]
17extern crate log;
18
19use rustc::ty::query::Providers;
20
21mod ty;
22
23pub fn provide(providers: &mut Providers<'_>) {
24 ty::provide(providers);
25}
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
new file mode 100644
index 0000000..fc8beb6
--- /dev/null
+++ b/src/librustc_ty/ty.rs
@@ -0,0 +1,369 @@
1use rustc::hir::map as hir_map;
2use rustc::session::CrateDisambiguator;
3use rustc::traits::{self};
4use rustc::ty::subst::Subst;
5use rustc::ty::{self, ToPredicate, Ty, TyCtxt};
6use rustc_data_structures::svh::Svh;
7use rustc_hir as hir;
8use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
9use rustc_span::symbol::Symbol;
10use rustc_span::Span;
11
12fn sized_constraint_for_ty(tcx: TyCtxt<'tcx>, adtdef: &ty::AdtDef, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
13 use ty::TyKind::*;
14
15 let result = match ty.kind {
16 Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
17 | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
18
19 Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
20 // these are never sized - return the target type
21 vec![ty]
22 }
23
24 Tuple(ref tys) => match tys.last() {
25 None => vec![],
26 Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()),
27 },
28
29 Adt(adt, substs) => {
30 // recursive case
31 let adt_tys = adt.sized_constraint(tcx);
32 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
33 adt_tys
34 .iter()
35 .map(|ty| ty.subst(tcx, substs))
36 .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
37 .collect()
38 }
39
40 Projection(..) | Opaque(..) => {
41 // must calculate explicitly.
42 // FIXME: consider special-casing always-Sized projections
43 vec![ty]
44 }
45
46 UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
47
48 Param(..) => {
49 // perf hack: if there is a `T: Sized` bound, then
50 // we know that `T` is Sized and do not need to check
51 // it on the impl.
52
53 let sized_trait = match tcx.lang_items().sized_trait() {
54 Some(x) => x,
55 _ => return vec![ty],
56 };
57 let sized_predicate = ty::Binder::dummy(ty::TraitRef {
58 def_id: sized_trait,
59 substs: tcx.mk_substs_trait(ty, &[]),
60 })
61 .to_predicate();
62 let predicates = tcx.predicates_of(adtdef.did).predicates;
63 if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
64 }
65
66 Placeholder(..) | Bound(..) | Infer(..) => {
67 bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
68 }
69 };
70 debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
71 result
72}
73
74fn associated_item_from_trait_item_ref(
75 tcx: TyCtxt<'_>,
76 parent_def_id: DefId,
77 parent_vis: &hir::Visibility<'_>,
78 trait_item_ref: &hir::TraitItemRef,
79) -> ty::AssocItem {
80 let def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
81 let (kind, has_self) = match trait_item_ref.kind {
82 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
83 hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
84 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
85 hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
86 };
87
88 ty::AssocItem {
89 ident: trait_item_ref.ident,
90 kind,
91 // Visibility of trait items is inherited from their traits.
92 vis: ty::Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, tcx),
93 defaultness: trait_item_ref.defaultness,
94 def_id,
95 container: ty::TraitContainer(parent_def_id),
96 method_has_self_argument: has_self,
97 }
98}
99
100fn associated_item_from_impl_item_ref(
101 tcx: TyCtxt<'_>,
102 parent_def_id: DefId,
103 impl_item_ref: &hir::ImplItemRef<'_>,
104) -> ty::AssocItem {
105 let def_id = tcx.hir().local_def_id(impl_item_ref.id.hir_id);
106 let (kind, has_self) = match impl_item_ref.kind {
107 hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
108 hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
109 hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
110 hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
111 };
112
113 ty::AssocItem {
114 ident: impl_item_ref.ident,
115 kind,
116 // Visibility of trait impl items doesn't matter.
117 vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, tcx),
118 defaultness: impl_item_ref.defaultness,
119 def_id,
120 container: ty::ImplContainer(parent_def_id),
121 method_has_self_argument: has_self,
122 }
123}
124
125fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
126 let id = tcx.hir().as_local_hir_id(def_id).unwrap();
127 let parent_id = tcx.hir().get_parent_item(id);
128 let parent_def_id = tcx.hir().local_def_id(parent_id);
129 let parent_item = tcx.hir().expect_item(parent_id);
130 match parent_item.kind {
131 hir::ItemKind::Impl(.., ref impl_item_refs) => {
132 if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
133 let assoc_item =
134 associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
135 debug_assert_eq!(assoc_item.def_id, def_id);
136 return assoc_item;
137 }
138 }
139
140 hir::ItemKind::Trait(.., ref trait_item_refs) => {
141 if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
142 let assoc_item = associated_item_from_trait_item_ref(
143 tcx,
144 parent_def_id,
145 &parent_item.vis,
146 trait_item_ref,
147 );
148 debug_assert_eq!(assoc_item.def_id, def_id);
149 return assoc_item;
150 }
151 }
152
153 _ => {}
154 }
155
156 span_bug!(
157 parent_item.span,
158 "unexpected parent of trait or impl item or item not found: {:?}",
159 parent_item.kind
160 )
161}
162
163/// Calculates the `Sized` constraint.
164///
165/// In fact, there are only a few options for the types in the constraint:
166/// - an obviously-unsized type
167/// - a type parameter or projection whose Sizedness can't be known
168/// - a tuple of type parameters or projections, if there are multiple
169/// such.
170/// - a Error, if a type contained itself. The representability
171/// check should catch this case.
172fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
173 let def = tcx.adt_def(def_id);
174
175 let result = tcx.mk_type_list(
176 def.variants
177 .iter()
178 .flat_map(|v| v.fields.last())
179 .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
180 );
181
182 debug!("adt_sized_constraint: {:?} => {:?}", def, result);
183
184 ty::AdtSizedConstraint(result)
185}
186
187fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
188 let id = tcx.hir().as_local_hir_id(def_id).unwrap();
189 let item = tcx.hir().expect_item(id);
190 match item.kind {
191 hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
192 trait_item_refs
193 .iter()
194 .map(|trait_item_ref| trait_item_ref.id)
195 .map(|id| tcx.hir().local_def_id(id.hir_id)),
196 ),
197 hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter(
198 impl_item_refs
199 .iter()
200 .map(|impl_item_ref| impl_item_ref.id)
201 .map(|id| tcx.hir().local_def_id(id.hir_id)),
202 ),
203 hir::ItemKind::TraitAlias(..) => &[],
204 _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
205 }
206}
207
208fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
209 tcx.hir().span_if_local(def_id).unwrap()
210}
211
212/// If the given `DefId` describes an item belonging to a trait,
213/// returns the `DefId` of the trait that the trait item belongs to;
214/// otherwise, returns `None`.
215fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
216 tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
217 ty::TraitContainer(def_id) => Some(def_id),
218 ty::ImplContainer(_) => None,
219 })
220}
221
222/// See `ParamEnv` struct definition for details.
223fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
224 // The param_env of an impl Trait type is its defining function's param_env
225 if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
226 return param_env(tcx, parent);
227 }
228 // Compute the bounds on Self and the type parameters.
229
230 let ty::InstantiatedPredicates { predicates } =
231 tcx.predicates_of(def_id).instantiate_identity(tcx);
232
233 // Finally, we have to normalize the bounds in the environment, in
234 // case they contain any associated type projections. This process
235 // can yield errors if the put in illegal associated types, like
236 // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
237 // report these errors right here; this doesn't actually feel
238 // right to me, because constructing the environment feels like a
239 // kind of a "idempotent" action, but I'm not sure where would be
240 // a better place. In practice, we construct environments for
241 // every fn once during type checking, and we'll abort if there
242 // are any errors at that point, so after type checking you can be
243 // sure that this will succeed without errors anyway.
244
245 let unnormalized_env = ty::ParamEnv::new(
246 tcx.intern_predicates(&predicates),
247 traits::Reveal::UserFacing,
248 tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
249 );
250
251 let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
252 tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
253 });
254 let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
255 traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
256}
257
258fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
259 assert_eq!(crate_num, LOCAL_CRATE);
260 tcx.sess.local_crate_disambiguator()
261}
262
263fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
264 assert_eq!(crate_num, LOCAL_CRATE);
265 tcx.crate_name.clone()
266}
267
268fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
269 assert_eq!(crate_num, LOCAL_CRATE);
270 tcx.hir().crate_hash
271}
272
273fn instance_def_size_estimate<'tcx>(
274 tcx: TyCtxt<'tcx>,
275 instance_def: ty::InstanceDef<'tcx>,
276) -> usize {
277 use ty::InstanceDef;
278
279 match instance_def {
280 InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
281 let mir = tcx.instance_mir(instance_def);
282 mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
283 }
284 // Estimate the size of other compiler-generated shims to be 1.
285 _ => 1,
286 }
287}
288
289/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
290///
291/// See [`ImplOverlapKind::Issue33140`] for more details.
292fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
293 debug!("issue33140_self_ty({:?})", def_id);
294
295 let trait_ref = tcx
296 .impl_trait_ref(def_id)
297 .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
298
299 debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
300
301 let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
302 && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
303
304 // Check whether these impls would be ok for a marker trait.
305 if !is_marker_like {
306 debug!("issue33140_self_ty - not marker-like!");
307 return None;
308 }
309
310 // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
311 if trait_ref.substs.len() != 1 {
312 debug!("issue33140_self_ty - impl has substs!");
313 return None;
314 }
315
316 let predicates = tcx.predicates_of(def_id);
317 if predicates.parent.is_some() || !predicates.predicates.is_empty() {
318 debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
319 return None;
320 }
321
322 let self_ty = trait_ref.self_ty();
323 let self_ty_matches = match self_ty.kind {
324 ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
325 _ => false,
326 };
327
328 if self_ty_matches {
329 debug!("issue33140_self_ty - MATCHES!");
330 Some(self_ty)
331 } else {
332 debug!("issue33140_self_ty - non-matching self type");
333 None
334 }
335}
336
337/// Check if a function is async.
338fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
339 let hir_id = tcx
340 .hir()
341 .as_local_hir_id(def_id)
342 .unwrap_or_else(|| bug!("asyncness: expected local `DefId`, got `{:?}`", def_id));
343
344 let node = tcx.hir().get(hir_id);
345
346 let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
347 bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
348 });
349
350 fn_like.asyncness()
351}
352
353pub fn provide(providers: &mut ty::query::Providers<'_>) {
354 *providers = ty::query::Providers {
355 asyncness,
356 associated_item,
357 associated_item_def_ids,
358 adt_sized_constraint,
359 def_span,
360 param_env,
361 trait_of_item,
362 crate_disambiguator,
363 original_crate_name,
364 crate_hash,
365 instance_def_size_estimate,
366 issue33140_self_ty,
367 ..*providers
368 };
369}