]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/collect.rs
Move generic arg / param validation to `create_substs_for_generic_args`
[rust.git] / src / librustc_typeck / collect.rs
index 5349c324ad8a7b6d0448e023a89bde5c35120346..3bdec71d3dcf702c51a356ad7ceeff15eb1f2b6f 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 //! "Collection" is the process of determining the type and other external
 //! details of each item in Rust. Collection is specifically concerned
 //! with *inter-procedural* things -- for example, for a function
 use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc::mir::mono::Linkage;
 use rustc::session::parse::feature_err;
-use rustc::traits;
 use rustc::ty::query::Providers;
-use rustc::ty::subst::GenericArgKind;
 use rustc::ty::subst::{InternalSubsts, Subst};
 use rustc::ty::util::Discr;
 use rustc::ty::util::IntTypeExt;
-use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness};
-use rustc::ty::{ReprOptions, ToPredicate};
+use rustc::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
+use rustc::ty::{ReprOptions, ToPredicate, WithConstness};
 use rustc_attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{struct_span_err, Applicability, StashKey};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -50,6 +46,8 @@
 use syntax::ast;
 use syntax::ast::{Ident, MetaItemKind};
 
+mod type_of;
+
 struct OnlySelfBounds(bool);
 
 ///////////////////////////////////////////////////////////////////////////
@@ -64,7 +62,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
 
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
-        type_of,
+        type_of: type_of::type_of,
         generics_of,
         predicates_of,
         predicates_defined_on,
@@ -371,10 +369,12 @@ fn projected_ty_from_poly_trait_ref(
                         hir::ItemKind::Enum(_, generics)
                         | hir::ItemKind::Struct(_, generics)
                         | hir::ItemKind::Union(_, generics) => {
-                            // FIXME: look for an appropriate lt name if `'a` is already used
+                            let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
                             let (lt_sp, sugg) = match &generics.params[..] {
-                                [] => (generics.span, "<'a>".to_string()),
-                                [bound, ..] => (bound.span.shrink_to_lo(), "'a, ".to_string()),
+                                [] => (generics.span, format!("<{}>", lt_name)),
+                                [bound, ..] => {
+                                    (bound.span.shrink_to_lo(), format!("{}, ", lt_name))
+                                }
                             };
                             let suggestions = vec![
                                 (lt_sp, sugg),
@@ -389,7 +389,7 @@ fn projected_ty_from_poly_trait_ref(
                                                     ty::EarlyBoundRegion {
                                                         def_id: item_def_id,
                                                         index: 0,
-                                                        name: Symbol::intern("'a"),
+                                                        name: Symbol::intern(&lt_name),
                                                     },
                                                 ))
                                             })
@@ -447,6 +447,43 @@ fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
     }
 }
 
+/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
+fn get_new_lifetime_name<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    poly_trait_ref: ty::PolyTraitRef<'tcx>,
+    generics: &hir::Generics<'tcx>,
+) -> String {
+    let existing_lifetimes = tcx
+        .collect_referenced_late_bound_regions(&poly_trait_ref)
+        .into_iter()
+        .filter_map(|lt| {
+            if let ty::BoundRegion::BrNamed(_, name) = lt {
+                Some(name.as_str().to_string())
+            } else {
+                None
+            }
+        })
+        .chain(generics.params.iter().filter_map(|param| {
+            if let hir::GenericParamKind::Lifetime { .. } = &param.kind {
+                Some(param.name.ident().as_str().to_string())
+            } else {
+                None
+            }
+        }))
+        .collect::<FxHashSet<String>>();
+
+    let a_to_z_repeat_n = |n| {
+        (b'a'..=b'z').map(move |c| {
+            let mut s = format!("'");
+            s.extend(std::iter::repeat(char::from(c)).take(n));
+            s
+        })
+    };
+
+    // If all single char lifetime names are present, we wrap around and double the chars.
+    (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
+}
+
 /// Returns the predicates defined on `item_def_id` of the form
 /// `X: Foo` where `X` is the type parameter `def_id`.
 fn type_param_predicates(
@@ -1232,7 +1269,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
 
     let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
 
-    // Now create the real type parameters.
+    // Now create the real type and const parameters.
     let type_start = own_start - has_self as u32 + params.len() as u32;
     let mut i = 0;
     params.extend(ast_generics.params.iter().filter_map(|param| {
@@ -1329,601 +1366,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
     })
 }
 
-fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
-    struct_span_err!(
-        tcx.sess,
-        span,
-        E0202,
-        "associated types are not yet supported in inherent impls (see #8995)"
-    )
-    .emit();
-}
-
-fn infer_placeholder_type(
-    tcx: TyCtxt<'_>,
-    def_id: DefId,
-    body_id: hir::BodyId,
-    span: Span,
-    item_ident: Ident,
-) -> Ty<'_> {
-    let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id);
-
-    // If this came from a free `const` or `static mut?` item,
-    // then the user may have written e.g. `const A = 42;`.
-    // In this case, the parser has stashed a diagnostic for
-    // us to improve in typeck so we do that now.
-    match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) {
-        Some(mut err) => {
-            // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
-            // We are typeck and have the real type, so remove that and suggest the actual type.
-            err.suggestions.clear();
-            err.span_suggestion(
-                span,
-                "provide a type for the item",
-                format!("{}: {}", item_ident, ty),
-                Applicability::MachineApplicable,
-            )
-            .emit();
-        }
-        None => {
-            let mut diag = bad_placeholder_type(tcx, vec![span]);
-            if ty != tcx.types.err {
-                diag.span_suggestion(
-                    span,
-                    "replace `_` with the correct type",
-                    ty.to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            diag.emit();
-        }
-    }
-
-    ty
-}
-
-fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
-    use rustc_hir::*;
-
-    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-
-    let icx = ItemCtxt::new(tcx, def_id);
-
-    match tcx.hir().get(hir_id) {
-        Node::TraitItem(item) => match item.kind {
-            TraitItemKind::Method(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
-            }
-            TraitItemKind::Const(ref ty, body_id) => body_id
-                .and_then(|body_id| {
-                    if is_suggestable_infer_ty(ty) {
-                        Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
-                    } else {
-                        None
-                    }
-                })
-                .unwrap_or_else(|| icx.to_ty(ty)),
-            TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
-            TraitItemKind::Type(_, None) => {
-                span_bug!(item.span, "associated type missing default");
-            }
-        },
-
-        Node::ImplItem(item) => match item.kind {
-            ImplItemKind::Method(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
-            }
-            ImplItemKind::Const(ref ty, body_id) => {
-                if is_suggestable_infer_ty(ty) {
-                    infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
-                } else {
-                    icx.to_ty(ty)
-                }
-            }
-            ImplItemKind::OpaqueTy(_) => {
-                if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() {
-                    report_assoc_ty_on_inherent_impl(tcx, item.span);
-                }
-
-                find_opaque_ty_constraints(tcx, def_id)
-            }
-            ImplItemKind::TyAlias(ref ty) => {
-                if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() {
-                    report_assoc_ty_on_inherent_impl(tcx, item.span);
-                }
-
-                icx.to_ty(ty)
-            }
-        },
-
-        Node::Item(item) => {
-            match item.kind {
-                ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
-                    if is_suggestable_infer_ty(ty) {
-                        infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
-                    } else {
-                        icx.to_ty(ty)
-                    }
-                }
-                ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
-                    icx.to_ty(self_ty)
-                }
-                ItemKind::Fn(..) => {
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs)
-                }
-                ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
-                    let def = tcx.adt_def(def_id);
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    tcx.mk_adt(def, substs)
-                }
-                ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => {
-                    find_opaque_ty_constraints(tcx, def_id)
-                }
-                // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
-                    tcx.typeck_tables_of(owner)
-                        .concrete_opaque_types
-                        .get(&def_id)
-                        .map(|opaque| opaque.concrete_type)
-                        .unwrap_or_else(|| {
-                            // This can occur if some error in the
-                            // owner fn prevented us from populating
-                            // the `concrete_opaque_types` table.
-                            tcx.sess.delay_span_bug(
-                                DUMMY_SP,
-                                &format!(
-                                    "owner {:?} has no opaque type for {:?} in its tables",
-                                    owner, def_id,
-                                ),
-                            );
-                            tcx.types.err
-                        })
-                }
-                ItemKind::Trait(..)
-                | ItemKind::TraitAlias(..)
-                | ItemKind::Mod(..)
-                | ItemKind::ForeignMod(..)
-                | ItemKind::GlobalAsm(..)
-                | ItemKind::ExternCrate(..)
-                | ItemKind::Use(..) => {
-                    span_bug!(
-                        item.span,
-                        "compute_type_of_item: unexpected item type: {:?}",
-                        item.kind
-                    );
-                }
-            }
-        }
-
-        Node::ForeignItem(foreign_item) => match foreign_item.kind {
-            ForeignItemKind::Fn(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
-            }
-            ForeignItemKind::Static(ref t, _) => icx.to_ty(t),
-            ForeignItemKind::Type => tcx.mk_foreign(def_id),
-        },
-
-        Node::Ctor(&ref def) | Node::Variant(hir::Variant { data: ref def, .. }) => match *def {
-            VariantData::Unit(..) | VariantData::Struct(..) => {
-                tcx.type_of(tcx.hir().get_parent_did(hir_id))
-            }
-            VariantData::Tuple(..) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                tcx.mk_fn_def(def_id, substs)
-            }
-        },
-
-        Node::Field(field) => icx.to_ty(&field.ty),
-
-        Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) => {
-            if gen.is_some() {
-                return tcx.typeck_tables_of(def_id).node_type(hir_id);
-            }
-
-            let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            tcx.mk_closure(def_id, substs)
-        }
-
-        Node::AnonConst(_) => {
-            let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
-            match parent_node {
-                Node::Ty(&hir::Ty { kind: hir::TyKind::Array(_, ref constant), .. })
-                | Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref constant), .. })
-                | Node::Expr(&hir::Expr { kind: ExprKind::Repeat(_, ref constant), .. })
-                    if constant.hir_id == hir_id =>
-                {
-                    tcx.types.usize
-                }
-
-                Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
-                    tcx.adt_def(tcx.hir().get_parent_did(hir_id)).repr.discr_type().to_ty(tcx)
-                }
-
-                Node::Ty(&hir::Ty { kind: hir::TyKind::Path(_), .. })
-                | Node::Expr(&hir::Expr { kind: ExprKind::Struct(..), .. })
-                | Node::Expr(&hir::Expr { kind: ExprKind::Path(_), .. })
-                | Node::TraitRef(..) => {
-                    let path = match parent_node {
-                        Node::Ty(&hir::Ty {
-                            kind: hir::TyKind::Path(QPath::Resolved(_, ref path)),
-                            ..
-                        })
-                        | Node::Expr(&hir::Expr {
-                            kind: ExprKind::Path(QPath::Resolved(_, ref path)),
-                            ..
-                        }) => Some(&**path),
-                        Node::Expr(&hir::Expr { kind: ExprKind::Struct(ref path, ..), .. }) => {
-                            if let QPath::Resolved(_, ref path) = **path {
-                                Some(&**path)
-                            } else {
-                                None
-                            }
-                        }
-                        Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(&**path),
-                        _ => None,
-                    };
-
-                    if let Some(path) = path {
-                        let arg_index = path
-                            .segments
-                            .iter()
-                            .filter_map(|seg| seg.args.as_ref())
-                            .map(|generic_args| generic_args.args.as_ref())
-                            .find_map(|args| {
-                                args.iter()
-                                    .filter(|arg| arg.is_const())
-                                    .enumerate()
-                                    .filter(|(_, arg)| arg.id() == hir_id)
-                                    .map(|(index, _)| index)
-                                    .next()
-                            })
-                            .unwrap_or_else(|| {
-                                bug!("no arg matching AnonConst in path");
-                            });
-
-                        // We've encountered an `AnonConst` in some path, so we need to
-                        // figure out which generic parameter it corresponds to and return
-                        // the relevant type.
-                        let generics = match path.res {
-                            Res::Def(DefKind::Ctor(..), def_id) => {
-                                tcx.generics_of(tcx.parent(def_id).unwrap())
-                            }
-                            Res::Def(_, def_id) => tcx.generics_of(def_id),
-                            Res::Err => return tcx.types.err,
-                            res => {
-                                tcx.sess.delay_span_bug(
-                                    DUMMY_SP,
-                                    &format!("unexpected const parent path def {:?}", res,),
-                                );
-                                return tcx.types.err;
-                            }
-                        };
-
-                        generics
-                            .params
-                            .iter()
-                            .filter(|param| {
-                                if let ty::GenericParamDefKind::Const = param.kind {
-                                    true
-                                } else {
-                                    false
-                                }
-                            })
-                            .nth(arg_index)
-                            .map(|param| tcx.type_of(param.def_id))
-                            // This is no generic parameter associated with the arg. This is
-                            // probably from an extra arg where one is not needed.
-                            .unwrap_or(tcx.types.err)
-                    } else {
-                        tcx.sess.delay_span_bug(
-                            DUMMY_SP,
-                            &format!("unexpected const parent path {:?}", parent_node,),
-                        );
-                        return tcx.types.err;
-                    }
-                }
-
-                x => {
-                    tcx.sess.delay_span_bug(
-                        DUMMY_SP,
-                        &format!("unexpected const parent in type_of_def_id(): {:?}", x),
-                    );
-                    tcx.types.err
-                }
-            }
-        }
-
-        Node::GenericParam(param) => match &param.kind {
-            hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
-            hir::GenericParamKind::Const { ty: ref hir_ty, .. } => {
-                let ty = icx.to_ty(hir_ty);
-                if !tcx.features().const_compare_raw_pointers {
-                    let err = match ty.peel_refs().kind {
-                        ty::FnPtr(_) => Some("function pointers"),
-                        ty::RawPtr(_) => Some("raw pointers"),
-                        _ => None,
-                    };
-                    if let Some(unsupported_type) = err {
-                        feature_err(
-                            &tcx.sess.parse_sess,
-                            sym::const_compare_raw_pointers,
-                            hir_ty.span,
-                            &format!(
-                                "using {} as const generic parameters is unstable",
-                                unsupported_type
-                            ),
-                        )
-                        .emit();
-                    };
-                }
-                if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
-                    .is_some()
-                {
-                    struct_span_err!(
-                        tcx.sess,
-                        hir_ty.span,
-                        E0741,
-                        "the types of const generic parameters must derive `PartialEq` and `Eq`",
-                    )
-                    .span_label(
-                        hir_ty.span,
-                        format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
-                    )
-                    .emit();
-                }
-                ty
-            }
-            x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
-        },
-
-        x => {
-            bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
-        }
-    }
-}
-
-fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
-    use rustc_hir::{ImplItem, Item, TraitItem};
-
-    debug!("find_opaque_ty_constraints({:?})", def_id);
-
-    struct ConstraintLocator<'tcx> {
-        tcx: TyCtxt<'tcx>,
-        def_id: DefId,
-        // (first found type span, actual type, mapping from the opaque type's generic
-        // parameters to the concrete type's generic parameters)
-        //
-        // The mapping is an index for each use site of a generic parameter in the concrete type
-        //
-        // The indices index into the generic parameters on the opaque type.
-        found: Option<(Span, Ty<'tcx>, Vec<usize>)>,
-    }
-
-    impl ConstraintLocator<'tcx> {
-        fn check(&mut self, def_id: DefId) {
-            // Don't try to check items that cannot possibly constrain the type.
-            if !self.tcx.has_typeck_tables(def_id) {
-                debug!(
-                    "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no tables",
-                    self.def_id, def_id,
-                );
-                return;
-            }
-            let ty = self.tcx.typeck_tables_of(def_id).concrete_opaque_types.get(&self.def_id);
-            if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
-                debug!(
-                    "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
-                    self.def_id, def_id, ty,
-                );
-
-                // FIXME(oli-obk): trace the actual span from inference to improve errors.
-                let span = self.tcx.def_span(def_id);
-                // used to quickly look up the position of a generic parameter
-                let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
-                // Skipping binder is ok, since we only use this to find generic parameters and
-                // their positions.
-                for (idx, subst) in substs.iter().enumerate() {
-                    if let GenericArgKind::Type(ty) = subst.unpack() {
-                        if let ty::Param(p) = ty.kind {
-                            if index_map.insert(p, idx).is_some() {
-                                // There was already an entry for `p`, meaning a generic parameter
-                                // was used twice.
-                                self.tcx.sess.span_err(
-                                    span,
-                                    &format!(
-                                        "defining opaque type use restricts opaque \
-                                         type by using the generic parameter `{}` twice",
-                                        p,
-                                    ),
-                                );
-                                return;
-                            }
-                        } else {
-                            self.tcx.sess.delay_span_bug(
-                                span,
-                                &format!(
-                                    "non-defining opaque ty use in defining scope: {:?}, {:?}",
-                                    concrete_type, substs,
-                                ),
-                            );
-                        }
-                    }
-                }
-                // Compute the index within the opaque type for each generic parameter used in
-                // the concrete type.
-                let indices = concrete_type
-                    .subst(self.tcx, substs)
-                    .walk()
-                    .filter_map(|t| match &t.kind {
-                        ty::Param(p) => Some(*index_map.get(p).unwrap()),
-                        _ => None,
-                    })
-                    .collect();
-                let is_param = |ty: Ty<'_>| match ty.kind {
-                    ty::Param(_) => true,
-                    _ => false,
-                };
-                let bad_substs: Vec<_> = substs
-                    .iter()
-                    .enumerate()
-                    .filter_map(|(i, k)| {
-                        if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None }
-                    })
-                    .filter(|(_, ty)| !is_param(ty))
-                    .collect();
-
-                if !bad_substs.is_empty() {
-                    let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id);
-                    for (i, bad_subst) in bad_substs {
-                        self.tcx.sess.span_err(
-                            span,
-                            &format!(
-                                "defining opaque type use does not fully define opaque type: \
-                            generic parameter `{}` is specified as concrete type `{}`",
-                                identity_substs.type_at(i),
-                                bad_subst
-                            ),
-                        );
-                    }
-                } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
-                    let mut ty = concrete_type.walk().fuse();
-                    let mut p_ty = prev_ty.walk().fuse();
-                    let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) {
-                        // Type parameters are equal to any other type parameter for the purpose of
-                        // concrete type equality, as it is possible to obtain the same type just
-                        // by passing matching parameters to a function.
-                        (ty::Param(_), ty::Param(_)) => true,
-                        _ => t == p,
-                    });
-                    if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
-                        debug!("find_opaque_ty_constraints: span={:?}", span);
-                        // Found different concrete types for the opaque type.
-                        let mut err = self.tcx.sess.struct_span_err(
-                            span,
-                            "concrete type differs from previous defining opaque type use",
-                        );
-                        err.span_label(
-                            span,
-                            format!("expected `{}`, got `{}`", prev_ty, concrete_type),
-                        );
-                        err.span_note(prev_span, "previous use here");
-                        err.emit();
-                    } else if indices != *prev_indices {
-                        // Found "same" concrete types, but the generic parameter order differs.
-                        let mut err = self.tcx.sess.struct_span_err(
-                            span,
-                            "concrete type's generic parameters differ from previous defining use",
-                        );
-                        use std::fmt::Write;
-                        let mut s = String::new();
-                        write!(s, "expected [").unwrap();
-                        let list = |s: &mut String, indices: &Vec<usize>| {
-                            let mut indices = indices.iter().cloned();
-                            if let Some(first) = indices.next() {
-                                write!(s, "`{}`", substs[first]).unwrap();
-                                for i in indices {
-                                    write!(s, ", `{}`", substs[i]).unwrap();
-                                }
-                            }
-                        };
-                        list(&mut s, prev_indices);
-                        write!(s, "], got [").unwrap();
-                        list(&mut s, &indices);
-                        write!(s, "]").unwrap();
-                        err.span_label(span, s);
-                        err.span_note(prev_span, "previous use here");
-                        err.emit();
-                    }
-                } else {
-                    self.found = Some((span, concrete_type, indices));
-                }
-            } else {
-                debug!(
-                    "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
-                    self.def_id, def_id,
-                );
-            }
-        }
-    }
-
-    impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
-        type Map = Map<'tcx>;
-
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
-            intravisit::NestedVisitorMap::All(&self.tcx.hir())
-        }
-        fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
-            debug!("find_existential_constraints: visiting {:?}", it);
-            let def_id = self.tcx.hir().local_def_id(it.hir_id);
-            // The opaque type itself or its children are not within its reveal scope.
-            if def_id != self.def_id {
-                self.check(def_id);
-                intravisit::walk_item(self, it);
-            }
-        }
-        fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
-            debug!("find_existential_constraints: visiting {:?}", it);
-            let def_id = self.tcx.hir().local_def_id(it.hir_id);
-            // The opaque type itself or its children are not within its reveal scope.
-            if def_id != self.def_id {
-                self.check(def_id);
-                intravisit::walk_impl_item(self, it);
-            }
-        }
-        fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
-            debug!("find_existential_constraints: visiting {:?}", it);
-            let def_id = self.tcx.hir().local_def_id(it.hir_id);
-            self.check(def_id);
-            intravisit::walk_trait_item(self, it);
-        }
-    }
-
-    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let scope = tcx.hir().get_defining_scope(hir_id);
-    let mut locator = ConstraintLocator { def_id, tcx, found: None };
-
-    debug!("find_opaque_ty_constraints: scope={:?}", scope);
-
-    if scope == hir::CRATE_HIR_ID {
-        intravisit::walk_crate(&mut locator, tcx.hir().krate());
-    } else {
-        debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
-        match tcx.hir().get(scope) {
-            // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
-            // This allows our visitor to process the defining item itself, causing
-            // it to pick up any 'sibling' defining uses.
-            //
-            // For example, this code:
-            // ```
-            // fn foo() {
-            //     type Blah = impl Debug;
-            //     let my_closure = || -> Blah { true };
-            // }
-            // ```
-            //
-            // requires us to explicitly process `foo()` in order
-            // to notice the defining usage of `Blah`.
-            Node::Item(ref it) => locator.visit_item(it),
-            Node::ImplItem(ref it) => locator.visit_impl_item(it),
-            Node::TraitItem(ref it) => locator.visit_trait_item(it),
-            other => bug!("{:?} is not a valid scope for an opaque type item", other),
-        }
-    }
-
-    match locator.found {
-        Some((_, ty, _)) => ty,
-        None => {
-            let span = tcx.def_span(def_id);
-            tcx.sess.span_err(span, "could not find defining uses");
-            tcx.types.err
-        }
-    }
-}
-
 fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
     generic_args
         .iter()
@@ -1957,8 +1399,8 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
     }
 }
 
-pub fn get_infer_ret_ty(output: &'hir hir::FunctionRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> {
-    if let hir::FunctionRetTy::Return(ref ty) = output {
+pub fn get_infer_ret_ty(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> {
+    if let hir::FnRetTy::Return(ref ty) = output {
         if is_suggestable_infer_ty(ty) {
             return Some(&**ty);
         }
@@ -2185,7 +1627,6 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
 /// Returns a list of user-specified type predicates for the definition with ID `def_id`.
 /// N.B., this does not include any implied/inferred constraints.
 fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
-    use rustc_data_structures::fx::FxHashSet;
     use rustc_hir::*;
 
     debug!("explicit_predicates_of(def_id={:?})", def_id);
@@ -2676,7 +2117,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
         for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) {
             check(&input, ty)
         }
-        if let hir::FunctionRetTy::Return(ref ty) = decl.output {
+        if let hir::FnRetTy::Return(ref ty) = decl.output {
             check(&ty, *fty.output().skip_binder())
         }
     }
@@ -2877,7 +2318,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
         } else if attr.check_name(sym::thread_local) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
         } else if attr.check_name(sym::track_caller) {
-            if tcx.fn_sig(id).abi() != abi::Abi::Rust {
+            if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust {
                 struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
                     .emit();
             }
@@ -2898,7 +2339,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 codegen_fn_attrs.export_name = Some(s);
             }
         } else if attr.check_name(sym::target_feature) {
-            if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
+            if tcx.is_closure(id) || tcx.fn_sig(id).unsafety() == Unsafety::Normal {
                 let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions";
                 tcx.sess
                     .struct_span_err(attr.span, msg)