about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-04 03:52:29 +0000
committerbors <bors@rust-lang.org>2022-08-04 03:52:29 +0000
commitcaee496150a551fe1b9f77b3a58f7e66d54bc824 (patch)
tree77717b7ad2e32bc0d7b20c637953a81601cffaa8 /compiler
parent1ad56350cd3d7f8260c44433800f687f8e0ede28 (diff)
parentf8e6617239a8412a983c9a6b6af79d0eff3cdce0 (diff)
downloadrust-caee496150a551fe1b9f77b3a58f7e66d54bc824.tar.gz
rust-caee496150a551fe1b9f77b3a58f7e66d54bc824.zip
Auto merge of #100120 - matthiaskrgr:rollup-g6ycykq, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #98771 (Add support for link-flavor rust-lld for iOS, tvOS and watchOS)
 - #98835 (relate `closure_substs.parent_substs()` to parent fn in NLL)
 - #99746 (Use `TraitEngine` in more places that don't specifically need `FulfillmentContext::new_in_snapshot`)
 - #99786 (Recover from C++ style `enum struct`)
 - #99795 (Delay a bug when failed to normalize trait ref during specialization)
 - #100029 (Prevent ICE for `doc_alias` on match arm, statement, expression)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs28
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs17
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs4
-rw-r--r--compiler/rustc_hir/src/target.rs90
-rw-r--r--compiler/rustc_parse/src/parser/item.rs19
-rw-r--r--compiler/rustc_passes/src/check_attr.rs31
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs11
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs19
-rw-r--r--compiler/rustc_target/src/spec/apple_sdk_base.rs54
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs5
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs4
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs5
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_typeck/src/hir_wf_check.rs4
-rw-r--r--compiler/rustc_typeck/src/outlives/outlives_bounds.rs4
22 files changed, 267 insertions, 89 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index f7d35da0259..d32b1edcd8f 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2619,6 +2619,34 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             );
         }
 
+        // Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
+        let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
+
+        let parent_substs = match tcx.def_kind(def_id) {
+            DefKind::Closure => substs.as_closure().parent_substs(),
+            DefKind::Generator => substs.as_generator().parent_substs(),
+            DefKind::InlineConst => substs.as_inline_const().parent_substs(),
+            other => bug!("unexpected item {:?}", other),
+        };
+        let parent_substs = tcx.mk_substs(parent_substs.iter());
+
+        assert_eq!(typeck_root_substs.len(), parent_substs.len());
+        if let Err(_) = self.eq_substs(
+            typeck_root_substs,
+            parent_substs,
+            location.to_locations(),
+            ConstraintCategory::BoringNoLocation,
+        ) {
+            span_mirbug!(
+                self,
+                def_id,
+                "could not relate closure to parent {:?} != {:?}",
+                typeck_root_substs,
+                parent_substs
+            );
+        }
+
         tcx.predicates_of(def_id).instantiate(tcx, substs)
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index c45850c6d84..c97a6a1a658 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -38,6 +38,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         .relate(a, b)?;
         Ok(())
     }
+
+    /// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
+    pub(super) fn eq_substs(
+        &mut self,
+        a: ty::SubstsRef<'tcx>,
+        b: ty::SubstsRef<'tcx>,
+        locations: Locations,
+        category: ConstraintCategory<'tcx>,
+    ) -> Fallible<()> {
+        TypeRelating::new(
+            self.infcx,
+            NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
+            ty::Variance::Invariant,
+        )
+        .relate(a, b)?;
+        Ok(())
+    }
 }
 
 struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 326dce8011e..63207803e32 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2675,7 +2675,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
     let llvm_target = &sess.target.llvm_target;
     if sess.target.vendor != "apple"
         || !matches!(os.as_ref(), "ios" | "tvos" | "watchos")
-        || flavor != LinkerFlavor::Gcc
+        || (flavor != LinkerFlavor::Gcc && flavor != LinkerFlavor::Lld(LldFlavor::Ld64))
     {
         return;
     }
@@ -2706,13 +2706,16 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
             return;
         }
     };
-    if llvm_target.contains("macabi") {
-        cmd.args(&["-target", llvm_target])
-    } else {
-        let arch_name = llvm_target.split('-').next().expect("LLVM target must have a hyphen");
-        cmd.args(&["-arch", arch_name])
+
+    match flavor {
+        LinkerFlavor::Gcc => {
+            cmd.args(&["-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
+        }
+        LinkerFlavor::Lld(LldFlavor::Ld64) => {
+            cmd.args(&["-syslibroot", &sdk_root]);
+        }
+        _ => unreachable!(),
     }
-    cmd.args(&["-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
 }
 
 fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index e0994451172..c8a63c9c3f8 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::{
-    self, FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext,
+    self, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngineExt,
 };
 
 use super::ConstCx;
@@ -191,7 +191,7 @@ impl Qualif for NeedsNonConstDrop {
 
             // If we successfully found one, then select all of the predicates
             // implied by our const drop impl.
-            let mut fcx = FulfillmentContext::new();
+            let mut fcx = <dyn TraitEngine<'tcx>>::new(cx.tcx);
             for nested in impl_src.nested_obligations() {
                 fcx.register_predicate_obligation(&infcx, nested);
             }
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index 96dd00ec5cf..6236dea10c8 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -60,51 +60,7 @@ pub enum Target {
 
 impl Display for Target {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "{}",
-            match *self {
-                Target::ExternCrate => "extern crate",
-                Target::Use => "use",
-                Target::Static => "static item",
-                Target::Const => "constant item",
-                Target::Fn => "function",
-                Target::Closure => "closure",
-                Target::Mod => "module",
-                Target::ForeignMod => "foreign module",
-                Target::GlobalAsm => "global asm",
-                Target::TyAlias => "type alias",
-                Target::OpaqueTy => "opaque type",
-                Target::Enum => "enum",
-                Target::Variant => "enum variant",
-                Target::Struct => "struct",
-                Target::Field => "struct field",
-                Target::Union => "union",
-                Target::Trait => "trait",
-                Target::TraitAlias => "trait alias",
-                Target::Impl => "item",
-                Target::Expression => "expression",
-                Target::Statement => "statement",
-                Target::Arm => "match arm",
-                Target::AssocConst => "associated const",
-                Target::Method(kind) => match kind {
-                    MethodKind::Inherent => "inherent method",
-                    MethodKind::Trait { body: false } => "required trait method",
-                    MethodKind::Trait { body: true } => "provided trait method",
-                },
-                Target::AssocTy => "associated type",
-                Target::ForeignFn => "foreign function",
-                Target::ForeignStatic => "foreign static item",
-                Target::ForeignTy => "foreign type",
-                Target::GenericParam(kind) => match kind {
-                    GenericParamKind::Type => "type parameter",
-                    GenericParamKind::Lifetime => "lifetime parameter",
-                    GenericParamKind::Const => "const parameter",
-                },
-                Target::MacroDef => "macro def",
-                Target::Param => "function param",
-            }
-        )
+        write!(f, "{}", Self::name(*self))
     }
 }
 
@@ -185,4 +141,48 @@ impl Target {
             hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const),
         }
     }
+
+    pub fn name(self) -> &'static str {
+        match self {
+            Target::ExternCrate => "extern crate",
+            Target::Use => "use",
+            Target::Static => "static item",
+            Target::Const => "constant item",
+            Target::Fn => "function",
+            Target::Closure => "closure",
+            Target::Mod => "module",
+            Target::ForeignMod => "foreign module",
+            Target::GlobalAsm => "global asm",
+            Target::TyAlias => "type alias",
+            Target::OpaqueTy => "opaque type",
+            Target::Enum => "enum",
+            Target::Variant => "enum variant",
+            Target::Struct => "struct",
+            Target::Field => "struct field",
+            Target::Union => "union",
+            Target::Trait => "trait",
+            Target::TraitAlias => "trait alias",
+            Target::Impl => "implementation block",
+            Target::Expression => "expression",
+            Target::Statement => "statement",
+            Target::Arm => "match arm",
+            Target::AssocConst => "associated const",
+            Target::Method(kind) => match kind {
+                MethodKind::Inherent => "inherent method",
+                MethodKind::Trait { body: false } => "required trait method",
+                MethodKind::Trait { body: true } => "provided trait method",
+            },
+            Target::AssocTy => "associated type",
+            Target::ForeignFn => "foreign function",
+            Target::ForeignStatic => "foreign static item",
+            Target::ForeignTy => "foreign type",
+            Target::GenericParam(kind) => match kind {
+                GenericParamKind::Type => "type parameter",
+                GenericParamKind::Lifetime => "lifetime parameter",
+                GenericParamKind::Const => "const parameter",
+            },
+            Target::MacroDef => "macro def",
+            Target::Param => "function param",
+        }
+    }
 }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 2c1e5807aa7..5670729253d 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1216,6 +1216,25 @@ impl<'a> Parser<'a> {
 
     /// Parses an enum declaration.
     fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
+        if self.token.is_keyword(kw::Struct) {
+            let mut err = self.struct_span_err(
+                self.prev_token.span.to(self.token.span),
+                "`enum` and `struct` are mutually exclusive",
+            );
+            err.span_suggestion(
+                self.prev_token.span.to(self.token.span),
+                "replace `enum struct` with",
+                "enum",
+                Applicability::MachineApplicable,
+            );
+            if self.look_ahead(1, |t| t.is_ident()) {
+                self.bump();
+                err.emit();
+            } else {
+                return Err(err);
+            }
+        }
+
         let id = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
         generics.where_clause = self.parse_where_clause()?;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index fde12b9eee6..5b7d44e41cf 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -596,8 +596,6 @@ impl CheckAttrVisitor<'_> {
 
         let span = meta.span();
         if let Some(location) = match target {
-            Target::Impl => Some("implementation block"),
-            Target::ForeignMod => Some("extern block"),
             Target::AssocTy => {
                 let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
                 let containing_item = self.tcx.hir().expect_item(parent_hir_id);
@@ -619,7 +617,34 @@ impl CheckAttrVisitor<'_> {
             }
             // we check the validity of params elsewhere
             Target::Param => return false,
-            _ => None,
+            Target::Expression
+            | Target::Statement
+            | Target::Arm
+            | Target::ForeignMod
+            | Target::Closure
+            | Target::Impl => Some(target.name()),
+            Target::ExternCrate
+            | Target::Use
+            | Target::Static
+            | Target::Const
+            | Target::Fn
+            | Target::Mod
+            | Target::GlobalAsm
+            | Target::TyAlias
+            | Target::OpaqueTy
+            | Target::Enum
+            | Target::Variant
+            | Target::Struct
+            | Target::Field
+            | Target::Union
+            | Target::Trait
+            | Target::TraitAlias
+            | Target::Method(..)
+            | Target::ForeignFn
+            | Target::ForeignStatic
+            | Target::ForeignTy
+            | Target::GenericParam(..)
+            | Target::MacroDef => None,
         } {
             tcx.sess.emit_err(errors::DocAliasBadLocation { span, attr_str, location });
             return false;
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 57634cbbfb1..1dad07a9a42 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -1,9 +1,14 @@
 use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
+    let llvm_target = "arm64-apple-ios14.0-macabi";
+
+    let mut base = opts("ios", Arch::Arm64_macabi);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-target", llvm_target]);
+
     Target {
-        llvm_target: "arm64-apple-ios14.0-macabi".into(),
+        llvm_target: llvm_target.into(),
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
@@ -21,7 +26,7 @@ pub fn target() -> Target {
                 -disable-llvm-passes\0\
                 -Os\0"
                 .into(),
-            ..opts("ios", Arch::Arm64_macabi)
+            ..base
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 9bfae46ef32..15e4fb9be63 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -109,15 +109,34 @@ pub fn ios_llvm_target(arch: &str) -> String {
     format!("{}-apple-ios{}.{}.0", arch, major, minor)
 }
 
+pub fn ios_lld_platform_version() -> String {
+    let (major, minor) = ios_deployment_target();
+    format!("{}.{}", major, minor)
+}
+
 pub fn ios_sim_llvm_target(arch: &str) -> String {
     let (major, minor) = ios_deployment_target();
     format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
 }
 
+fn tvos_deployment_target() -> (u32, u32) {
+    deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
+}
+
+pub fn tvos_lld_platform_version() -> String {
+    let (major, minor) = tvos_deployment_target();
+    format!("{}.{}", major, minor)
+}
+
 fn watchos_deployment_target() -> (u32, u32) {
     deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))
 }
 
+pub fn watchos_lld_platform_version() -> String {
+    let (major, minor) = watchos_deployment_target();
+    format!("{}.{}", major, minor)
+}
+
 pub fn watchos_sim_llvm_target(arch: &str) -> String {
     let (major, minor) = watchos_deployment_target();
     format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor)
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
index 0328ea98c48..d77558f0f84 100644
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -1,4 +1,4 @@
-use crate::{spec::cvs, spec::TargetOptions};
+use crate::spec::{cvs, LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
 use std::borrow::Cow;
 
 use Arch::*;
@@ -17,6 +17,18 @@ pub enum Arch {
     Arm64_sim,
 }
 
+fn target_arch_name(arch: Arch) -> &'static str {
+    match arch {
+        Armv7 => "armv7",
+        Armv7k => "armv7k",
+        Armv7s => "armv7s",
+        Arm64 | Arm64_macabi | Arm64_sim => "arm64",
+        Arm64_32 => "arm64_32",
+        I386 => "i386",
+        X86_64 | X86_64_macabi => "x86_64",
+    }
+}
+
 fn target_abi(arch: Arch) -> &'static str {
     match arch {
         Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "",
@@ -49,11 +61,51 @@ fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> {
     }
 }
 
+fn pre_link_args(os: &'static str, arch: Arch) -> LinkArgs {
+    let mut args = LinkArgs::new();
+
+    let target_abi = target_abi(arch);
+
+    let platform_name = match target_abi {
+        "sim" => format!("{}-simulator", os),
+        "macabi" => "mac-catalyst".to_string(),
+        _ => os.to_string(),
+    };
+
+    let platform_version = match os.as_ref() {
+        "ios" => super::apple_base::ios_lld_platform_version(),
+        "tvos" => super::apple_base::tvos_lld_platform_version(),
+        "watchos" => super::apple_base::watchos_lld_platform_version(),
+        _ => unreachable!(),
+    };
+
+    let arch_str = target_arch_name(arch);
+
+    if target_abi != "macabi" {
+        args.insert(LinkerFlavor::Gcc, vec!["-arch".into(), arch_str.into()]);
+    }
+
+    args.insert(
+        LinkerFlavor::Lld(LldFlavor::Ld64),
+        vec![
+            "-arch".into(),
+            arch_str.into(),
+            "-platform_version".into(),
+            platform_name.into(),
+            platform_version.clone().into(),
+            platform_version.into(),
+        ],
+    );
+
+    args
+}
+
 pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
     TargetOptions {
         abi: target_abi(arch).into(),
         cpu: target_cpu(arch).into(),
         dynamic_linking: false,
+        pre_link_args: pre_link_args(os, arch),
         link_env_remove: link_env_remove(arch),
         has_thread_local: false,
         ..super::apple_base::opts(os)
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index c7c5a231901..1db6db78b17 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -46,7 +46,10 @@ impl Target {
                         )
                     }
                     (LinkerFlavor::Gcc, LldFlavor::Ld64) => {
-                        assert_matches!(flavor, LinkerFlavor::Gcc)
+                        assert_matches!(
+                            flavor,
+                            LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Gcc
+                        )
                     }
                     (LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => {
                         assert_matches!(
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index c75632571ad..2122bcd37fc 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -1,10 +1,14 @@
 use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{StackProbeType, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let base = opts("ios", Arch::X86_64_macabi);
+    let llvm_target = "x86_64-apple-ios13.0-macabi";
+
+    let mut base = opts("ios", Arch::X86_64_macabi);
+    base.add_pre_link_args(LinkerFlavor::Gcc, &["-target", llvm_target]);
+
     Target {
-        llvm_target: "x86_64-apple-ios13.0-macabi".into(),
+        llvm_target: llvm_target.into(),
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .into(),
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 5763e6d1b55..294c81d0b21 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -205,7 +205,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             // At this point, we already have all of the bounds we need. FulfillmentContext is used
             // to store all of the necessary region/lifetime bounds in the InferContext, as well as
             // an additional sanity check.
-            let mut fulfill = FulfillmentContext::new();
+            let mut fulfill = <dyn TraitEngine<'tcx>>::new(tcx);
             fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy());
             let errors = fulfill.select_all_or_error(&infcx);
 
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 4b575ea660a..c0700748c79 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -5,7 +5,7 @@
 
 use crate::infer::{DefiningAnchor, TyCtxtInferExt};
 use crate::traits::{
-    FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
+    ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
     Unimplemented,
 };
 use rustc_middle::traits::CodegenObligationError;
@@ -53,7 +53,7 @@ pub fn codegen_fulfill_obligation<'tcx>(
         // Currently, we use a fulfillment context to completely resolve
         // all nested obligations. This is because they can inform the
         // inference of the impl's type parameters.
-        let mut fulfill_cx = FulfillmentContext::new();
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
         let impl_source = selection.map(|predicate| {
             fulfill_cx.register_predicate_obligation(&infcx, predicate);
         });
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index f62ccb99df5..1c8cdf4ca8f 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -11,7 +11,7 @@ use crate::traits::util::impl_subject_and_oblig;
 use crate::traits::SkipLeakCheck;
 use crate::traits::{
     self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
-    PredicateObligations, SelectionContext,
+    PredicateObligations, SelectionContext, TraitEngineExt,
 };
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::Diagnostic;
@@ -385,7 +385,7 @@ fn resolve_negative_obligation<'cx, 'tcx>(
         return false;
     };
 
-    let mut fulfillment_cx = FulfillmentContext::new();
+    let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
     fulfillment_cx.register_predicate_obligation(infcx, o);
 
     let errors = fulfillment_cx.select_all_or_error(infcx);
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index d0a17f712d3..9c6bb0731f4 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -164,7 +164,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
         // The handling of regions in this area of the code is terrible,
         // see issue #29149. We should be able to improve on this with
         // NLL.
-        let mut fulfill_cx = FulfillmentContext::new();
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
 
         // We can use a dummy node-id here because we won't pay any mind
         // to region obligations that arise (there shouldn't really be any
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 5f77aae6f22..6223c5ea339 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -14,7 +14,9 @@ use specialization_graph::GraphExt;
 
 use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
+use crate::traits::{
+    self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine, TraitEngineExt,
+};
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder};
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -24,8 +26,8 @@ use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
 use rustc_span::{Span, DUMMY_SP};
 
-use super::util;
-use super::{FulfillmentContext, SelectionContext};
+use super::SelectionContext;
+use super::{util, FulfillmentContext};
 
 /// Information pertinent to an overlapping impl error.
 #[derive(Debug)]
@@ -149,8 +151,6 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
 
     // Create an infcx, taking the predicates of impl1 as assumptions:
     tcx.infer_ctxt().enter(|infcx| {
-        // Normalize the trait reference. The WF rules ought to ensure
-        // that this always succeeds.
         let impl1_trait_ref = match traits::fully_normalize(
             &infcx,
             FulfillmentContext::new(),
@@ -159,8 +159,12 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
             impl1_trait_ref,
         ) {
             Ok(impl1_trait_ref) => impl1_trait_ref,
-            Err(err) => {
-                bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
+            Err(_errors) => {
+                tcx.sess.delay_span_bug(
+                    tcx.def_span(impl1_def_id),
+                    format!("failed to fully normalize {impl1_trait_ref}"),
+                );
+                impl1_trait_ref
             }
         };
 
@@ -207,7 +211,7 @@ fn fulfill_implication<'a, 'tcx>(
     // (which are packed up in penv)
 
     infcx.save_and_restore_in_snapshot_flag(|infcx| {
-        let mut fulfill_cx = FulfillmentContext::new();
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
         for oblig in obligations.chain(more_obligations) {
             fulfill_cx.register_predicate_obligation(&infcx, oblig);
         }
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index c278752e3d9..5829a0f92ee 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -1,6 +1,6 @@
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::ObligationCause;
-use crate::traits::{self, TraitEngine};
+use crate::traits::{TraitEngine, TraitEngineExt};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -72,7 +72,7 @@ fn type_marked_structural<'tcx>(
     adt_ty: Ty<'tcx>,
     cause: ObligationCause<'tcx>,
 ) -> bool {
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
+    let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
     // require `#[derive(PartialEq)]`
     let structural_peq_def_id =
         infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 4d4d55de5f4..e3e78f70b15 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -14,8 +14,7 @@ use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
 use rustc_trait_selection::traits::wf;
-use rustc_trait_selection::traits::FulfillmentContext;
-use rustc_trait_selection::traits::TraitEngine;
+use rustc_trait_selection::traits::{TraitEngine, TraitEngineExt};
 use smallvec::{smallvec, SmallVec};
 
 pub(crate) fn provide(p: &mut Providers) {
@@ -52,7 +51,7 @@ fn compute_implied_outlives_bounds<'tcx>(
 
     let mut implied_bounds = vec![];
 
-    let mut fulfill_cx = FulfillmentContext::new();
+    let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
 
     while let Some(arg) = wf_args.pop() {
         if !checked_wf_args.insert(arg) {
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index c23cbd71723..50946cc1def 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -109,7 +109,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
                 // it is not immediately clear why Copy is not implemented for a field, since
                 // all we point at is the field itself.
                 tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
-                    let mut fulfill_cx = traits::FulfillmentContext::new();
+                    let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
                     fulfill_cx.register_bound(
                         &infcx,
                         param_env,
diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs
index 3dc728271b0..55c7a15f9bc 100644
--- a/compiler/rustc_typeck/src/hir_wf_check.rs
+++ b/compiler/rustc_typeck/src/hir_wf_check.rs
@@ -7,7 +7,7 @@ use rustc_infer::traits::TraitEngine;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
-use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::{self, TraitEngineExt};
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers { diagnostic_hir_wf_check, ..*providers };
@@ -66,7 +66,7 @@ fn diagnostic_hir_wf_check<'tcx>(
     impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
         fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
             self.tcx.infer_ctxt().enter(|infcx| {
-                let mut fulfill = traits::FulfillmentContext::new();
+                let mut fulfill = <dyn TraitEngine<'tcx>>::new(self.tcx);
                 let tcx_ty =
                     self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
                 let cause = traits::ObligationCause::new(
diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
index 70b8bcd0220..229a6465084 100644
--- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
+++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::{self, Ty};
 use rustc_trait_selection::infer::InferCtxt;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::query::NoSolution;
-use rustc_trait_selection::traits::{FulfillmentContext, ObligationCause, TraitEngine};
+use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
@@ -63,7 +63,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
         if let Some(constraints) = constraints {
             // Instantiation may have produced new inference variables and constraints on those
             // variables. Process these constraints.
-            let mut fulfill_cx = FulfillmentContext::new();
+            let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx);
             let cause = ObligationCause::misc(span, body_id);
             for &constraint in &constraints.outlives {
                 let obligation = self.query_outlives_constraint_to_obligation(