about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs38
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs10
-rw-r--r--compiler/rustc_expand/src/config.rs54
-rw-r--r--compiler/rustc_target/src/spec/illumos_base.rs11
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs98
8 files changed, 119 insertions, 100 deletions
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index b44553e4f6d..6101b90aea6 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -339,24 +339,32 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
         Some(_) | None => {}
     };
 
+    let filter = |s: &str| {
+        if s.is_empty() {
+            return None;
+        }
+        let feature = if s.starts_with("+") || s.starts_with("-") {
+            &s[1..]
+        } else {
+            return Some(s.to_string());
+        };
+        // Rustc-specific feature requests like `+crt-static` or `-crt-static`
+        // are not passed down to LLVM.
+        if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
+            return None;
+        }
+        // ... otherwise though we run through `to_llvm_feature` feature when
+        // passing requests down to LLVM. This means that all in-language
+        // features also work on the command line instead of having two
+        // different names when the LLVM name and the Rust name differ.
+        Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
+    };
+
     // Features implied by an implicit or explicit `--target`.
-    features.extend(
-        sess.target
-            .features
-            .split(',')
-            .filter(|f| !f.is_empty() && !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)))
-            .map(String::from),
-    );
+    features.extend(sess.target.features.split(',').filter_map(&filter));
 
     // -Ctarget-features
-    features.extend(
-        sess.opts
-            .cg
-            .target_feature
-            .split(',')
-            .filter(|f| !f.is_empty() && !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)))
-            .map(String::from),
-    );
+    features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
 
     features
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 401d379b0d1..929bdf22755 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -340,6 +340,14 @@ impl<'a> Linker for GccLinker<'a> {
     }
 
     fn link_dylib(&mut self, lib: Symbol, verbatim: bool, as_needed: bool) {
+        if self.sess.target.os == "illumos" && lib.as_str() == "c" {
+            // libc will be added via late_link_args on illumos so that it will
+            // appear last in the library search order.
+            // FIXME: This should be replaced by a more complete and generic
+            // mechanism for controlling the order of library arguments passed
+            // to the linker.
+            return;
+        }
         if !as_needed {
             if self.sess.target.is_like_osx {
                 // FIXME(81490): ld64 doesn't support these flags but macOS 11
@@ -813,11 +821,9 @@ impl<'a> Linker for MsvcLinker<'a> {
     }
 
     fn link_whole_staticlib(&mut self, lib: Symbol, verbatim: bool, _search_path: &[PathBuf]) {
-        self.link_staticlib(lib, verbatim);
         self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" }));
     }
     fn link_whole_rlib(&mut self, path: &Path) {
-        self.link_rlib(path);
         let mut arg = OsString::from("/WHOLEARCHIVE:");
         arg.push(path);
         self.cmd.arg(arg);
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 03c83f9c07b..f9140609c0f 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -464,31 +464,9 @@ impl<'a> StripUnconfigured<'a> {
                     return true;
                 }
             };
-            let error = |span, msg, suggestion: &str| {
-                let mut err = self.sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
-                if !suggestion.is_empty() {
-                    err.span_suggestion(
-                        span,
-                        "expected syntax is",
-                        suggestion.into(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                err.emit();
-                true
-            };
-            let span = meta_item.span;
-            match meta_item.meta_item_list() {
-                None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
-                Some([]) => error(span, "`cfg` predicate is not specified", ""),
-                Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
-                Some([single]) => match single.meta_item() {
-                    Some(meta_item) => {
-                        attr::cfg_matches(meta_item, &self.sess.parse_sess, self.features)
-                    }
-                    None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
-                },
-            }
+            parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
+                attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.features)
+            })
         })
     }
 
@@ -532,6 +510,32 @@ impl<'a> StripUnconfigured<'a> {
     }
 }
 
+pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
+    let error = |span, msg, suggestion: &str| {
+        let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
+        if !suggestion.is_empty() {
+            err.span_suggestion(
+                span,
+                "expected syntax is",
+                suggestion.into(),
+                Applicability::HasPlaceholders,
+            );
+        }
+        err.emit();
+        None
+    };
+    let span = meta_item.span;
+    match meta_item.meta_item_list() {
+        None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
+        Some([]) => error(span, "`cfg` predicate is not specified", ""),
+        Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
+        Some([single]) => match single.meta_item() {
+            Some(meta_item) => Some(meta_item),
+            None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
+        },
+    }
+}
+
 fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
     sess.check_name(attr, sym::cfg)
 }
diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs
index 2e365d210f3..2b8e046c46b 100644
--- a/compiler/rustc_target/src/spec/illumos_base.rs
+++ b/compiler/rustc_target/src/spec/illumos_base.rs
@@ -6,6 +6,17 @@ pub fn opts() -> TargetOptions {
     late_link_args.insert(
         LinkerFlavor::Gcc,
         vec![
+            // The illumos libc contains a stack unwinding implementation, as
+            // does libgcc_s.  The latter implementation includes several
+            // additional symbols that are not always in base libc.  To force
+            // the consistent use of just one unwinder, we ensure libc appears
+            // after libgcc_s in the NEEDED list for the resultant binary by
+            // ignoring any attempts to add it as a dynamic dependency until the
+            // very end.
+            // FIXME: This should be replaced by a more complete and generic
+            // mechanism for controlling the order of library arguments passed
+            // to the linker.
+            "-lc".to_string(),
             // LLVM will insert calls to the stack protector functions
             // "__stack_chk_fail" and "__stack_chk_guard" into code in native
             // object files.  Some platforms include these symbols directly in
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
index 28d9801b78c..359cb0f6881 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
     base.stack_probes = StackProbeType::Call;
 
     Target {
-        llvm_target: "x86_64-unknown-none-elf".to_string(),
+        llvm_target: "x86_64-unknown-hermit".to_string(),
         pointer_width: 64,
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .to_string(),
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 0c6a33b91ce..4d6caf07236 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -720,11 +720,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn select_obligations_where_possible(
         &self,
         fallback_has_occurred: bool,
-        mutate_fullfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
+        mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
     ) {
         let result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
         if let Err(mut errors) = result {
-            mutate_fullfillment_errors(&mut errors);
+            mutate_fulfillment_errors(&mut errors);
             self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
         }
     }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 80b5a9d4e62..3417bc01972 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -986,7 +986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             error.obligation.predicate.kind().skip_binder()
                         {
                             // If any of the type arguments in this path segment caused the
-                            // `FullfillmentError`, point at its span (#61860).
+                            // `FulfillmentError`, point at its span (#61860).
                             for arg in path
                                 .segments
                                 .iter()
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 4914f196afb..7436edccf84 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -43,7 +43,7 @@ struct CheckWfFcxBuilder<'tcx> {
 impl<'tcx> CheckWfFcxBuilder<'tcx> {
     fn with_fcx<F>(&mut self, f: F)
     where
-        F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>, TyCtxt<'tcx>) -> Vec<Ty<'tcx>>,
+        F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> Vec<Ty<'tcx>>,
     {
         let id = self.id;
         let span = self.span;
@@ -56,7 +56,7 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
                 // empty `param_env`.
                 check_false_global_bounds(&fcx, span, id);
             }
-            let wf_tys = f(&fcx, fcx.tcx);
+            let wf_tys = f(&fcx);
             fcx.select_all_obligations_or_error();
             fcx.regionck_item(id, span, &wf_tys);
         });
@@ -388,7 +388,7 @@ fn check_associated_item(
     debug!("check_associated_item: {:?}", item_id);
 
     let code = ObligationCauseCode::MiscObligation;
-    for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
+    for_id(tcx, item_id, span).with_fcx(|fcx| {
         let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
 
         let (mut implied_bounds, self_ty) = match item.container {
@@ -409,7 +409,6 @@ fn check_associated_item(
                 let sig = fcx.normalize_associated_types_in(span, sig);
                 let hir_sig = sig_if_method.expect("bad signature for method");
                 check_fn_or_method(
-                    tcx,
                     fcx,
                     item.ident.span,
                     sig,
@@ -467,9 +466,9 @@ fn check_type_defn<'tcx, F>(
 ) where
     F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
 {
-    for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
+    for_item(tcx, item).with_fcx(|fcx| {
         let variants = lookup_fields(fcx);
-        let packed = fcx.tcx.adt_def(item.def_id).repr.packed();
+        let packed = tcx.adt_def(item.def_id).repr.packed();
 
         for variant in &variants {
             // For DST, or when drop needs to copy things around, all
@@ -477,15 +476,14 @@ fn check_type_defn<'tcx, F>(
             let needs_drop_copy = || {
                 packed && {
                     let ty = variant.fields.last().unwrap().ty;
-                    let ty = fcx.tcx.erase_regions(ty);
+                    let ty = tcx.erase_regions(ty);
                     if ty.needs_infer() {
-                        fcx_tcx
-                            .sess
+                        tcx.sess
                             .delay_span_bug(item.span, &format!("inference variables in {:?}", ty));
                         // Just treat unresolved type expression as if it needs drop.
                         true
                     } else {
-                        ty.needs_drop(fcx_tcx, fcx_tcx.param_env(item.def_id))
+                        ty.needs_drop(tcx, tcx.param_env(item.def_id))
                     }
                 }
             };
@@ -497,7 +495,7 @@ fn check_type_defn<'tcx, F>(
                 let last = idx == variant.fields.len() - 1;
                 fcx.register_bound(
                     field.ty,
-                    fcx.tcx.require_lang_item(LangItem::Sized, None),
+                    tcx.require_lang_item(LangItem::Sized, None),
                     traits::ObligationCause::new(
                         field.span,
                         fcx.body_id,
@@ -524,11 +522,10 @@ fn check_type_defn<'tcx, F>(
 
             // Explicit `enum` discriminant values must const-evaluate successfully.
             if let Some(discr_def_id) = variant.explicit_discr {
-                let discr_substs =
-                    InternalSubsts::identity_for_item(fcx.tcx, discr_def_id.to_def_id());
+                let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
 
                 let cause = traits::ObligationCause::new(
-                    fcx.tcx.def_span(discr_def_id),
+                    tcx.def_span(discr_def_id),
                     fcx.body_id,
                     traits::MiscObligation,
                 );
@@ -539,12 +536,12 @@ fn check_type_defn<'tcx, F>(
                         ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
                         discr_substs,
                     )
-                    .to_predicate(fcx.tcx),
+                    .to_predicate(tcx),
                 ));
             }
         }
 
-        check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
+        check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
         // No implied bounds in a struct definition.
         vec![]
@@ -569,8 +566,9 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
         }
     }
 
-    for_item(tcx, item).with_fcx(|fcx, _| {
-        check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
+    // FIXME: this shouldn't use an `FnCtxt` at all.
+    for_item(tcx, item).with_fcx(|fcx| {
+        check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
         vec![]
     });
@@ -610,20 +608,12 @@ fn check_item_fn(
     span: Span,
     decl: &hir::FnDecl<'_>,
 ) {
-    for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
-        let def_id = fcx.tcx.hir().local_def_id(item_id);
-        let sig = fcx.tcx.fn_sig(def_id);
+    for_id(tcx, item_id, span).with_fcx(|fcx| {
+        let def_id = tcx.hir().local_def_id(item_id);
+        let sig = tcx.fn_sig(def_id);
         let sig = fcx.normalize_associated_types_in(span, sig);
         let mut implied_bounds = vec![];
-        check_fn_or_method(
-            tcx,
-            fcx,
-            ident.span,
-            sig,
-            decl,
-            def_id.to_def_id(),
-            &mut implied_bounds,
-        );
+        check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
         implied_bounds
     })
 }
@@ -631,7 +621,7 @@ fn check_item_fn(
 fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_foreign_ty: bool) {
     debug!("check_item_type: {:?}", item_id);
 
-    for_id(tcx, item_id, ty_span).with_fcx(|fcx, tcx| {
+    for_id(tcx, item_id, ty_span).with_fcx(|fcx| {
         let ty = tcx.type_of(tcx.hir().local_def_id(item_id));
         let item_ty = fcx.normalize_associated_types_in(ty_span, ty);
 
@@ -647,7 +637,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         if forbid_unsized {
             fcx.register_bound(
                 item_ty,
-                fcx.tcx.require_lang_item(LangItem::Sized, None),
+                tcx.require_lang_item(LangItem::Sized, None),
                 traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation),
             );
         }
@@ -665,13 +655,13 @@ fn check_impl<'tcx>(
 ) {
     debug!("check_impl: {:?}", item);
 
-    for_item(tcx, item).with_fcx(|fcx, tcx| {
+    for_item(tcx, item).with_fcx(|fcx| {
         match *ast_trait_ref {
             Some(ref ast_trait_ref) => {
                 // `#[rustc_reservation_impl]` impls are not real impls and
                 // therefore don't need to be WF (the trait's `Self: Trait` predicate
                 // won't hold).
-                let trait_ref = fcx.tcx.impl_trait_ref(item.def_id).unwrap();
+                let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
                 let trait_ref =
                     fcx.normalize_associated_types_in(ast_trait_ref.path.span, trait_ref);
                 let obligations = traits::wf::trait_obligations(
@@ -687,7 +677,7 @@ fn check_impl<'tcx>(
                 }
             }
             None => {
-                let self_ty = fcx.tcx.type_of(item.def_id);
+                let self_ty = tcx.type_of(item.def_id);
                 let self_ty = fcx.normalize_associated_types_in(item.span, self_ty);
                 fcx.register_wf_obligation(
                     self_ty.into(),
@@ -697,7 +687,7 @@ fn check_impl<'tcx>(
             }
         }
 
-        check_where_clauses(tcx, fcx, item.span, item.def_id.to_def_id(), None);
+        check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
         fcx.impl_implied_bounds(item.def_id.to_def_id(), item.span)
     });
@@ -705,15 +695,15 @@ fn check_impl<'tcx>(
 
 /// Checks where-clauses and inline bounds that are declared on `def_id`.
 fn check_where_clauses<'tcx, 'fcx>(
-    tcx: TyCtxt<'tcx>,
     fcx: &FnCtxt<'fcx, 'tcx>,
     span: Span,
     def_id: DefId,
     return_ty: Option<(Ty<'tcx>, Span)>,
 ) {
     debug!("check_where_clauses(def_id={:?}, return_ty={:?})", def_id, return_ty);
+    let tcx = fcx.tcx;
 
-    let predicates = fcx.tcx.predicates_of(def_id);
+    let predicates = tcx.predicates_of(def_id);
     let generics = tcx.generics_of(def_id);
 
     let is_our_default = |def: &ty::GenericParamDef| match def.kind {
@@ -734,14 +724,14 @@ fn check_where_clauses<'tcx, 'fcx>(
         match param.kind {
             GenericParamDefKind::Type { .. } => {
                 if is_our_default(&param) {
-                    let ty = fcx.tcx.type_of(param.def_id);
+                    let ty = tcx.type_of(param.def_id);
                     // Ignore dependent defaults -- that is, where the default of one type
                     // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
                     // be sure if it will error or not as user might always specify the other.
                     if !ty.needs_subst() {
                         fcx.register_wf_obligation(
                             ty.into(),
-                            fcx.tcx.def_span(param.def_id),
+                            tcx.def_span(param.def_id),
                             ObligationCauseCode::MiscObligation,
                         );
                     }
@@ -754,7 +744,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     let default_ct = tcx.const_param_default(param.def_id);
                     fcx.register_wf_obligation(
                         default_ct.into(),
-                        fcx.tcx.def_span(param.def_id),
+                        tcx.def_span(param.def_id),
                         ObligationCauseCode::MiscObligation,
                     );
                 }
@@ -772,17 +762,17 @@ fn check_where_clauses<'tcx, 'fcx>(
     // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
     //
     // First we build the defaulted substitution.
-    let substs = InternalSubsts::for_item(fcx.tcx, def_id, |param, _| {
+    let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
         match param.kind {
             GenericParamDefKind::Lifetime => {
                 // All regions are identity.
-                fcx.tcx.mk_param_from_def(param)
+                tcx.mk_param_from_def(param)
             }
 
             GenericParamDefKind::Type { .. } => {
                 // If the param has a default, ...
                 if is_our_default(param) {
-                    let default_ty = fcx.tcx.type_of(param.def_id);
+                    let default_ty = tcx.type_of(param.def_id);
                     // ... and it's not a dependent default, ...
                     if !default_ty.needs_subst() {
                         // ... then substitute it with the default.
@@ -790,7 +780,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     }
                 }
 
-                fcx.tcx.mk_param_from_def(param)
+                tcx.mk_param_from_def(param)
             }
             GenericParamDefKind::Const { .. } => {
                 // FIXME(const_generics_defaults): I(@lcnr) feel like always
@@ -811,7 +801,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     }
                 }
 
-                fcx.tcx.mk_param_from_def(param)
+                tcx.mk_param_from_def(param)
             }
         }
     });
@@ -848,7 +838,7 @@ fn check_where_clauses<'tcx, 'fcx>(
             }
             let mut param_count = CountParams::default();
             let has_region = pred.visit_with(&mut param_count).is_break();
-            let substituted_pred = pred.subst(fcx.tcx, substs);
+            let substituted_pred = pred.subst(tcx, substs);
             // Don't check non-defaulted params, dependent defaults (including lifetimes)
             // or preds with multiple params.
             if substituted_pred.has_param_types_or_consts()
@@ -879,14 +869,14 @@ fn check_where_clauses<'tcx, 'fcx>(
             traits::Obligation::new(cause, fcx.param_env, pred)
         });
 
-    let predicates = predicates.instantiate_identity(fcx.tcx);
+    let predicates = predicates.instantiate_identity(tcx);
 
     if let Some((mut return_ty, span)) = return_ty {
         if return_ty.has_infer_types_or_consts() {
             fcx.select_obligations_where_possible(false, |_| {});
             return_ty = fcx.resolve_vars_if_possible(return_ty);
         }
-        check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
+        check_opaque_types(fcx, def_id.expect_local(), span, return_ty);
     }
 
     let predicates = fcx.normalize_associated_types_in(span, predicates);
@@ -905,7 +895,6 @@ fn check_where_clauses<'tcx, 'fcx>(
 }
 
 fn check_fn_or_method<'fcx, 'tcx>(
-    tcx: TyCtxt<'tcx>,
     fcx: &FnCtxt<'fcx, 'tcx>,
     span: Span,
     sig: ty::PolyFnSig<'tcx>,
@@ -930,7 +919,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
     // FIXME(#25759) return types should not be implied bounds
     implied_bounds.push(sig.output());
 
-    check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
+    check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
 }
 
 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
@@ -953,15 +942,16 @@ fn check_fn_or_method<'fcx, 'tcx>(
 /// ```
 ///
 fn check_opaque_types<'fcx, 'tcx>(
-    tcx: TyCtxt<'tcx>,
     fcx: &FnCtxt<'fcx, 'tcx>,
     fn_def_id: LocalDefId,
     span: Span,
     ty: Ty<'tcx>,
 ) {
-    trace!("check_opaque_types(ty={:?})", ty);
+    trace!("check_opaque_types(fn_def_id={:?}, ty={:?})", fn_def_id, ty);
+    let tcx = fcx.tcx;
+
     ty.fold_with(&mut ty::fold::BottomUpFolder {
-        tcx: fcx.tcx,
+        tcx,
         ty_op: |ty| {
             if let ty::Opaque(def_id, substs) = *ty.kind() {
                 trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);