Skip to content

Commit

Permalink
Perform unconstrained param detection in explicit_predicates_of and t…
Browse files Browse the repository at this point in the history
…aint the query result
  • Loading branch information
oli-obk committed Jul 20, 2024
1 parent e567eab commit 403b050
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 59 deletions.
31 changes: 24 additions & 7 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, Upcast};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Ident;
Expand Down Expand Up @@ -86,6 +86,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
parent: Some(tcx.parent(def_id.to_def_id())),
predicates: tcx.arena.alloc_from_iter(predicates),
effects_min_tys: ty::List::empty(),
tainted_by_errors: Ok(()),
};
}

Expand All @@ -108,6 +109,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
parent: Some(impl_def_id),
predicates: tcx.arena.alloc_from_iter(impl_predicates),
effects_min_tys: ty::List::empty(),
tainted_by_errors: trait_assoc_predicates.tainted_by_errors,
};
}

Expand All @@ -128,6 +130,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// Preserving the order of insertion is important here so as not to break UI tests.
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
let mut effects_min_tys = Vec::new();
let mut tainted_by_errors = Ok(());

let hir_generics = node.generics().unwrap_or(NO_GENERICS);
if let Node::Item(item) = node {
Expand Down Expand Up @@ -291,11 +294,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
let self_ty = tcx.type_of(def_id).instantiate_identity();
let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
cgp::setup_constraining_predicates(
tcx,
&mut predicates,
trait_ref,
&mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
let mut input_parameters = cgp::parameters_for_impl(tcx, self_ty, trait_ref);
cgp::setup_constraining_predicates(tcx, &mut predicates, trait_ref, &mut input_parameters);
tainted_by_errors = tainted_by_errors.and(
self_ty.error_reported().and(trait_ref.error_reported()).and_then(|()| {
crate::impl_wf_check::enforce_impl_params_are_constrained(
tcx,
def_id,
input_parameters,
)
}),
);
}

Expand Down Expand Up @@ -338,6 +346,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
parent: generics.parent,
predicates: tcx.arena.alloc_from_iter(predicates),
effects_min_tys: tcx.mk_type_list(&effects_min_tys),
tainted_by_errors,
}
}

Expand Down Expand Up @@ -489,6 +498,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
parent: predicates_and_bounds.parent,
predicates: tcx.arena.alloc_slice(&predicates),
effects_min_tys: predicates_and_bounds.effects_min_tys,
tainted_by_errors: predicates_and_bounds.tainted_by_errors,
}
}
} else {
Expand Down Expand Up @@ -541,6 +551,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
parent: parent_preds.parent,
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
effects_min_tys: parent_preds.effects_min_tys,
tainted_by_errors: parent_preds.tainted_by_errors,
};
}
gather_explicit_predicates_of(tcx, def_id)
Expand Down Expand Up @@ -653,6 +664,7 @@ pub(super) fn implied_predicates_with_filter(
parent: None,
predicates: implied_bounds,
effects_min_tys: ty::List::empty(),
tainted_by_errors: Ok(()),
}
}

Expand Down Expand Up @@ -688,7 +700,12 @@ pub(super) fn type_param_predicates(
let icx = ItemCtxt::new(tcx, parent);
icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_name)
})
.unwrap_or_default();
.unwrap_or(GenericPredicates {
parent: None,
predicates: &[],
effects_min_tys: ty::List::empty(),
tainted_by_errors: Ok(()),
});
let mut extend = None;

let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
Expand Down
22 changes: 5 additions & 17 deletions compiler/rustc_hir_analysis/src/impl_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
use crate::{constrained_generic_params as cgp, errors::UnconstrainedGenericParameter};
use min_specialization::check_min_specialization;

use rustc_data_structures::fx::FxHashSet;
use rustc_errors::codes::*;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::ErrorGuaranteed;

mod min_specialization;
Expand Down Expand Up @@ -53,34 +54,21 @@ pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), Err
let min_specialization = tcx.features().min_specialization;
let mut res = Ok(());
debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }));
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
res = res.and(tcx.explicit_predicates_of(impl_def_id).tainted_by_errors);
if min_specialization {
res = res.and(check_min_specialization(tcx, impl_def_id));
}

res
}

fn enforce_impl_params_are_constrained(
pub(crate) fn enforce_impl_params_are_constrained(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
input_parameters: FxHashSet<cgp::Parameter>,
) -> Result<(), ErrorGuaranteed> {
// Every lifetime used in an associated type must be constrained.
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
impl_self_ty.error_reported()?;
let impl_generics = tcx.generics_of(impl_def_id);
let impl_predicates = tcx.predicates_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);

impl_trait_ref.error_reported()?;

let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
cgp::identify_constrained_generic_params(
tcx,
impl_predicates,
impl_trait_ref,
&mut input_parameters,
);

let mut res = Ok(());
for param in &impl_generics.own_params {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
}),
),
effects_min_tys: ty::List::empty(),
tainted_by_errors: Ok(()),
}
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
use rustc_span::{ErrorGuaranteed, Span};
use tracing::instrument;

use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
Expand Down Expand Up @@ -367,11 +367,12 @@ impl<'tcx> Generics {
}

/// Bounds on generics.
#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
pub predicates: &'tcx [(Clause<'tcx>, Span)],
pub effects_min_tys: &'tcx ty::List<Ty<'tcx>>,
pub tainted_by_errors: Result<(), ErrorGuaranteed>,
}

impl<'tcx> GenericPredicates<'tcx> {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let GenericPredicates { parent, predicates, effects_min_tys: _ } =
let GenericPredicates { parent, predicates, effects_min_tys: _, tainted_by_errors: _ } =
tables.tcx.predicates_of(def_id);
stable_mir::ty::GenericPredicates {
parent: parent.map(|did| tables.trait_def(did)),
Expand All @@ -182,7 +182,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
) -> stable_mir::ty::GenericPredicates {
let mut tables = self.0.borrow_mut();
let def_id = tables[def_id];
let GenericPredicates { parent, predicates, effects_min_tys: _ } =
let GenericPredicates { parent, predicates, effects_min_tys: _, tainted_by_errors: _ } =
tables.tcx.explicit_predicates_of(def_id);
stable_mir::ty::GenericPredicates {
parent: parent.map(|did| tables.trait_def(did)),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//@ known-bug: rust-lang/rust#126646
//! This test used to ICE when trying to resolve the method call in the `test` function.
mod foo {
pub trait Callable {
type Output;
fn call() -> Self::Output;
}

impl<'a, V: ?Sized> Callable for &'a () {
//~^ ERROR: `V` is not constrained
type Output = ();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
--> $DIR/missing_method_in_impl_with_unconstrained_type_param.rs:9:14
|
LL | impl<'a, V: ?Sized> Callable for &'a () {
| ^ unconstrained type parameter

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0207`.
48 changes: 24 additions & 24 deletions tests/ui/impl-unused-tps.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:47:8
|
LL | impl<T,U,V> Foo<T> for T
| ^ unconstrained type parameter

error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:47:10
|
LL | impl<T,U,V> Foo<T> for T
| ^ unconstrained type parameter

error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:31:8
|
LL | impl<T,U> Bar for T {
| ^ unconstrained type parameter

error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:39:8
|
LL | impl<T,U> Bar for T
| ^ unconstrained type parameter

error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
--> $DIR/impl-unused-tps.rs:27:1
|
Expand Down Expand Up @@ -26,30 +50,6 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
LL | impl<T,U> Foo<T> for [isize;1] {
| ^ unconstrained type parameter

error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:31:8
|
LL | impl<T,U> Bar for T {
| ^ unconstrained type parameter

error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:39:8
|
LL | impl<T,U> Bar for T
| ^ unconstrained type parameter

error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:47:8
|
LL | impl<T,U,V> Foo<T> for T
| ^ unconstrained type parameter

error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
--> $DIR/impl-unused-tps.rs:47:10
|
LL | impl<T,U,V> Foo<T> for T
| ^ unconstrained type parameter

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0119, E0207, E0275.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ note: this opaque type is in the signature
LL | type DummyT<T> = impl F;
| ^^^^^^

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> $DIR/ice-failed-to-resolve-instance-for-110696.rs:41:6
|
LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
| ^ unconstrained type parameter

error: item does not constrain `DummyT::{opaque#0}`, but has it in its signature
--> $DIR/ice-failed-to-resolve-instance-for-110696.rs:44:8
|
Expand All @@ -24,12 +30,6 @@ note: this opaque type is in the signature
LL | type DummyT<T> = impl F;
| ^^^^^^

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> $DIR/ice-failed-to-resolve-instance-for-110696.rs:41:6
|
LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
| ^ unconstrained type parameter

error: aborting due to 3 previous errors

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

0 comments on commit 403b050

Please sign in to comment.