From 403b0506b11cb2798d2aee1c2ebfc48fd6bbc0d6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 20 Jul 2024 13:12:25 +0000 Subject: [PATCH] Perform unconstrained param detection in explicit_predicates_of and taint the query result --- .../src/collect/predicates_of.rs | 31 +++++++++--- .../rustc_hir_analysis/src/impl_wf_check.rs | 22 ++------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 1 + compiler/rustc_middle/src/ty/generics.rs | 5 +- compiler/rustc_smir/src/rustc_smir/context.rs | 4 +- ..._in_impl_with_unconstrained_type_param.rs} | 4 +- ..._impl_with_unconstrained_type_param.stderr | 9 ++++ tests/ui/impl-unused-tps.stderr | 48 +++++++++---------- ...iled-to-resolve-instance-for-110696.stderr | 12 ++--- 9 files changed, 77 insertions(+), 59 deletions(-) rename tests/{crashes/126646.rs => ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.rs} (66%) create mode 100644 tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 9e430c83e20d7..dc8ea10b9dbf7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -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; @@ -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(()), }; } @@ -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, }; } @@ -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 { @@ -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, + ) + }), ); } @@ -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, } } @@ -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 { @@ -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) @@ -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(()), } } @@ -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); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index e11866d7fbdad..423fc11775f15 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -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; @@ -53,7 +54,7 @@ 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)); } @@ -61,26 +62,13 @@ pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), Err res } -fn enforce_impl_params_are_constrained( +pub(crate) fn enforce_impl_params_are_constrained( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, + input_parameters: FxHashSet, ) -> 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 { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 3fe87c03e7431..02c56f71a1c46 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -279,6 +279,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { }), ), effects_min_tys: ty::List::empty(), + tainted_by_errors: Ok(()), } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 11ed0bdaa7028..343b7451ac402 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -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}; @@ -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, pub predicates: &'tcx [(Clause<'tcx>, Span)], pub effects_min_tys: &'tcx ty::List>, + pub tainted_by_errors: Result<(), ErrorGuaranteed>, } impl<'tcx> GenericPredicates<'tcx> { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index b0ced8e920fe5..f28532a7dab27 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -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)), @@ -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)), diff --git a/tests/crashes/126646.rs b/tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.rs similarity index 66% rename from tests/crashes/126646.rs rename to tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.rs index 24e3530320a89..0d2b89ea7ca3d 100644 --- a/tests/crashes/126646.rs +++ b/tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.rs @@ -1,4 +1,5 @@ -//@ 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; @@ -6,6 +7,7 @@ mod foo { } impl<'a, V: ?Sized> Callable for &'a () { + //~^ ERROR: `V` is not constrained type Output = (); } } diff --git a/tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.stderr b/tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.stderr new file mode 100644 index 0000000000000..6998e1b1abc1c --- /dev/null +++ b/tests/ui/associated-item/missing_method_in_impl_with_unconstrained_type_param.stderr @@ -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`. diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr index af427cb5f3e3c..0df46b04c9c67 100644 --- a/tests/ui/impl-unused-tps.stderr +++ b/tests/ui/impl-unused-tps.stderr @@ -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 Foo 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 Foo 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 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 Bar for T + | ^ unconstrained type parameter + error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` --> $DIR/impl-unused-tps.rs:27:1 | @@ -26,30 +50,6 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self LL | impl Foo 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 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 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 Foo 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 Foo for T - | ^ unconstrained type parameter - error: aborting due to 7 previous errors Some errors have detailed explanations: E0119, E0207, E0275. diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr index 22c776e171c2f..70675b446d126 100644 --- a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr +++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr @@ -11,6 +11,12 @@ note: this opaque type is in the signature LL | type DummyT = 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>>, U> MyIndex> for Scope { + | ^ 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 | @@ -24,12 +30,6 @@ note: this opaque type is in the signature LL | type DummyT = 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>>, U> MyIndex> for Scope { - | ^ unconstrained type parameter - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0207`.