Skip to content

Only select true errors in impossible_predicates #141121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 17, 2025
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