Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: The three printed TypeIds should be identical, as with the behavior in Rust <=1.70 Instead, this happened: switch between rust versions. I could not find reference in the that could explain such behavioral changes.
if my bisection is correct, this surfaced in commit cc (makes sense?)
I do not believe that is the correct PR to point at. Bisecting anything related to MIR opts can be tricky because you need to stabilize the MIR opt pipeline against changes like in that PR which don't actually implement any new behavior, they just change the meaning of MIR opt levels. Try bisecting with ? The above PR just changes the opt level 3 inliner behavior to be the default.
Reproduces since before with
This has to do with the fact that this impl: ... applies even when . Therefore in a polymorphic function like , we're eagerly inlining from that impl even though during monomorphization we'd prefer the built-in candidate instead. This seems problematic.
WG-prioritization assigning priority (). label -I-prioritize +P-high

Discussion:
_ => false, } } <ins> pub fn is_known_rigid(self) -> bool { match self.kind() { Bool | Char | Int(_) | Uint(_) | Float(_) | Adt(_, _) | Foreign(_) | Str | Array(_, _) | Slice(_) | RawPtr(_) | Ref(_, _, _) | FnDef(_, _) | FnPtr(_) | Dynamic(_, _, _) | Closure(_, _) | Generator(_, _, _) | GeneratorWitness(_) | GeneratorWitnessMIR(_, _) | Never | Tuple(_) => true, Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false, } } </ins> } /// Extra information about why we ended up with a particular variance.

false } }; if !eligible { return Ok(None); } <ins> // HACK: We may have overlapping `dyn Trait` built-in impls and // user-provided blanket impls. Detect that case here, and return // ambiguity. // // This should not affect totally monomorphized contexts, only // resolve calls that happen polymorphically, such as the mir-inliner // and const-prop (and also some lints). let self_ty = rcvr_args.type_at(0); if !self_ty.is_known_rigid() { let predicates = tcx .predicates_of(impl_data.impl_def_id) .instantiate(tcx, impl_data.args) .predicates; let sized_def_id = tcx.lang_items().sized_trait(); // If we find a `Self: Sized` bound on the item, then we know // that `dyn Trait` can certainly never apply here. if !predicates.into_iter().filter_map(ty::Clause::as_trait_clause).any(|clause| { Some(clause.def_id()) == sized_def_id && clause.skip_binder().self_ty() == self_ty }) { return Ok(None); } } </ins> // Any final impl is required to define all associated items. if !leaf_def.item.defaultness(tcx).has_value() { let guard = tcx.sess.delay_span_bug(

<ins> - // MIR for `call` before Inline + // MIR for `call` after Inline fn call(_1: &T) -> TypeId { debug s => _1; let mut _0: std::any::TypeId; let mut _2: &T; bb0: { StorageLive(_2); _2 = &(*_1); _0 = <T as Any>::type_id(move _2) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_2); return; } } </ins>

<ins> // unit-test: Inline // compile-flags: --crate-type=lib -C panic=abort use std::any::Any; use std::any::TypeId; struct A<T: ?Sized + 'static> { a: i32, b: T, } // EMIT_MIR dont_inline_type_id.call.Inline.diff pub fn call<T: ?Sized + 'static>(s: &T) -> TypeId { s.type_id() } </ins>

<ins> - // MIR for `call` before Inline + // MIR for `call` after Inline fn call(_1: &T) -> i32 { debug s => _1; let mut _0: i32; let mut _2: &T; +     scope 1 (inlined <T as Foo>::bar) { +         debug self => _2; +     } bb0: { StorageLive(_2); _2 = &(*_1); -         _0 = <T as Foo>::bar(move _2) -> [return: bb1, unwind unreachable]; -     } - -     bb1: { +         _0 = const 0_i32; StorageDead(_2); return; } } </ins>

<ins> // unit-test: Inline // compile-flags: --crate-type=lib -C panic=abort trait Foo { fn bar(&self) -> i32; } impl<T> Foo for T { fn bar(&self) -> i32 { 0 } } // EMIT_MIR inline_generically_if_sized.call.Inline.diff pub fn call<T>(s: &T) -> i32 { s.bar() } </ins>

<ins> // run-pass #![feature(inline_const)] // Makes sure we don't propagate generic instances of `Self: ?Sized` blanket impls. // This is relevant when we have an overlapping impl and builtin dyn instance. // See <https://github.com/rust-lang/rust/pull/114941> for more context. trait Trait { fn foo(&self) -> &'static str; } impl<T: ?Sized> Trait for T { fn foo(&self) -> &'static str { std::any::type_name::<T>() } } fn bar<T: ?Sized>() -> fn(&T) -> &'static str { const { Trait::foo as fn(&T) -> &'static str } // If const prop were to propagate the instance } fn main() { assert_eq!("i32", bar::<dyn Trait>()(&1i32)); } </ins>

<ins> // run-pass // Makes sure we don't propagate generic instances of `Self: ?Sized` blanket impls. // This is relevant when we have an overlapping impl and builtin dyn instance. // See <https://github.com/rust-lang/rust/pull/114941> for more context. trait Trait { fn foo(&self) -> &'static str; } impl<T: ?Sized> Trait for T { fn foo(&self) -> &'static str { std::any::type_name::<T>() } } const fn bar<T: ?Sized>() -> fn(&T) -> &'static str { Trait::foo // If const prop were to propagate the instance } fn main() { assert_eq!("i32", bar::<dyn Trait>()(&1i32)); } </ins>