Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,9 +701,15 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
ocx.register_obligation(obligation);
}
let errors = ocx.select_all_or_error();

if !errors.is_empty() {
// Use `select_where_possible` to only return impossible for true errors,
// and not ambiguities or overflows. Since the new trait solver forces
// some currently undetected overlap between `dyn Trait: Trait` built-in
// vs user-written impls to AMBIGUOUS, this may return ambiguity even
// with no infer vars. There may also be ways to encounter ambiguity due
// to post-mono overflow.
let true_errors = ocx.select_where_possible();
if !true_errors.is_empty() {
return true;
}

Expand Down
37 changes: 37 additions & 0 deletions tests/ui/traits/object/ambiguity-vtable-segfault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// In this example below, we have two overlapping candidates for `dyn Q: Q`.
// Specifically, the user written impl for `<dyn Q as Mirror>::Assoc` and the
// built-in impl for object types. Since they differ by their region responses,
// the goal is ambiguous. This affects codegen since impossible obligations
// for method dispatch will lead to a segfault, since we end up emitting dummy
// call vtable offsets due to <https://github.com/rust-lang/rust/pull/136311>.

// Test for <https://github.com/rust-lang/rust/issues/141119>.

//@ run-pass

trait Mirror {
type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for T {
type Assoc = T;
}

trait Q: 'static {
fn q(&self);
}

impl Q for i32 {
fn q(&self) { println!("i32"); }
}

impl Q for <dyn Q as Mirror>::Assoc where Self: 'static {
fn q(&self) { println!("dyn Q"); }
}

fn foo<T: Q + ?Sized>(t: &T) {
t.q();
}

fn main() {
foo(&1 as &dyn Q);
}
Loading