]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #67780 - cjgillot:passes-ty, r=Zoxc
authorDylan DPC <dylan.dpc@gmail.com>
Thu, 16 Jan 2020 06:28:00 +0000 (11:58 +0530)
committerGitHub <noreply@github.com>
Thu, 16 Jan 2020 06:28:00 +0000 (11:58 +0530)
Move some queries from rustc::ty to librustc_ty.

cc #65031

Cargo.lock
src/librustc/ty/mod.rs
src/librustc_interface/Cargo.toml
src/librustc_interface/passes.rs
src/librustc_ty/Cargo.toml [new file with mode: 0644]
src/librustc_ty/lib.rs [new file with mode: 0644]
src/librustc_ty/ty.rs [new file with mode: 0644]

index 3359fe488f16b2cbdacd514c9dd489acad56ccdd..f33d7ff12febff8ddad98478bc31215fb2e5f310 100644 (file)
@@ -3652,6 +3652,7 @@ dependencies = [
  "rustc_span",
  "rustc_target",
  "rustc_traits",
+ "rustc_ty",
  "rustc_typeck",
  "serialize",
  "smallvec 1.0.0",
@@ -3953,6 +3954,17 @@ dependencies = [
  "syntax",
 ]
 
+[[package]]
+name = "rustc_ty"
+version = "0.0.0"
+dependencies = [
+ "log",
+ "rustc",
+ "rustc_data_structures",
+ "rustc_hir",
+ "rustc_span",
+]
+
 [[package]]
 name = "rustc_typeck"
 version = "0.0.0"
index d1e37a4ea1151f09e8a1dc01e9d2c71ae784fc03..e6acb6b74dc6340b449d074ef66d7875463c371e 100644 (file)
@@ -18,7 +18,6 @@
 use crate::mir::interpret::ErrorHandled;
 use crate::mir::GeneratorLayout;
 use crate::mir::ReadOnlyBodyAndCache;
-use crate::session::CrateDisambiguator;
 use crate::session::DataTypeKind;
 use crate::traits::{self, Reveal};
 use crate::ty;
@@ -31,7 +30,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -2423,70 +2421,6 @@ pub fn destructor(&self, tcx: TyCtxt<'tcx>) -> Option<Destructor> {
     pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
         tcx.adt_sized_constraint(self.did).0
     }
-
-    fn sized_constraint_for_ty(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
-        let result = match ty.kind {
-            Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
-            | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
-
-            Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
-                // these are never sized - return the target type
-                vec![ty]
-            }
-
-            Tuple(ref tys) => match tys.last() {
-                None => vec![],
-                Some(ty) => self.sized_constraint_for_ty(tcx, ty.expect_ty()),
-            },
-
-            Adt(adt, substs) => {
-                // recursive case
-                let adt_tys = adt.sized_constraint(tcx);
-                debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
-                adt_tys
-                    .iter()
-                    .map(|ty| ty.subst(tcx, substs))
-                    .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
-                    .collect()
-            }
-
-            Projection(..) | Opaque(..) => {
-                // must calculate explicitly.
-                // FIXME: consider special-casing always-Sized projections
-                vec![ty]
-            }
-
-            UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-
-            Param(..) => {
-                // perf hack: if there is a `T: Sized` bound, then
-                // we know that `T` is Sized and do not need to check
-                // it on the impl.
-
-                let sized_trait = match tcx.lang_items().sized_trait() {
-                    Some(x) => x,
-                    _ => return vec![ty],
-                };
-                let sized_predicate = Binder::dummy(TraitRef {
-                    def_id: sized_trait,
-                    substs: tcx.mk_substs_trait(ty, &[]),
-                })
-                .to_predicate();
-                let predicates = tcx.predicates_of(self.did).predicates;
-                if predicates.iter().any(|(p, _)| *p == sized_predicate) {
-                    vec![]
-                } else {
-                    vec![ty]
-                }
-            }
-
-            Placeholder(..) | Bound(..) | Infer(..) => {
-                bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
-            }
-        };
-        debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
-        result
-    }
 }
 
 impl<'tcx> FieldDef {
@@ -2742,57 +2676,6 @@ pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
         is_associated_item.then(|| self.associated_item(def_id))
     }
 
-    fn associated_item_from_trait_item_ref(
-        self,
-        parent_def_id: DefId,
-        parent_vis: &hir::Visibility<'_>,
-        trait_item_ref: &hir::TraitItemRef,
-    ) -> AssocItem {
-        let def_id = self.hir().local_def_id(trait_item_ref.id.hir_id);
-        let (kind, has_self) = match trait_item_ref.kind {
-            hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
-            hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
-            hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-            hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
-        };
-
-        AssocItem {
-            ident: trait_item_ref.ident,
-            kind,
-            // Visibility of trait items is inherited from their traits.
-            vis: Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, self),
-            defaultness: trait_item_ref.defaultness,
-            def_id,
-            container: TraitContainer(parent_def_id),
-            method_has_self_argument: has_self,
-        }
-    }
-
-    fn associated_item_from_impl_item_ref(
-        self,
-        parent_def_id: DefId,
-        impl_item_ref: &hir::ImplItemRef<'_>,
-    ) -> AssocItem {
-        let def_id = self.hir().local_def_id(impl_item_ref.id.hir_id);
-        let (kind, has_self) = match impl_item_ref.kind {
-            hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
-            hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
-            hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-            hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
-        };
-
-        AssocItem {
-            ident: impl_item_ref.ident,
-            kind,
-            // Visibility of trait impl items doesn't matter.
-            vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, self),
-            defaultness: impl_item_ref.defaultness,
-            def_id,
-            container: ImplContainer(parent_def_id),
-            method_has_self_argument: has_self,
-        }
-    }
-
     pub fn field_index(self, hir_id: hir::HirId, tables: &TypeckTables<'_>) -> usize {
         tables.field_indices().get(hir_id).cloned().expect("no index for a field")
     }
@@ -3070,105 +2953,9 @@ fn next(&mut self) -> Option<AssocItem> {
     }
 }
 
-fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> AssocItem {
-    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let parent_id = tcx.hir().get_parent_item(id);
-    let parent_def_id = tcx.hir().local_def_id(parent_id);
-    let parent_item = tcx.hir().expect_item(parent_id);
-    match parent_item.kind {
-        hir::ItemKind::Impl(.., ref impl_item_refs) => {
-            if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
-                let assoc_item =
-                    tcx.associated_item_from_impl_item_ref(parent_def_id, impl_item_ref);
-                debug_assert_eq!(assoc_item.def_id, def_id);
-                return assoc_item;
-            }
-        }
-
-        hir::ItemKind::Trait(.., ref trait_item_refs) => {
-            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
-                let assoc_item = tcx.associated_item_from_trait_item_ref(
-                    parent_def_id,
-                    &parent_item.vis,
-                    trait_item_ref,
-                );
-                debug_assert_eq!(assoc_item.def_id, def_id);
-                return assoc_item;
-            }
-        }
-
-        _ => {}
-    }
-
-    span_bug!(
-        parent_item.span,
-        "unexpected parent of trait or impl item or item not found: {:?}",
-        parent_item.kind
-    )
-}
-
 #[derive(Clone, HashStable)]
 pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);
 
-/// Calculates the `Sized` constraint.
-///
-/// In fact, there are only a few options for the types in the constraint:
-///     - an obviously-unsized type
-///     - a type parameter or projection whose Sizedness can't be known
-///     - a tuple of type parameters or projections, if there are multiple
-///       such.
-///     - a Error, if a type contained itself. The representability
-///       check should catch this case.
-fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> AdtSizedConstraint<'_> {
-    let def = tcx.adt_def(def_id);
-
-    let result = tcx.mk_type_list(
-        def.variants
-            .iter()
-            .flat_map(|v| v.fields.last())
-            .flat_map(|f| def.sized_constraint_for_ty(tcx, tcx.type_of(f.did))),
-    );
-
-    debug!("adt_sized_constraint: {:?} => {:?}", def, result);
-
-    AdtSizedConstraint(result)
-}
-
-fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
-    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let item = tcx.hir().expect_item(id);
-    match item.kind {
-        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
-            trait_item_refs
-                .iter()
-                .map(|trait_item_ref| trait_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id)),
-        ),
-        hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter(
-            impl_item_refs
-                .iter()
-                .map(|impl_item_ref| impl_item_ref.id)
-                .map(|id| tcx.hir().local_def_id(id.hir_id)),
-        ),
-        hir::ItemKind::TraitAlias(..) => &[],
-        _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
-    }
-}
-
-fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
-    tcx.hir().span_if_local(def_id).unwrap()
-}
-
-/// If the given `DefId` describes an item belonging to a trait,
-/// returns the `DefId` of the trait that the trait item belongs to;
-/// otherwise, returns `None`.
-fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
-    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
-        TraitContainer(def_id) => Some(def_id),
-        ImplContainer(_) => None,
-    })
-}
-
 /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
 pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
     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> {
     None
 }
 
-/// See `ParamEnv` struct definition for details.
-fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ParamEnv<'_> {
-    // The param_env of an impl Trait type is its defining function's param_env
-    if let Some(parent) = is_impl_trait_defn(tcx, def_id) {
-        return param_env(tcx, parent);
-    }
-    // Compute the bounds on Self and the type parameters.
-
-    let InstantiatedPredicates { predicates } = tcx.predicates_of(def_id).instantiate_identity(tcx);
-
-    // Finally, we have to normalize the bounds in the environment, in
-    // case they contain any associated type projections. This process
-    // can yield errors if the put in illegal associated types, like
-    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
-    // report these errors right here; this doesn't actually feel
-    // right to me, because constructing the environment feels like a
-    // kind of a "idempotent" action, but I'm not sure where would be
-    // a better place. In practice, we construct environments for
-    // every fn once during type checking, and we'll abort if there
-    // are any errors at that point, so after type checking you can be
-    // sure that this will succeed without errors anyway.
-
-    let unnormalized_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        traits::Reveal::UserFacing,
-        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
-    );
-
-    let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
-        tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
-    });
-    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
-    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
-}
-
-fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.sess.local_crate_disambiguator()
-}
-
-fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.crate_name.clone()
-}
-
-fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
-    assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.hir().crate_hash
-}
-
-fn instance_def_size_estimate<'tcx>(tcx: TyCtxt<'tcx>, instance_def: InstanceDef<'tcx>) -> usize {
-    match instance_def {
-        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
-            let mir = tcx.instance_mir(instance_def);
-            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
-        }
-        // Estimate the size of other compiler-generated shims to be 1.
-        _ => 1,
-    }
-}
-
-/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
-///
-/// See [`ImplOverlapKind::Issue33140`] for more details.
-fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
-    debug!("issue33140_self_ty({:?})", def_id);
-
-    let trait_ref = tcx
-        .impl_trait_ref(def_id)
-        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
-
-    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
-
-    let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
-        && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
-
-    // Check whether these impls would be ok for a marker trait.
-    if !is_marker_like {
-        debug!("issue33140_self_ty - not marker-like!");
-        return None;
-    }
-
-    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
-    if trait_ref.substs.len() != 1 {
-        debug!("issue33140_self_ty - impl has substs!");
-        return None;
-    }
-
-    let predicates = tcx.predicates_of(def_id);
-    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
-        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
-        return None;
-    }
-
-    let self_ty = trait_ref.self_ty();
-    let self_ty_matches = match self_ty.kind {
-        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
-        _ => false,
-    };
-
-    if self_ty_matches {
-        debug!("issue33140_self_ty - MATCHES!");
-        Some(self_ty)
-    } else {
-        debug!("issue33140_self_ty - non-matching self type");
-        None
-    }
-}
-
-/// Check if a function is async.
-fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
-    let hir_id = tcx
-        .hir()
-        .as_local_hir_id(def_id)
-        .unwrap_or_else(|| bug!("asyncness: expected local `DefId`, got `{:?}`", def_id));
-
-    let node = tcx.hir().get(hir_id);
-
-    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
-        bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
-    });
-
-    fn_like.asyncness()
-}
-
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
     context::provide(providers);
     erase_regions::provide(providers);
     layout::provide(providers);
-    *providers = ty::query::Providers {
-        asyncness,
-        associated_item,
-        associated_item_def_ids,
-        adt_sized_constraint,
-        def_span,
-        param_env,
-        trait_of_item,
-        crate_disambiguator,
-        original_crate_name,
-        crate_hash,
-        trait_impls_of: trait_def::trait_impls_of_provider,
-        instance_def_size_estimate,
-        issue33140_self_ty,
-        ..*providers
-    };
+    *providers =
+        ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers };
 }
 
 /// A map for the local crate mapping each type to a vector of its
index 7baae90beabb5a50d5e97786abe2323d8fbc2d28..1fe5248dbf4ceac9b33712b6cbacc2af81081689 100644 (file)
@@ -40,6 +40,7 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_plugin_impl = { path = "../librustc_plugin_impl" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
+rustc_ty = { path = "../librustc_ty" }
 tempfile = "3.0.5"
 once_cell = "1"
 
index 5f0d9ed5bdf0d945d7e0b2edb9f1a251dbf6faae..c4444fbaa2fc761390e2b1b99be5d6cf84fa33ec 100644 (file)
@@ -680,6 +680,7 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
     rustc_passes::provide(providers);
     rustc_resolve::provide(providers);
     rustc_traits::provide(providers);
+    rustc_ty::provide(providers);
     rustc_metadata::provide(providers);
     rustc_lint::provide(providers);
     rustc_codegen_utils::provide(providers);
diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml
new file mode 100644 (file)
index 0000000..fb0d93f
--- /dev/null
@@ -0,0 +1,16 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_ty"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_ty"
+path = "lib.rs"
+
+[dependencies]
+log = "0.4"
+rustc = { path = "../librustc" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_span = { path = "../librustc_span" }
diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs
new file mode 100644 (file)
index 0000000..2548d2c
--- /dev/null
@@ -0,0 +1,25 @@
+//! Various checks
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bool_to_option)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+#![feature(slice_patterns)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate rustc;
+#[macro_use]
+extern crate log;
+
+use rustc::ty::query::Providers;
+
+mod ty;
+
+pub fn provide(providers: &mut Providers<'_>) {
+    ty::provide(providers);
+}
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
new file mode 100644 (file)
index 0000000..fc8beb6
--- /dev/null
@@ -0,0 +1,369 @@
+use rustc::hir::map as hir_map;
+use rustc::session::CrateDisambiguator;
+use rustc::traits::{self};
+use rustc::ty::subst::Subst;
+use rustc::ty::{self, ToPredicate, Ty, TyCtxt};
+use rustc_data_structures::svh::Svh;
+use rustc_hir as hir;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_span::symbol::Symbol;
+use rustc_span::Span;
+
+fn sized_constraint_for_ty(tcx: TyCtxt<'tcx>, adtdef: &ty::AdtDef, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
+    use ty::TyKind::*;
+
+    let result = match ty.kind {
+        Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
+        | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
+
+        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
+            // these are never sized - return the target type
+            vec![ty]
+        }
+
+        Tuple(ref tys) => match tys.last() {
+            None => vec![],
+            Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()),
+        },
+
+        Adt(adt, substs) => {
+            // recursive case
+            let adt_tys = adt.sized_constraint(tcx);
+            debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
+            adt_tys
+                .iter()
+                .map(|ty| ty.subst(tcx, substs))
+                .flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
+                .collect()
+        }
+
+        Projection(..) | Opaque(..) => {
+            // must calculate explicitly.
+            // FIXME: consider special-casing always-Sized projections
+            vec![ty]
+        }
+
+        UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
+        Param(..) => {
+            // perf hack: if there is a `T: Sized` bound, then
+            // we know that `T` is Sized and do not need to check
+            // it on the impl.
+
+            let sized_trait = match tcx.lang_items().sized_trait() {
+                Some(x) => x,
+                _ => return vec![ty],
+            };
+            let sized_predicate = ty::Binder::dummy(ty::TraitRef {
+                def_id: sized_trait,
+                substs: tcx.mk_substs_trait(ty, &[]),
+            })
+            .to_predicate();
+            let predicates = tcx.predicates_of(adtdef.did).predicates;
+            if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] }
+        }
+
+        Placeholder(..) | Bound(..) | Infer(..) => {
+            bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty)
+        }
+    };
+    debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
+    result
+}
+
+fn associated_item_from_trait_item_ref(
+    tcx: TyCtxt<'_>,
+    parent_def_id: DefId,
+    parent_vis: &hir::Visibility<'_>,
+    trait_item_ref: &hir::TraitItemRef,
+) -> ty::AssocItem {
+    let def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
+    let (kind, has_self) = match trait_item_ref.kind {
+        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
+        hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
+        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+        hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
+    };
+
+    ty::AssocItem {
+        ident: trait_item_ref.ident,
+        kind,
+        // Visibility of trait items is inherited from their traits.
+        vis: ty::Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, tcx),
+        defaultness: trait_item_ref.defaultness,
+        def_id,
+        container: ty::TraitContainer(parent_def_id),
+        method_has_self_argument: has_self,
+    }
+}
+
+fn associated_item_from_impl_item_ref(
+    tcx: TyCtxt<'_>,
+    parent_def_id: DefId,
+    impl_item_ref: &hir::ImplItemRef<'_>,
+) -> ty::AssocItem {
+    let def_id = tcx.hir().local_def_id(impl_item_ref.id.hir_id);
+    let (kind, has_self) = match impl_item_ref.kind {
+        hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
+        hir::AssocItemKind::Method { has_self } => (ty::AssocKind::Method, has_self),
+        hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
+        hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
+    };
+
+    ty::AssocItem {
+        ident: impl_item_ref.ident,
+        kind,
+        // Visibility of trait impl items doesn't matter.
+        vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, tcx),
+        defaultness: impl_item_ref.defaultness,
+        def_id,
+        container: ty::ImplContainer(parent_def_id),
+        method_has_self_argument: has_self,
+    }
+}
+
+fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
+    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let parent_id = tcx.hir().get_parent_item(id);
+    let parent_def_id = tcx.hir().local_def_id(parent_id);
+    let parent_item = tcx.hir().expect_item(parent_id);
+    match parent_item.kind {
+        hir::ItemKind::Impl(.., ref impl_item_refs) => {
+            if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
+                let assoc_item =
+                    associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
+                let assoc_item = associated_item_from_trait_item_ref(
+                    tcx,
+                    parent_def_id,
+                    &parent_item.vis,
+                    trait_item_ref,
+                );
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        _ => {}
+    }
+
+    span_bug!(
+        parent_item.span,
+        "unexpected parent of trait or impl item or item not found: {:?}",
+        parent_item.kind
+    )
+}
+
+/// Calculates the `Sized` constraint.
+///
+/// In fact, there are only a few options for the types in the constraint:
+///     - an obviously-unsized type
+///     - a type parameter or projection whose Sizedness can't be known
+///     - a tuple of type parameters or projections, if there are multiple
+///       such.
+///     - a Error, if a type contained itself. The representability
+///       check should catch this case.
+fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
+    let def = tcx.adt_def(def_id);
+
+    let result = tcx.mk_type_list(
+        def.variants
+            .iter()
+            .flat_map(|v| v.fields.last())
+            .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
+    );
+
+    debug!("adt_sized_constraint: {:?} => {:?}", def, result);
+
+    ty::AdtSizedConstraint(result)
+}
+
+fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
+    let id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let item = tcx.hir().expect_item(id);
+    match item.kind {
+        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
+            trait_item_refs
+                .iter()
+                .map(|trait_item_ref| trait_item_ref.id)
+                .map(|id| tcx.hir().local_def_id(id.hir_id)),
+        ),
+        hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter(
+            impl_item_refs
+                .iter()
+                .map(|impl_item_ref| impl_item_ref.id)
+                .map(|id| tcx.hir().local_def_id(id.hir_id)),
+        ),
+        hir::ItemKind::TraitAlias(..) => &[],
+        _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
+    }
+}
+
+fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
+    tcx.hir().span_if_local(def_id).unwrap()
+}
+
+/// If the given `DefId` describes an item belonging to a trait,
+/// returns the `DefId` of the trait that the trait item belongs to;
+/// otherwise, returns `None`.
+fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
+    tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container {
+        ty::TraitContainer(def_id) => Some(def_id),
+        ty::ImplContainer(_) => None,
+    })
+}
+
+/// See `ParamEnv` struct definition for details.
+fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
+    // The param_env of an impl Trait type is its defining function's param_env
+    if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
+        return param_env(tcx, parent);
+    }
+    // Compute the bounds on Self and the type parameters.
+
+    let ty::InstantiatedPredicates { predicates } =
+        tcx.predicates_of(def_id).instantiate_identity(tcx);
+
+    // Finally, we have to normalize the bounds in the environment, in
+    // case they contain any associated type projections. This process
+    // can yield errors if the put in illegal associated types, like
+    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+    // report these errors right here; this doesn't actually feel
+    // right to me, because constructing the environment feels like a
+    // kind of a "idempotent" action, but I'm not sure where would be
+    // a better place. In practice, we construct environments for
+    // every fn once during type checking, and we'll abort if there
+    // are any errors at that point, so after type checking you can be
+    // sure that this will succeed without errors anyway.
+
+    let unnormalized_env = ty::ParamEnv::new(
+        tcx.intern_predicates(&predicates),
+        traits::Reveal::UserFacing,
+        tcx.sess.opts.debugging_opts.chalk.then_some(def_id),
+    );
+
+    let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
+        tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
+    });
+    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
+    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
+}
+
+fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.sess.local_crate_disambiguator()
+}
+
+fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.crate_name.clone()
+}
+
+fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.hir().crate_hash
+}
+
+fn instance_def_size_estimate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance_def: ty::InstanceDef<'tcx>,
+) -> usize {
+    use ty::InstanceDef;
+
+    match instance_def {
+        InstanceDef::Item(..) | InstanceDef::DropGlue(..) => {
+            let mir = tcx.instance_mir(instance_def);
+            mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum()
+        }
+        // Estimate the size of other compiler-generated shims to be 1.
+        _ => 1,
+    }
+}
+
+/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
+///
+/// See [`ImplOverlapKind::Issue33140`] for more details.
+fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
+    debug!("issue33140_self_ty({:?})", def_id);
+
+    let trait_ref = tcx
+        .impl_trait_ref(def_id)
+        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
+
+    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
+
+    let is_marker_like = tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive
+        && tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
+
+    // Check whether these impls would be ok for a marker trait.
+    if !is_marker_like {
+        debug!("issue33140_self_ty - not marker-like!");
+        return None;
+    }
+
+    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
+    if trait_ref.substs.len() != 1 {
+        debug!("issue33140_self_ty - impl has substs!");
+        return None;
+    }
+
+    let predicates = tcx.predicates_of(def_id);
+    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
+        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
+        return None;
+    }
+
+    let self_ty = trait_ref.self_ty();
+    let self_ty_matches = match self_ty.kind {
+        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
+        _ => false,
+    };
+
+    if self_ty_matches {
+        debug!("issue33140_self_ty - MATCHES!");
+        Some(self_ty)
+    } else {
+        debug!("issue33140_self_ty - non-matching self type");
+        None
+    }
+}
+
+/// Check if a function is async.
+fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
+    let hir_id = tcx
+        .hir()
+        .as_local_hir_id(def_id)
+        .unwrap_or_else(|| bug!("asyncness: expected local `DefId`, got `{:?}`", def_id));
+
+    let node = tcx.hir().get(hir_id);
+
+    let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| {
+        bug!("asyncness: expected fn-like node but got `{:?}`", def_id);
+    });
+
+    fn_like.asyncness()
+}
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers {
+        asyncness,
+        associated_item,
+        associated_item_def_ids,
+        adt_sized_constraint,
+        def_span,
+        param_env,
+        trait_of_item,
+        crate_disambiguator,
+        original_crate_name,
+        crate_hash,
+        instance_def_size_estimate,
+        issue33140_self_ty,
+        ..*providers
+    };
+}