Skip to content

Commit

Permalink
Rollup merge of #108136 - eggyal:unmet_trait_alias_bound_on_generic_i…
Browse files Browse the repository at this point in the history
…mpl, r=compiler-errors

Do not ICE on unmet trait alias impl bounds

Fixes #108132

I've also added some documentation to the `impl_def_id` field of `DerivedObligationCause` to try and minimise the risk of such errors in future.

r? `@compiler-errors`
  • Loading branch information
matthiaskrgr authored Feb 16, 2023
2 parents e1e58fc + 55d449f commit ecdb7bc
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -477,14 +477,14 @@ 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 = if self.tcx.is_trait_alias(obligation.impl_def_id) {
let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) {
self.tcx.mk_trait_ref(
obligation.impl_def_id,
ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_def_id),
obligation.impl_or_alias_def_id,
ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
)
} else {
self.tcx
.impl_trait_ref(obligation.impl_def_id)
.impl_trait_ref(obligation.impl_or_alias_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)?
Expand All @@ -494,7 +494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();

let impl_predicates: ty::GenericPredicates<'tcx> =
self.tcx.predicates_of(obligation.impl_def_id);
self.tcx.predicates_of(obligation.impl_or_alias_def_id);
let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
// We don't have the index, so we can only guess.
return Err(expr);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1576,7 +1576,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause {
derived,
impl_def_id,
impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: None,
span,
},
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ObligationCauseCode::ImplDerivedObligation(data)
if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
{
Some((p, parent, data.impl_def_id, data))
Some((p, parent, data.impl_or_alias_def_id, data))
}
_ => None,
})
Expand Down Expand Up @@ -714,7 +714,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
Some(Node::Item(hir::Item {
ident, kind: hir::ItemKind::Trait(..), ..
ident,
kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
..
})) => {
skip_list.insert(p);
let entry = spanned_predicates.entry(ident.span);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl<'tcx> Elaborator<'tcx> {
traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause {
derived,
impl_def_id: data.def_id(),
impl_or_alias_def_id: data.def_id(),
impl_def_predicate_index: Some(index),
span,
},
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,11 @@ pub enum WellFormedLoc {
#[derive(TypeVisitable, TypeFoldable)]
pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'tcx>,
pub impl_def_id: DefId,
/// The `DefId` of the `impl` that gave rise to the `derived` obligation.
/// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
/// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
/// that exceptional case where appropriate.
pub impl_or_alias_def_id: DefId,
/// The index of the derived predicate in the parent impl's predicates.
pub impl_def_predicate_index: Option<usize>,
pub span: Span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3143,7 +3143,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
parent_trait_pred.print_modifiers_and_trait_path()
);
let mut is_auto_trait = false;
match self.tcx.hir().get_if_local(data.impl_def_id) {
match self.tcx.hir().get_if_local(data.impl_or_alias_def_id) {
Some(Node::Item(hir::Item {
kind: hir::ItemKind::Trait(is_auto, ..),
ident,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(|derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
impl_def_id,
impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: None,
span: obligation.cause.span,
}))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2657,7 +2657,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
impl_def_id: def_id,
impl_or_alias_def_id: def_id,
impl_def_predicate_index: Some(index),
span,
}))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Regression test for #108132: do not ICE upon unmet trait alias constraint in generic impl

#![feature(trait_alias)]

trait IteratorAlias = Iterator;

struct Foo<I>(I);

impl<I: IteratorAlias> Foo<I> {
fn f() {}
}

fn main() {
Foo::<()>::f() //~ trait bounds were not satisfied
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error[E0599]: the function or associated item `f` exists for struct `Foo<()>`, but its trait bounds were not satisfied
--> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:14:16
|
LL | struct Foo<I>(I);
| ------------- function or associated item `f` not found for this struct
...
LL | Foo::<()>::f()
| ^ function or associated item cannot be called on `Foo<()>` due to unsatisfied trait bounds
|
note: trait bound `(): Iterator` was not satisfied
--> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:5:23
|
LL | trait IteratorAlias = Iterator;
| ------------- ^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `(): IteratorAlias` was not satisfied
--> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
|
LL | impl<I: IteratorAlias> Foo<I> {
| ^^^^^^^^^^^^^ ------
| |
| unsatisfied trait bound introduced here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.

0 comments on commit ecdb7bc

Please sign in to comment.