1
Fork 0

implied_bounds: clarify our assumptions

This commit is contained in:
lcnr 2022-08-17 12:22:32 +02:00
parent b7a8496a07
commit 4fe666ee64
22 changed files with 251 additions and 172 deletions

View file

@ -765,6 +765,14 @@ rustc_queries! {
desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) } desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
} }
/// Returns the types assumed to be well formed while "inside" of the given item.
///
/// Note that we've liberated the late bound regions of function signatures, so
/// this can not be used to check whether these types are well formed.
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) }
}
/// Computes the signature of the function. /// Computes the signature of the function.
query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> { query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }

View file

@ -0,0 +1,60 @@
use crate::rustc_middle::ty::DefIdTree;
use rustc_hir::{def::DefKind, def_id::DefId};
use rustc_middle::ty::{self, Ty, TyCtxt};
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { assumed_wf_types, ..*providers };
}
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty<'tcx>> {
match tcx.def_kind(def_id) {
DefKind::Fn => {
let sig = tcx.fn_sig(def_id);
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
liberated_sig.inputs_and_output
}
DefKind::AssocFn => {
let sig = tcx.fn_sig(def_id);
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
let mut assumed_wf_types: Vec<_> =
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
assumed_wf_types.extend(liberated_sig.inputs_and_output);
tcx.intern_type_list(&assumed_wf_types)
}
DefKind::Impl => match tcx.impl_trait_ref(def_id) {
Some(trait_ref) => {
let types: Vec<_> = trait_ref.substs.types().collect();
tcx.intern_type_list(&types)
}
// Only the impl self type
None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
},
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
DefKind::Mod
| DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::TyParam
| DefKind::Const
| DefKind::ConstParam
| DefKind::Static(_)
| DefKind::Ctor(_, _)
| DefKind::Macro(_)
| DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Closure
| DefKind::Generator => ty::List::empty(),
}
}

View file

@ -21,6 +21,7 @@ use rustc_middle::ty::query::Providers;
mod assoc; mod assoc;
mod common_traits; mod common_traits;
mod consts; mod consts;
mod implied_bounds;
pub mod instance; pub mod instance;
mod needs_drop; mod needs_drop;
pub mod representability; pub mod representability;
@ -30,6 +31,7 @@ pub fn provide(providers: &mut Providers) {
assoc::provide(providers); assoc::provide(providers);
common_traits::provide(providers); common_traits::provide(providers);
consts::provide(providers); consts::provide(providers);
implied_bounds::provide(providers);
needs_drop::provide(providers); needs_drop::provide(providers);
ty::provide(providers); ty::provide(providers);
instance::provide(providers); instance::provide(providers);

View file

@ -1,6 +1,5 @@
use super::potentially_plural_count; use super::potentially_plural_count;
use crate::check::regionck::OutlivesEnvironmentExt; use crate::check::regionck::OutlivesEnvironmentExt;
use crate::check::wfcheck;
use crate::errors::LifetimesOrBoundsMismatchOnTrait; use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
@ -1445,14 +1444,24 @@ pub fn check_type_bounds<'tcx>(
}; };
debug!(?normalize_param_env); debug!(?normalize_param_env);
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id); let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
tcx.infer_ctxt().enter(move |infcx| { tcx.infer_ctxt().enter(move |infcx| {
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let assumed_wf_types = tcx.assumed_wf_types(impl_ty.def_id);
let mut implied_bounds = FxHashSet::default();
let cause = ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
for ty in assumed_wf_types {
implied_bounds.insert(ty);
let normalized = ocx.normalize(cause.clone(), param_env, ty);
implied_bounds.insert(normalized);
}
let implied_bounds = implied_bounds;
let mut selcx = traits::SelectionContext::new(&infcx); let mut selcx = traits::SelectionContext::new(&infcx);
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
let normalize_cause = ObligationCause::new( let normalize_cause = ObligationCause::new(
impl_ty_span, impl_ty_span,
impl_ty_hir_id, impl_ty_hir_id,
@ -1508,15 +1517,6 @@ pub fn check_type_bounds<'tcx>(
// Finally, resolve all regions. This catches wily misuses of // Finally, resolve all regions. This catches wily misuses of
// lifetime parameters. // lifetime parameters.
let implied_bounds = match impl_ty.container {
ty::TraitContainer => FxHashSet::default(),
ty::ImplContainer => wfcheck::impl_implied_bounds(
tcx,
param_env,
container_id.expect_local(),
impl_ty_span,
),
};
let mut outlives_environment = OutlivesEnvironment::new(param_env); let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id); outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
infcx.check_region_obligations_and_report_errors( infcx.check_region_obligations_and_report_errors(

View file

@ -10,7 +10,6 @@ use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::outlives::obligations::TypeOutlives;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::Normalized;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::trait_def::TraitSpecializationKind;
@ -24,8 +23,6 @@ use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::query::normalize::AtExt;
use rustc_trait_selection::traits::query::NoSolution;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
}; };
@ -86,18 +83,29 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
body_def_id: LocalDefId, body_def_id: LocalDefId,
f: F, f: F,
) where ) where
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> FxHashSet<Ty<'tcx>>, F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
{ {
let param_env = tcx.param_env(body_def_id); let param_env = tcx.param_env(body_def_id);
let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id); let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
tcx.infer_ctxt().enter(|ref infcx| { tcx.infer_ctxt().enter(|ref infcx| {
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
let assumed_wf_types = tcx.assumed_wf_types(body_def_id);
let mut implied_bounds = FxHashSet::default();
let cause = ObligationCause::misc(span, body_id);
for ty in assumed_wf_types {
implied_bounds.insert(ty);
let normalized = ocx.normalize(cause.clone(), param_env, ty);
implied_bounds.insert(normalized);
}
let implied_bounds = implied_bounds;
let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env }; let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
if !tcx.features().trivial_bounds { if !tcx.features().trivial_bounds {
wfcx.check_false_global_bounds() wfcx.check_false_global_bounds()
} }
let wf_tys = f(&mut wfcx); f(&mut wfcx);
let errors = wfcx.select_all_or_error(); let errors = wfcx.select_all_or_error();
if !errors.is_empty() { if !errors.is_empty() {
infcx.report_fulfillment_errors(&errors, None, false); infcx.report_fulfillment_errors(&errors, None, false);
@ -105,7 +113,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
} }
let mut outlives_environment = OutlivesEnvironment::new(param_env); let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(infcx, wf_tys, body_id); outlives_environment.add_implied_bounds(infcx, implied_bounds, body_id);
infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
}) })
} }
@ -976,15 +984,9 @@ fn check_associated_item(
enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| { enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
let item = tcx.associated_item(item_id); let item = tcx.associated_item(item_id);
let (mut implied_bounds, self_ty) = match item.container { let self_ty = match item.container {
ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param), ty::TraitContainer => tcx.types.self_param,
ty::ImplContainer => { ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
let def_id = item.container_id(tcx);
(
impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
tcx.type_of(def_id),
)
}
}; };
match item.kind { match item.kind {
@ -1002,7 +1004,6 @@ fn check_associated_item(
sig, sig,
hir_sig.decl, hir_sig.decl,
item.def_id.expect_local(), item.def_id.expect_local(),
&mut implied_bounds,
); );
check_method_receiver(wfcx, hir_sig, item, self_ty); check_method_receiver(wfcx, hir_sig, item, self_ty);
} }
@ -1017,8 +1018,6 @@ fn check_associated_item(
} }
} }
} }
implied_bounds
}) })
} }
@ -1118,9 +1117,6 @@ fn check_type_defn<'tcx, F>(
} }
check_where_clauses(wfcx, item.span, item.def_id); check_where_clauses(wfcx, item.span, item.def_id);
// No implied bounds in a struct definition.
FxHashSet::default()
}); });
} }
@ -1144,9 +1140,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
} }
enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
check_where_clauses(wfcx, item.span, item.def_id); check_where_clauses(wfcx, item.span, item.def_id)
FxHashSet::default()
}); });
// Only check traits, don't check trait aliases // Only check traits, don't check trait aliases
@ -1186,9 +1180,7 @@ fn check_item_fn(
) { ) {
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| { enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
let sig = tcx.fn_sig(def_id); let sig = tcx.fn_sig(def_id);
let mut implied_bounds = FxHashSet::default(); check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
check_fn_or_method(wfcx, ident.span, sig, decl, def_id, &mut implied_bounds);
implied_bounds
}) })
} }
@ -1231,9 +1223,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
tcx.require_lang_item(LangItem::Sync, Some(ty_span)), tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
); );
} }
// No implied bounds in a const, etc.
FxHashSet::default()
}); });
} }
@ -1284,8 +1273,6 @@ fn check_impl<'tcx>(
} }
check_where_clauses(wfcx, item.span, item.def_id); check_where_clauses(wfcx, item.span, item.def_id);
impl_implied_bounds(tcx, wfcx.param_env, item.def_id, item.span)
}); });
} }
@ -1479,7 +1466,6 @@ fn check_fn_or_method<'tcx>(
sig: ty::PolyFnSig<'tcx>, sig: ty::PolyFnSig<'tcx>,
hir_decl: &hir::FnDecl<'_>, hir_decl: &hir::FnDecl<'_>,
def_id: LocalDefId, def_id: LocalDefId,
implied_bounds: &mut FxHashSet<Ty<'tcx>>,
) { ) {
let tcx = wfcx.tcx(); let tcx = wfcx.tcx();
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
@ -1521,15 +1507,8 @@ fn check_fn_or_method<'tcx>(
); );
} }
implied_bounds.extend(sig.inputs());
wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into()); wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into());
// FIXME(#27579) return types should not be implied bounds
implied_bounds.insert(sig.output());
debug!(?implied_bounds);
check_where_clauses(wfcx, span, def_id); check_where_clauses(wfcx, span, def_id);
} }
@ -1924,40 +1903,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
} }
} }
pub fn impl_implied_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
impl_def_id: LocalDefId,
span: Span,
) -> FxHashSet<Ty<'tcx>> {
// We completely ignore any obligations caused by normalizing the types
// we assume to be well formed. Considering that the user of the implied
// bounds will also normalize them, we leave it to them to emit errors
// which should result in better causes and spans.
tcx.infer_ctxt().enter(|infcx| {
let cause = ObligationCause::misc(span, tcx.hir().local_def_id_to_hir_id(impl_def_id));
match tcx.impl_trait_ref(impl_def_id) {
Some(trait_ref) => {
// Trait impl: take implied bounds from all types that
// appear in the trait reference.
match infcx.at(&cause, param_env).normalize(trait_ref) {
Ok(Normalized { value, obligations: _ }) => value.substs.types().collect(),
Err(NoSolution) => FxHashSet::default(),
}
}
None => {
// Inherent impl: take implied bounds from the `self` type.
let self_ty = tcx.type_of(impl_def_id);
match infcx.at(&cause, param_env).normalize(self_ty) {
Ok(Normalized { value, obligations: _ }) => FxHashSet::from_iter([value]),
Err(NoSolution) => FxHashSet::default(),
}
}
}
})
}
fn error_392( fn error_392(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
span: Span, span: Span,

View file

@ -66,26 +66,25 @@
//! on traits with methods can. //! on traits with methods can.
use crate::check::regionck::OutlivesEnvironmentExt; use crate::check::regionck::OutlivesEnvironmentExt;
use crate::check::wfcheck::impl_implied_bounds;
use crate::constrained_generic_params as cgp; use crate::constrained_generic_params as cgp;
use crate::errors::SubstsOnOverriddenImpl; use crate::errors::SubstsOnOverriddenImpl;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::specialization_graph::Node; use rustc_infer::traits::specialization_graph::Node;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::{self, translate_substs, wf}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
if let Some(node) = parent_specialization_node(tcx, impl_def_id) { if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
tcx.infer_ctxt().enter(|infcx| { check_always_applicable(tcx, impl_def_id, node);
check_always_applicable(&infcx, impl_def_id, node);
});
} }
} }
@ -105,16 +104,14 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti
} }
/// Check that `impl1` is a sound specialization /// Check that `impl1` is a sound specialization
fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) { fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) {
if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) { if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
let impl2_def_id = impl2_node.def_id(); let impl2_def_id = impl2_node.def_id();
debug!( debug!(
"check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)", "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
impl1_def_id, impl2_def_id, impl2_substs impl1_def_id, impl2_def_id, impl2_substs
); );
let tcx = infcx.tcx;
let parent_substs = if impl2_node.is_from_trait() { let parent_substs = if impl2_node.is_from_trait() {
impl2_substs.to_vec() impl2_substs.to_vec()
} else { } else {
@ -124,7 +121,7 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId,
let span = tcx.def_span(impl1_def_id); let span = tcx.def_span(impl1_def_id);
check_static_lifetimes(tcx, &parent_substs, span); check_static_lifetimes(tcx, &parent_substs, span);
check_duplicate_params(tcx, impl1_substs, &parent_substs, span); check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
} }
} }
@ -139,25 +136,37 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId,
/// ///
/// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`. /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
fn get_impl_substs<'tcx>( fn get_impl_substs<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, tcx: TyCtxt<'tcx>,
impl1_def_id: LocalDefId, impl1_def_id: LocalDefId,
impl2_node: Node, impl2_node: Node,
) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> { ) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
let tcx = infcx.tcx; tcx.infer_ctxt().enter(|ref infcx| {
let ocx = ObligationCtxt::new(infcx);
let param_env = tcx.param_env(impl1_def_id); let param_env = tcx.param_env(impl1_def_id);
let impl1_hir_id = tcx.hir().local_def_id_to_hir_id(impl1_def_id);
let assumed_wf_types = tcx.assumed_wf_types(impl1_def_id);
let mut implied_bounds = FxHashSet::default();
let cause = ObligationCause::misc(tcx.def_span(impl1_def_id), impl1_hir_id);
for ty in assumed_wf_types {
implied_bounds.insert(ty);
let normalized = ocx.normalize(cause.clone(), param_env, ty);
implied_bounds.insert(normalized);
}
let implied_bounds = implied_bounds;
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id()); let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
let impl2_substs = let impl2_substs =
translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node); translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
ocx.infcx.report_fulfillment_errors(&errors, None, false);
return None;
}
let mut outlives_env = OutlivesEnvironment::new(param_env); let mut outlives_env = OutlivesEnvironment::new(param_env);
let implied_bounds = outlives_env.add_implied_bounds(infcx, implied_bounds, impl1_hir_id);
impl_implied_bounds(infcx.tcx, param_env, impl1_def_id, tcx.def_span(impl1_def_id));
outlives_env.add_implied_bounds(
infcx,
implied_bounds,
tcx.hir().local_def_id_to_hir_id(impl1_def_id),
);
infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
let span = tcx.def_span(impl1_def_id); let span = tcx.def_span(impl1_def_id);
@ -165,6 +174,7 @@ fn get_impl_substs<'tcx>(
return None; return None;
}; };
Some((impl1_substs, impl2_substs)) Some((impl1_substs, impl2_substs))
})
} }
/// Returns a list of all of the unconstrained subst of the given impl. /// Returns a list of all of the unconstrained subst of the given impl.
@ -279,14 +289,13 @@ fn check_static_lifetimes<'tcx>(
/// * a well-formed predicate of a type argument of the trait being implemented, /// * a well-formed predicate of a type argument of the trait being implemented,
/// including the `Self`-type. /// including the `Self`-type.
fn check_predicates<'tcx>( fn check_predicates<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, tcx: TyCtxt<'tcx>,
impl1_def_id: LocalDefId, impl1_def_id: LocalDefId,
impl1_substs: SubstsRef<'tcx>, impl1_substs: SubstsRef<'tcx>,
impl2_node: Node, impl2_node: Node,
impl2_substs: SubstsRef<'tcx>, impl2_substs: SubstsRef<'tcx>,
span: Span, span: Span,
) { ) {
let tcx = infcx.tcx;
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span( let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
tcx, tcx,
@ -343,19 +352,23 @@ fn check_predicates<'tcx>(
// Include the well-formed predicates of the type parameters of the impl. // Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs { for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs {
if let Some(obligations) = wf::obligations( tcx.infer_ctxt().enter(|ref infcx| {
let obligations = wf::obligations(
infcx, infcx,
tcx.param_env(impl1_def_id), tcx.param_env(impl1_def_id),
tcx.hir().local_def_id_to_hir_id(impl1_def_id), tcx.hir().local_def_id_to_hir_id(impl1_def_id),
0, 0,
arg, arg,
span, span,
) { )
.unwrap();
assert!(!obligations.needs_infer());
impl2_predicates.extend( impl2_predicates.extend(
traits::elaborate_obligations(tcx, obligations) traits::elaborate_obligations(tcx, obligations)
.map(|obligation| obligation.predicate), .map(|obligation| obligation.predicate),
) )
} })
} }
impl2_predicates.extend( impl2_predicates.extend(
traits::elaborate_predicates_with_span(tcx, always_applicable_traits) traits::elaborate_predicates_with_span(tcx, always_applicable_traits)

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `Self: Get` is not satisfied error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-for-unimpl-trait.rs:10:40 --> $DIR/associated-types-for-unimpl-trait.rs:10:5
| |
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `T: Get` is not satisfied error[E0277]: the trait bound `T: Get` is not satisfied
--> $DIR/associated-types-no-suitable-bound.rs:11:21 --> $DIR/associated-types-no-suitable-bound.rs:11:5
| |
LL | fn uhoh<T>(foo: <T as Get>::Value) {} LL | fn uhoh<T>(foo: <T as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
| |
help: consider restricting type parameter `T` help: consider restricting type parameter `T`
| |

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `Self: Get` is not satisfied error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40 --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
| |
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,14 +1,14 @@
error[E0277]: the trait bound `(T, U): Get` is not satisfied error[E0277]: the trait bound `(T, U): Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:22:40 --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
| |
LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
error[E0277]: the trait bound `Self: Get` is not satisfied error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:17:40 --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
| |
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `Self: Get` is not satisfied error[E0277]: the trait bound `Self: Get` is not satisfied
--> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5
| |
LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value); LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
| ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
| |
help: consider further restricting `Self` help: consider further restricting `Self`
| |

View file

@ -45,16 +45,20 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
| +++++ | +++++
error[E0277]: the trait bound `(): Foo` is not satisfied error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/issue-59324.rs:23:29 --> $DIR/issue-59324.rs:23:1
| |
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {} LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
error[E0277]: the trait bound `Bug: Foo` is not satisfied error[E0277]: the trait bound `Bug: Foo` is not satisfied
--> $DIR/issue-59324.rs:16:8 --> $DIR/issue-59324.rs:16:5
| |
LL | fn get_service( LL | / fn get_service(
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` LL | |
LL | |
LL | | &self,
LL | | ) -> Self::AssocType;
| |_________________________^ the trait `Foo` is not implemented for `Bug`
| |
help: consider further restricting this bound help: consider further restricting this bound
| |

View file

@ -1,8 +1,10 @@
error[E0277]: the trait bound `isize: HasState` is not satisfied error[E0277]: the trait bound `isize: HasState` is not satisfied
--> $DIR/issue-18611.rs:1:18 --> $DIR/issue-18611.rs:1:1
| |
LL | fn add_state(op: <isize as HasState>::State) { LL | / fn add_state(op: <isize as HasState>::State) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` LL | |
LL | | }
| |_^ the trait `HasState` is not implemented for `isize`
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,8 +1,14 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> $DIR/issue-20831-debruijn.rs:28:8 --> $DIR/issue-20831-debruijn.rs:28:5
| |
LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) { LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
| ^^^^^^^^^ LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | | //
... |
LL | | self.sub = t;
LL | | }
| |_____^
| |
note: first, the lifetime cannot outlive the anonymous lifetime defined here... note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> $DIR/issue-20831-debruijn.rs:28:58 --> $DIR/issue-20831-debruijn.rs:28:58
@ -15,10 +21,16 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
LL | impl<'a> Publisher<'a> for MyStruct<'a> { LL | impl<'a> Publisher<'a> for MyStruct<'a> {
| ^^ | ^^
note: ...so that the types are compatible note: ...so that the types are compatible
--> $DIR/issue-20831-debruijn.rs:28:8 --> $DIR/issue-20831-debruijn.rs:28:5
| |
LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) { LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
| ^^^^^^^^^ LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | | //
... |
LL | | self.sub = t;
LL | | }
| |_____^
= note: expected `<MyStruct<'a> as Publisher<'_>>` = note: expected `<MyStruct<'a> as Publisher<'_>>`
found `<MyStruct<'_> as Publisher<'_>>` found `<MyStruct<'_> as Publisher<'_>>`

View file

@ -6,7 +6,8 @@ trait Trait2<'a> {
} }
fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) { fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
//~^ the trait bound `for<'a> (): Trait2<'a>` is not satisfied //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
//~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
let _e: (usize, usize) = unsafe{mem::transmute(param)}; let _e: (usize, usize) = unsafe{mem::transmute(param)};
} }

View file

@ -1,9 +1,19 @@
error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
--> $DIR/issue-35570.rs:8:1
|
LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
LL | |
LL | |
LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)};
LL | | }
| |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
--> $DIR/issue-35570.rs:8:40 --> $DIR/issue-35570.rs:8:40
| |
LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) { LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
error: aborting due to previous error error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View file

@ -1,8 +1,8 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
--> $DIR/normalization-bounds-error.rs:12:4 --> $DIR/normalization-bounds-error.rs:12:1
| |
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
| ^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: first, the lifetime cannot outlive the lifetime `'d` as defined here... note: first, the lifetime cannot outlive the lifetime `'d` as defined here...
--> $DIR/normalization-bounds-error.rs:12:14 --> $DIR/normalization-bounds-error.rs:12:14
@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
| ^^ | ^^
note: ...so that the types are compatible note: ...so that the types are compatible
--> $DIR/normalization-bounds-error.rs:12:4 --> $DIR/normalization-bounds-error.rs:12:1
| |
LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
| ^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Visitor<'d>` = note: expected `Visitor<'d>`
found `Visitor<'_>` found `Visitor<'_>`

View file

@ -19,7 +19,8 @@ trait Trait2<'a, 'b> {
// since for it to be WF, we would need to know that `'y: 'x`, but we // since for it to be WF, we would need to know that `'y: 'x`, but we
// do not infer that. // do not infer that.
fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >) fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
//~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
//~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
{ {
} }

View file

@ -1,3 +1,18 @@
error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
|
LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
LL | |
LL | |
LL | | {
LL | | }
| |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
| ++++++++++++++++++++++++
error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49 --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49
| |
@ -9,6 +24,6 @@ help: consider restricting type parameter `T`
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >) LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
| ++++++++++++++++++++++++ | ++++++++++++++++++++++++
error: aborting due to previous error error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View file

@ -1,8 +1,12 @@
error[E0277]: the trait bound `B: Clone` is not satisfied error[E0277]: the trait bound `B: Clone` is not satisfied
--> $DIR/issue-79224.rs:18:17 --> $DIR/issue-79224.rs:18:1
| |
LL | impl<B: ?Sized> Display for Cow<'_, B> { LL | / impl<B: ?Sized> Display for Cow<'_, B> {
| ^^^^^^^ the trait `Clone` is not implemented for `B` LL | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
LL | | write!(f, "foo")
LL | | }
LL | | }
| |_^ the trait `Clone` is not implemented for `B`
| |
= note: required because of the requirements on the impl of `ToOwned` for `B` = note: required because of the requirements on the impl of `ToOwned` for `B`
help: consider further restricting this bound help: consider further restricting this bound
@ -11,10 +15,12 @@ LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
| +++++++++++++++++++ | +++++++++++++++++++
error[E0277]: the trait bound `B: Clone` is not satisfied error[E0277]: the trait bound `B: Clone` is not satisfied
--> $DIR/issue-79224.rs:19:12 --> $DIR/issue-79224.rs:19:5
| |
LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { LL | / fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
| ^^^^^ the trait `Clone` is not implemented for `B` LL | | write!(f, "foo")
LL | | }
| |_____^ the trait `Clone` is not implemented for `B`
| |
= note: required because of the requirements on the impl of `ToOwned` for `B` = note: required because of the requirements on the impl of `ToOwned` for `B`
help: consider further restricting this bound help: consider further restricting this bound

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
--> $DIR/issue-91594.rs:10:6 --> $DIR/issue-91594.rs:10:1
| |
LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {} LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
| |
= help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo` = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
note: required because of the requirements on the impl of `Component<Foo>` for `Foo` note: required because of the requirements on the impl of `Component<Foo>` for `Foo`

View file

@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): Foo` is not satisfied error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/wf-foreign-fn-decl-ret.rs:11:25 --> $DIR/wf-foreign-fn-decl-ret.rs:11:5
| |
LL | pub fn lint_me() -> <() as Foo>::Assoc; LL | pub fn lint_me() -> <() as Foo>::Assoc;
| ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
--> $DIR/wf-foreign-fn-decl-ret.rs:14:32 --> $DIR/wf-foreign-fn-decl-ret.rs:14:32