diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
commit | 94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch) | |
tree | 2b827afe6a05f3538db3f7803a88c4587fe85648 /compiler/rustc_trait_selection/src/traits/specialize | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip |
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_trait_selection/src/traits/specialize/mod.rs | 134 | ||||
-rw-r--r-- | compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs | 48 |
2 files changed, 68 insertions, 114 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 6223c5ea3..c89165858 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -12,22 +12,21 @@ pub mod specialization_graph; use specialization_graph::GraphExt; +use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::{ - self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine, TraitEngineExt, -}; +use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder}; +use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, ImplSubject, TyCtxt}; +use rustc_middle::ty::{InternalSubsts, SubstsRef}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; use rustc_span::{Span, DUMMY_SP}; +use super::util; use super::SelectionContext; -use super::{util, FulfillmentContext}; /// Information pertinent to an overlapping impl error. #[derive(Debug)] @@ -74,8 +73,8 @@ pub struct OverlapError { /// through associated type projection. We deal with such cases by using /// *fulfillment* to relate the two impls, requiring that all projections are /// resolved. -pub fn translate_substs<'a, 'tcx>( - infcx: &InferCtxt<'a, 'tcx>, +pub fn translate_substs<'tcx>( + infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, source_impl: DefId, source_substs: SubstsRef<'tcx>, @@ -150,14 +149,9 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); // Create an infcx, taking the predicates of impl1 as assumptions: - tcx.infer_ctxt().enter(|infcx| { - let impl1_trait_ref = match traits::fully_normalize( - &infcx, - FulfillmentContext::new(), - ObligationCause::dummy(), - penv, - impl1_trait_ref, - ) { + let infcx = tcx.infer_ctxt().build(); + let impl1_trait_ref = + match traits::fully_normalize(&infcx, ObligationCause::dummy(), penv, impl1_trait_ref) { Ok(impl1_trait_ref) => impl1_trait_ref, Err(_errors) => { tcx.sess.delay_span_bug( @@ -168,9 +162,8 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, } }; - // Attempt to prove that impl2 applies, given all of the above. - fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok() - }) + // Attempt to prove that impl2 applies, given all of the above. + fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok() } /// Attempt to fulfill all obligations of `target_impl` after unification with @@ -178,8 +171,8 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, /// generics of `target_impl`, including both those needed to unify with /// `source_trait_ref` and those whose identity is determined via a where /// clause in the impl. -fn fulfill_implication<'a, 'tcx>( - infcx: &InferCtxt<'a, 'tcx>, +fn fulfill_implication<'tcx>( + infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, source_trait_ref: ty::TraitRef<'tcx>, target_impl: DefId, @@ -211,11 +204,8 @@ fn fulfill_implication<'a, 'tcx>( // (which are packed up in penv) infcx.save_and_restore_in_snapshot_flag(|infcx| { - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); - for oblig in obligations.chain(more_obligations) { - fulfill_cx.register_predicate_obligation(&infcx, oblig); - } - match fulfill_cx.select_all_or_error(infcx).as_slice() { + let errors = traits::fully_solve_obligations(&infcx, obligations.chain(more_obligations)); + match &errors[..] { [] => { debug!( "fulfill_implication: an impl for {:?} specializes {:?}", @@ -333,35 +323,13 @@ fn report_negative_positive_conflict( positive_impl_def_id: DefId, sg: &mut specialization_graph::Graph, ) { - let impl_span = tcx.def_span(local_impl_def_id); - - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0751, - "found both positive and negative implementation of trait `{}`{}:", - overlap.trait_desc, - overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty)) - ); - - match tcx.span_of_impl(negative_impl_def_id) { - Ok(span) => { - err.span_label(span, "negative implementation here"); - } - Err(cname) => { - err.note(&format!("negative implementation in crate `{}`", cname)); - } - } - - match tcx.span_of_impl(positive_impl_def_id) { - Ok(span) => { - err.span_label(span, "positive implementation here"); - } - Err(cname) => { - err.note(&format!("positive implementation in crate `{}`", cname)); - } - } - + let mut err = tcx.sess.create_err(NegativePositiveConflict { + impl_span: tcx.def_span(local_impl_def_id), + trait_desc: &overlap.trait_desc, + self_desc: &overlap.self_desc, + negative_impl_span: tcx.span_of_impl(negative_impl_def_id), + positive_impl_span: tcx.span_of_impl(positive_impl_def_id), + }); sg.has_errored = Some(err.emit()); } @@ -377,26 +345,12 @@ fn report_conflicting_impls( // Work to be done after we've built the DiagnosticBuilder. We have to define it // now because the struct_lint methods don't return back the DiagnosticBuilder // that's passed in. - fn decorate<G: EmissionGuarantee>( + fn decorate<'a, 'b, G: EmissionGuarantee>( tcx: TyCtxt<'_>, overlap: OverlapError, - used_to_be_allowed: Option<FutureCompatOverlapErrorKind>, impl_span: Span, - err: LintDiagnosticBuilder<'_, G>, - ) -> G { - let msg = format!( - "conflicting implementations of trait `{}`{}{}", - overlap.trait_desc, - overlap - .self_desc - .clone() - .map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }), - match used_to_be_allowed { - Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)", - _ => "", - } - ); - let mut err = err.build(&msg); + err: &'b mut DiagnosticBuilder<'a, G>, + ) -> &'b mut DiagnosticBuilder<'a, G> { match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { err.span_label(span, "first implementation here"); @@ -411,7 +365,9 @@ fn report_conflicting_impls( } Err(cname) => { let msg = match to_pretty_impl_header(tcx, overlap.with_impl) { - Some(s) => format!("conflicting implementation in crate `{}`:\n- {}", cname, s), + Some(s) => { + format!("conflicting implementation in crate `{}`:\n- {}", cname, s) + } None => format!("conflicting implementation in crate `{}`", cname), }; err.note(&msg); @@ -419,28 +375,33 @@ fn report_conflicting_impls( } for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(&mut err); + cause.add_intercrate_ambiguity_hint(err); } if overlap.involves_placeholder { - coherence::add_placeholder_note(&mut err); + coherence::add_placeholder_note(err); } - err.emit() + err } + let msg = format!( + "conflicting implementations of trait `{}`{}{}", + overlap.trait_desc, + overlap.self_desc.as_deref().map_or_else(String::new, |ty| format!(" for type `{ty}`")), + match used_to_be_allowed { + Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)", + _ => "", + } + ); + match used_to_be_allowed { None => { let reported = if overlap.with_impl.is_local() || tcx.orphan_check_impl(impl_def_id).is_ok() { - let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); - Some(decorate( - tcx, - overlap, - used_to_be_allowed, - impl_span, - LintDiagnosticBuilder::new(err), - )) + let mut err = struct_span_err!(tcx.sess, impl_span, E0119, "{msg}",); + decorate(tcx, overlap, impl_span, &mut err); + Some(err.emit()) } else { Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check")) }; @@ -455,9 +416,8 @@ fn report_conflicting_impls( lint, tcx.hir().local_def_id_to_hir_id(impl_def_id), impl_span, - |ldb| { - decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb); - }, + msg, + |err| decorate(tcx, overlap, impl_span, err), ); } }; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index fcb73b43f..63f89a33e 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -137,9 +137,8 @@ impl ChildrenExt<'_> for Children { impl_def_id, traits::SkipLeakCheck::default(), overlap_mode, - |_| true, - || false, - ); + ) + .is_some(); let error = create_overlap_error(overlap); @@ -162,34 +161,29 @@ impl ChildrenExt<'_> for Children { impl_def_id, traits::SkipLeakCheck::Yes, overlap_mode, - |overlap| { - if let Some(overlap_kind) = - tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) - { - match overlap_kind { - ty::ImplOverlapKind::Permitted { marker: _ } => {} - ty::ImplOverlapKind::Issue33140 => { - *last_lint_mut = Some(FutureCompatOverlapError { - error: create_overlap_error(overlap), - kind: FutureCompatOverlapErrorKind::Issue33140, - }); - } + ) + .map_or(Ok((false, false)), |overlap| { + if let Some(overlap_kind) = + tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) + { + match overlap_kind { + ty::ImplOverlapKind::Permitted { marker: _ } => {} + ty::ImplOverlapKind::Issue33140 => { + *last_lint_mut = Some(FutureCompatOverlapError { + error: create_overlap_error(overlap), + kind: FutureCompatOverlapErrorKind::Issue33140, + }); } - - return Ok((false, false)); } - let le = tcx.specializes((impl_def_id, possible_sibling)); - let ge = tcx.specializes((possible_sibling, impl_def_id)); + return Ok((false, false)); + } - if le == ge { - report_overlap_error(overlap, last_lint_mut) - } else { - Ok((le, ge)) - } - }, - || Ok((false, false)), - )?; + let le = tcx.specializes((impl_def_id, possible_sibling)); + let ge = tcx.specializes((possible_sibling, impl_def_id)); + + if le == ge { report_overlap_error(overlap, last_lint_mut) } else { Ok((le, ge)) } + })?; if le && !ge { debug!( |