From 540bd986aac6f50363848f37ab1bb9e6eb408170 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Thu, 16 Feb 2023 05:07:18 +0000 Subject: [PATCH] Do not ICE on unmet trait alias bounds --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 17 +++++++++++------ .../issue-108072-unmet-trait-alias-bound.rs | 11 +++++++++++ ...ssue-108072-unmet-trait-alias-bound.stderr | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs create mode 100644 tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index f434fb922893d..d13d8ff8270a9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -477,12 +477,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about. // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of // that struct type. - let impl_trait_self_ref: Option> = - self.tcx.impl_trait_ref(obligation.impl_def_id).map(|impl_def| impl_def.skip_binder()); - - let Some(impl_trait_self_ref) = impl_trait_self_ref else { - // It is possible that this is absent. In this case, we make no progress. - return Err(expr); + let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_def_id) { + self.tcx.mk_trait_ref( + obligation.impl_def_id, + ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_def_id), + ) + } else { + self.tcx + .impl_trait_ref(obligation.impl_def_id) + .map(|impl_def| impl_def.skip_binder()) + // It is possible that this is absent. In this case, we make no progress. + .ok_or(expr)? }; // We only really care about the `Self` type itself, which we extract from the ref. diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs new file mode 100644 index 0000000000000..d254c0ae3ef92 --- /dev/null +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs @@ -0,0 +1,11 @@ +// Regression test for #108072: do not ICE upon unmet trait alias constraint + +#![feature(trait_alias)] + +trait IteratorAlias = Iterator; + +fn f(_: impl IteratorAlias) {} + +fn main() { + f(()) //~ `()` is not an iterator +} diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr new file mode 100644 index 0000000000000..39f974f962c2b --- /dev/null +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: `()` is not an iterator + --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7 + | +LL | f(()) + | - ^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + = note: required for `()` to implement `IteratorAlias` +note: required by a bound in `f` + --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14 + | +LL | fn f(_: impl IteratorAlias) {} + | ^^^^^^^^^^^^^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.