Skip to content

Commit e8f9d94

Browse files
Don't resolve generic instances if they may be shadowed by dyn
1 parent 2c0fc50 commit e8f9d94

7 files changed

+143
-19
lines changed

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,6 +2929,33 @@ impl<'tcx> Ty<'tcx> {
29292929
_ => false,
29302930
}
29312931
}
2932+
2933+
pub fn is_known_rigid(self) -> bool {
2934+
match self.kind() {
2935+
Bool
2936+
| Char
2937+
| Int(_)
2938+
| Uint(_)
2939+
| Float(_)
2940+
| Adt(_, _)
2941+
| Foreign(_)
2942+
| Str
2943+
| Array(_, _)
2944+
| Slice(_)
2945+
| RawPtr(_)
2946+
| Ref(_, _, _)
2947+
| FnDef(_, _)
2948+
| FnPtr(_)
2949+
| Dynamic(_, _, _)
2950+
| Closure(_, _)
2951+
| Generator(_, _, _)
2952+
| GeneratorWitness(_)
2953+
| GeneratorWitnessMIR(_, _)
2954+
| Never
2955+
| Tuple(_) => true,
2956+
Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false,
2957+
}
2958+
}
29322959
}
29332960

29342961
/// Extra information about why we ended up with a particular variance.

compiler/rustc_ty_utils/src/instance.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,34 @@ fn resolve_associated_item<'tcx>(
140140
false
141141
}
142142
};
143-
144143
if !eligible {
145144
return Ok(None);
146145
}
147146

147+
// HACK: We may have overlapping `dyn Trait` built-in impls and
148+
// user-provided blanket impls. Detect that case here, and return
149+
// ambiguity.
150+
//
151+
// This should not affect totally monomorphized contexts, only
152+
// resolve calls that happen polymorphically, such as the mir-inliner
153+
// and const-prop (and also some lints).
154+
let self_ty = rcvr_args.type_at(0);
155+
if !self_ty.is_known_rigid() {
156+
let predicates = tcx
157+
.predicates_of(impl_data.impl_def_id)
158+
.instantiate(tcx, impl_data.args)
159+
.predicates;
160+
let sized_def_id = tcx.lang_items().sized_trait();
161+
// If we find a `Self: Sized` bound on the item, then we know
162+
// that `dyn Trait` can certainly never apply here.
163+
if !predicates.into_iter().filter_map(ty::Clause::as_trait_clause).any(|clause| {
164+
Some(clause.def_id()) == sized_def_id
165+
&& clause.skip_binder().self_ty() == self_ty
166+
}) {
167+
return Ok(None);
168+
}
169+
}
170+
148171
// Any final impl is required to define all associated items.
149172
if !leaf_def.item.defaultness(tcx).has_value() {
150173
let guard = tcx.sess.delay_span_bug(

tests/mir-opt/dont_inline_type_id.call.Inline.diff

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,14 @@
55
debug s => _1;
66
let mut _0: std::any::TypeId;
77
let mut _2: &T;
8-
+ scope 1 (inlined <T as Any>::type_id) {
9-
+ debug self => _2;
10-
+ scope 2 (inlined TypeId::of::<T>) {
11-
+ let _3: u128;
12-
+ let mut _4: u128;
13-
+ scope 3 {
14-
+ debug t => _3;
15-
+ }
16-
+ }
17-
+ }
188

199
bb0: {
2010
StorageLive(_2);
2111
_2 = &(*_1);
22-
- _0 = <T as Any>::type_id(move _2) -> [return: bb1, unwind unreachable];
23-
+ StorageLive(_3);
24-
+ _3 = std::intrinsics::type_id::<T>() -> [return: bb1, unwind unreachable];
12+
_0 = <T as Any>::type_id(move _2) -> [return: bb1, unwind unreachable];
2513
}
2614

2715
bb1: {
28-
+ StorageLive(_4);
29-
+ _4 = _3;
30-
+ _0 = TypeId { t: move _4 };
31-
+ StorageDead(_4);
32-
+ StorageDead(_3);
3316
StorageDead(_2);
3417
return;
3518
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
- // MIR for `call` before Inline
2+
+ // MIR for `call` after Inline
3+
4+
fn call(_1: &T) -> i32 {
5+
debug s => _1;
6+
let mut _0: i32;
7+
let mut _2: &T;
8+
+ scope 1 (inlined <T as Foo>::bar) {
9+
+ debug self => _2;
10+
+ }
11+
12+
bb0: {
13+
StorageLive(_2);
14+
_2 = &(*_1);
15+
- _0 = <T as Foo>::bar(move _2) -> [return: bb1, unwind unreachable];
16+
- }
17+
-
18+
- bb1: {
19+
+ _0 = const 0_i32;
20+
StorageDead(_2);
21+
return;
22+
}
23+
}
24+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// unit-test: Inline
2+
// compile-flags: --crate-type=lib -C panic=abort
3+
4+
trait Foo {
5+
fn bar(&self) -> i32;
6+
}
7+
8+
impl<T> Foo for T {
9+
fn bar(&self) -> i32 {
10+
0
11+
}
12+
}
13+
14+
// EMIT_MIR inline_generically_if_sized.call.Inline.diff
15+
fn call<T>(s: &T) -> i32 {
16+
s.bar()
17+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// run-pass
2+
3+
#![feature(inline_const)]
4+
5+
// Makes sure we don't propagate generic instances of `Self: ?Sized` blanket impls.
6+
// This is relevant when we have an overlapping impl and builtin dyn instance.
7+
// See <https://github.com/rust-lang/rust/pull/114941> for more context.
8+
9+
trait Trait {
10+
fn foo(&self) -> &'static str;
11+
}
12+
13+
impl<T: ?Sized> Trait for T {
14+
fn foo(&self) -> &'static str {
15+
std::any::type_name::<T>()
16+
}
17+
}
18+
19+
fn bar<T: ?Sized>() -> fn(&T) -> &'static str {
20+
const { Trait::foo as fn(&T) -> &'static str }
21+
// If const prop were to propagate the instance
22+
}
23+
24+
fn main() {
25+
assert_eq!("i32", bar::<dyn Trait>()(&1i32));
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// run-pass
2+
3+
// Makes sure we don't propagate generic instances of `Self: ?Sized` blanket impls.
4+
// This is relevant when we have an overlapping impl and builtin dyn instance.
5+
// See <https://github.com/rust-lang/rust/pull/114941> for more context.
6+
7+
trait Trait {
8+
fn foo(&self) -> &'static str;
9+
}
10+
11+
impl<T: ?Sized> Trait for T {
12+
fn foo(&self) -> &'static str {
13+
std::any::type_name::<T>()
14+
}
15+
}
16+
17+
const fn bar<T: ?Sized>() -> fn(&T) -> &'static str {
18+
Trait::foo
19+
// If const prop were to propagate the instance
20+
}
21+
22+
fn main() {
23+
assert_eq!("i32", bar::<dyn Trait>()(&1i32));
24+
}

0 commit comments

Comments
 (0)