diff options
| author | Michael Goulet <michael@errs.io> | 2024-02-13 23:49:39 +0000 | 
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-02-16 15:07:37 +0000 | 
| commit | 9c25823bb4bba6416ca4b15cd956ae92716f82eb (patch) | |
| tree | f721cae71a460391c47a38917f4dd63574b0aee9 /compiler/rustc_trait_selection | |
| parent | 3250e953050be1a6867aac3745742f86ab406361 (diff) | |
| download | rust-9c25823bb4bba6416ca4b15cd956ae92716f82eb.tar.gz rust-9c25823bb4bba6416ca4b15cd956ae92716f82eb.zip | |
Use extension trait derive
Diffstat (limited to 'compiler/rustc_trait_selection')
17 files changed, 86 insertions, 824 deletions
| diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index ef4a0f52f9e..8406880477e 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -17,49 +17,8 @@ use std::fmt::Debug; pub use rustc_infer::infer::*; -pub trait InferCtxtExt<'tcx> { - fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - - fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - - /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. - /// - /// The inputs are: - /// - /// - the def-id of the trait - /// - the type parameters of the trait, including the self-type - /// - the parameter environment - /// - /// Invokes `evaluate_obligation`, so in the event that evaluating - /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent - /// (or EvaluatedToAmbigStackDependent) will be returned. - fn type_implements_trait( - &self, - trait_def_id: DefId, - params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, - param_env: ty::ParamEnv<'tcx>, - ) -> traits::EvaluationResult; - - /// Returns `Some` if a type implements a trait shallowly, without side-effects, - /// along with any errors that would have been reported upon further obligation - /// processing. - /// - /// - If this returns `Some([])`, then the trait holds modulo regions. - /// - If this returns `Some([errors..])`, then the trait has an impl for - /// the self type, but some nested obligations do not hold. - /// - If this returns `None`, no implementation that applies could be found. - /// - /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, - /// this will probably only ever return `Some([])` or `None`. - fn type_implements_trait_shallow( - &self, - trait_def_id: DefId, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Option<Vec<traits::FulfillmentError<'tcx>>>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); @@ -81,6 +40,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item) } + /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. + /// + /// The inputs are: + /// + /// - the def-id of the trait + /// - the type parameters of the trait, including the self-type + /// - the parameter environment + /// + /// Invokes `evaluate_obligation`, so in the event that evaluating + /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent + /// (or EvaluatedToAmbigStackDependent) will be returned. #[instrument(level = "debug", skip(self, params), ret)] fn type_implements_trait( &self, @@ -99,6 +69,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } + /// Returns `Some` if a type implements a trait shallowly, without side-effects, + /// along with any errors that would have been reported upon further obligation + /// processing. + /// + /// - If this returns `Some([])`, then the trait holds modulo regions. + /// - If this returns `Some([errors..])`, then the trait has an impl for + /// the self type, but some nested obligations do not hold. + /// - If this returns `None`, no implementation that applies could be found. + /// + /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, + /// this will probably only ever return `Some([])` or `None`. fn type_implements_trait_shallow( &self, trait_def_id: DefId, @@ -124,19 +105,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } } -pub trait InferCtxtBuilderExt<'tcx> { - fn enter_canonical_trait_query<K, R>( - self, - canonical_key: &Canonical<'tcx, K>, - operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>, - ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution> - where - K: TypeFoldable<TyCtxt<'tcx>>, - R: Debug + TypeFoldable<TyCtxt<'tcx>>, - Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>; -} - -impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { /// The "main method" for a canonicalized trait query. Given the /// canonical key `canonical_key`, this method will create a new /// inference context, instantiate the key, and run your operation diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 756db7cc206..dc9edb6063d 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -3,7 +3,8 @@ use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; -pub trait InferCtxtRegionExt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { /// Resolve regions, using the deep normalizer to normalize any type-outlives /// obligations in the process. This is in `rustc_trait_selection` because /// we need to normalize. @@ -13,13 +14,6 @@ pub trait InferCtxtRegionExt<'tcx> { fn resolve_regions( &self, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Vec<RegionResolutionError<'tcx>>; -} - -impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { - fn resolve_regions( - &self, - outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec<RegionResolutionError<'tcx>> { self.resolve_regions_with_normalize(outlives_env, |ty, origin| { let ty = self.resolve_vars_if_possible(ty); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 803379af005..3abdc4a3330 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -131,22 +131,12 @@ pub enum GenerateProofTree { Never, } -pub trait InferCtxtEvalExt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { /// Evaluates a goal from **outside** of the trait solver. /// /// Using this while inside of the solver is wrong as it uses a new /// search graph which would break cycle detection. - fn evaluate_root_goal( - &self, - goal: Goal<'tcx, ty::Predicate<'tcx>>, - generate_proof_tree: GenerateProofTree, - ) -> ( - Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>, - Option<inspect::GoalEvaluation<'tcx>>, - ); -} - -impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] fn evaluate_root_goal( &self, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index eab59624436..406f4c2f615 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -17,14 +17,8 @@ use crate::solve::inspect::ProofTreeBuilder; use crate::traits::StructurallyNormalizeExt; use crate::traits::TraitEngineExt; -pub trait InferCtxtSelectExt<'tcx> { - fn select_in_new_trait_solver( - &self, - obligation: &PolyTraitObligation<'tcx>, - ) -> SelectionResult<'tcx, Selection<'tcx>>; -} - -impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { fn select_in_new_trait_solver( &self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index f33d0f397ce..1c6c2ff594a 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -216,15 +216,8 @@ pub trait ProofTreeVisitor<'tcx> { fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>; } -pub trait ProofTreeInferCtxtExt<'tcx> { - fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( - &self, - goal: Goal<'tcx, ty::Predicate<'tcx>>, - visitor: &mut V, - ) -> ControlFlow<V::BreakTy>; -} - -impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 94a3cef8ad1..11e1e72e04e 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -61,10 +61,7 @@ enum GoalEvaluationKind { Nested { is_normalizes_to_hack: IsNormalizesToHack }, } -trait CanonicalResponseExt { - fn has_no_inference_or_external_constraints(&self) -> bool; -} - +#[extension] impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> { fn has_no_inference_or_external_constraints(&self) -> bool { self.value.external_constraints.region_constraints.is_empty() diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index caf950037fd..b234b8a9d03 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -27,11 +27,8 @@ use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; -pub trait TraitEngineExt<'tcx> { - fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>; -} - -impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { +#[extension] +pub impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> { if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index 15d064d4036..80581d01f6b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -11,38 +11,8 @@ use super::ArgKind; pub use rustc_infer::traits::error_reporting::*; -pub trait InferCtxtExt<'tcx> { - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>; - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option<Span>, - expected_args: Vec<ArgKind>, - found_args: Vec<ArgKind>, - is_closure: bool, - closure_pipe_span: Option<Span>, - ) -> DiagnosticBuilder<'tcx>; - - /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` - /// in that order, and returns the generic type corresponding to the - /// argument of that trait (corresponding to the closure arguments). - fn type_implements_fn_trait( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: ty::Binder<'tcx, Ty<'tcx>>, - polarity: ty::ImplPolarity, - ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Given some node representing a fn-like thing in the HIR map, /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to @@ -229,6 +199,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { err } + /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` + /// in that order, and returns the generic type corresponding to the + /// argument of that trait (corresponding to the closure arguments). fn type_implements_fn_trait( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index f0773fd1671..7d7f415c7bb 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -23,24 +23,6 @@ use crate::errors::{ use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; -pub trait TypeErrCtxtExt<'tcx> { - /*private*/ - fn impl_similar_to( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> Option<(DefId, GenericArgsRef<'tcx>)>; - - /*private*/ - fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str>; - - fn on_unimplemented_note( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> OnUnimplementedNote; -} - /// The symbols which are always allowed in a format string static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ kw::SelfUpper, @@ -56,7 +38,8 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ sym::Trait, ]; -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn impl_similar_to( &self, trait_ref: ty::PolyTraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 335e6ff2822..58c731a8ed7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -106,279 +106,6 @@ impl<'tcx, 'a> CoroutineData<'tcx, 'a> { } } -// This trait is public to expose the diagnostics methods to clippy. -pub trait TypeErrCtxtExt<'tcx> { - fn suggest_restricting_param_bound( - &self, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - associated_item: Option<(&'static str, Ty<'tcx>)>, - body_id: LocalDefId, - ); - - fn suggest_dereferences( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn get_closure_name( - &self, - def_id: DefId, - err: &mut Diagnostic, - msg: Cow<'static, str>, - ) -> Option<Symbol>; - - fn suggest_fn_call( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn check_for_binding_assigned_block_without_tail_expression( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_add_clone_to_arg( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn extract_callable_info( - &self, - body_id: LocalDefId, - param_env: ty::ParamEnv<'tcx>, - found: Ty<'tcx>, - ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)>; - - fn suggest_add_reference_to_arg( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - has_custom_message: bool, - ) -> bool; - - fn suggest_borrowing_for_object_cast( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - self_ty: Ty<'tcx>, - object_ty: Ty<'tcx>, - ); - - fn suggest_remove_reference( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic); - - fn suggest_change_mut( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_semicolon_removal( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - span: Span, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>; - - fn suggest_impl_trait( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn point_at_returns_when_relevant( - &self, - err: &mut DiagnosticBuilder<'tcx>, - obligation: &PredicateObligation<'tcx>, - ); - - fn report_closure_arg_mismatch( - &self, - span: Span, - found_span: Option<Span>, - found: ty::PolyTraitRef<'tcx>, - expected: ty::PolyTraitRef<'tcx>, - cause: &ObligationCauseCode<'tcx>, - found_node: Option<Node<'_>>, - param_env: ty::ParamEnv<'tcx>, - ) -> DiagnosticBuilder<'tcx>; - - fn note_conflicting_fn_args( - &self, - err: &mut Diagnostic, - cause: &ObligationCauseCode<'tcx>, - expected: Ty<'tcx>, - found: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ); - - fn note_conflicting_closure_bounds( - &self, - cause: &ObligationCauseCode<'tcx>, - err: &mut DiagnosticBuilder<'tcx>, - ); - - fn suggest_fully_qualified_path( - &self, - err: &mut Diagnostic, - item_def_id: DefId, - span: Span, - trait_ref: DefId, - ); - - fn maybe_note_obligation_cause_for_async_await( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - ) -> bool; - - fn note_obligation_cause_for_async_await( - &self, - err: &mut Diagnostic, - interior_or_upvar_span: CoroutineInteriorOrUpvar, - is_async: bool, - outer_coroutine: Option<DefId>, - trait_pred: ty::TraitPredicate<'tcx>, - target_ty: Ty<'tcx>, - obligation: &PredicateObligation<'tcx>, - next_code: Option<&ObligationCauseCode<'tcx>>, - ); - - fn note_obligation_cause_code<T>( - &self, - body_id: LocalDefId, - err: &mut Diagnostic, - predicate: T, - param_env: ty::ParamEnv<'tcx>, - cause_code: &ObligationCauseCode<'tcx>, - obligated_types: &mut Vec<Ty<'tcx>>, - seen_requirements: &mut FxHashSet<DefId>, - ) where - T: ToPredicate<'tcx>; - - /// Suggest to await before try: future? => future.await? - fn suggest_await_before_try( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - trait_pred: ty::PolyTraitPredicate<'tcx>, - span: Span, - ); - - fn suggest_floating_point_literal( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_ref: &ty::PolyTraitRef<'tcx>, - ); - - fn suggest_derive( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_dereferencing_index( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_option_method_if_applicable( - &self, - failed_pred: ty::Predicate<'tcx>, - param_env: ty::ParamEnv<'tcx>, - err: &mut Diagnostic, - expr: &hir::Expr<'_>, - ); - - fn note_function_argument_obligation( - &self, - body_id: LocalDefId, - err: &mut Diagnostic, - arg_hir_id: HirId, - parent_code: &ObligationCauseCode<'tcx>, - param_env: ty::ParamEnv<'tcx>, - predicate: ty::Predicate<'tcx>, - call_hir_id: HirId, - ); - - fn look_for_iterator_item_mistakes( - &self, - assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], - typeck_results: &TypeckResults<'tcx>, - type_diffs: &[TypeError<'tcx>], - param_env: ty::ParamEnv<'tcx>, - path_segment: &hir::PathSegment<'_>, - args: &[hir::Expr<'_>], - err: &mut Diagnostic, - ); - - fn point_at_chain( - &self, - expr: &hir::Expr<'_>, - typeck_results: &TypeckResults<'tcx>, - type_diffs: Vec<TypeError<'tcx>>, - param_env: ty::ParamEnv<'tcx>, - err: &mut Diagnostic, - ); - - fn probe_assoc_types_at_expr( - &self, - type_diffs: &[TypeError<'tcx>], - span: Span, - prev_ty: Ty<'tcx>, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>; - - fn suggest_convert_to_slice( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - candidate_impls: &[ImplCandidate<'tcx>], - span: Span, - ); - - fn explain_hrtb_projection( - &self, - diag: &mut Diagnostic, - pred: ty::PolyTraitPredicate<'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: &ObligationCause<'tcx>, - ); - - fn suggest_desugaring_async_fn_in_trait( - &self, - err: &mut Diagnostic, - trait_ref: ty::PolyTraitRef<'tcx>, - ); -} - fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { ( generics.tail_span_for_predicate_suggestion(), @@ -509,7 +236,8 @@ pub fn suggest_restriction<'tcx>( } } -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn suggest_restricting_param_bound( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 68b1a0d4e61..92992de64ff 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -57,78 +57,8 @@ use super::{ pub use rustc_infer::traits::error_reporting::*; -pub trait TypeErrCtxtExt<'tcx> { - fn build_overflow_error<T>( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx> - where - T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; - - fn report_overflow_error<T>( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - mutate: impl FnOnce(&mut Diagnostic), - ) -> ! - where - T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; - - fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; - - fn report_fulfillment_errors(&self, errors: Vec<FulfillmentError<'tcx>>) -> ErrorGuaranteed; - - fn report_overflow_obligation<T>( - &self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool, - ) -> ! - where - T: ToPredicate<'tcx> + Clone; - - fn suggest_new_overflow_limit(&self, err: &mut Diagnostic); - - fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; - - /// The `root_obligation` parameter should be the `root_obligation` field - /// from a `FulfillmentError`. If no `FulfillmentError` is available, - /// then it should be the same as `obligation`. - fn report_selection_error( - &self, - obligation: PredicateObligation<'tcx>, - root_obligation: &PredicateObligation<'tcx>, - error: &SelectionError<'tcx>, - ) -> ErrorGuaranteed; - - fn emit_specialized_closure_kind_error( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Option<ErrorGuaranteed>; - - fn fn_arg_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> Result<(), ErrorGuaranteed>; - - fn try_conversion_context( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - err: &mut Diagnostic, - ) -> bool; - - fn report_const_param_not_wf( - &self, - ty: Ty<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> DiagnosticBuilder<'tcx>; -} - -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn report_fulfillment_errors( &self, mut errors: Vec<FulfillmentError<'tcx>>, @@ -382,6 +312,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.emit() } + /// The `root_obligation` parameter should be the `root_obligation` field + /// from a `FulfillmentError`. If no `FulfillmentError` is available, + /// then it should be the same as `obligation`. fn report_selection_error( &self, mut obligation: PredicateObligation<'tcx>, @@ -1393,209 +1326,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } -pub(super) trait InferCtxtPrivExt<'tcx> { - // returns if `cond` not occurring implies that `error` does not occur - i.e., that - // `error` occurring implies that `cond` occurs. - fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; - - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed; - - fn report_projection_error( - &self, - obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>, - ) -> ErrorGuaranteed; - - fn maybe_detailed_projection_msg( - &self, - pred: ty::ProjectionPredicate<'tcx>, - normalized_ty: ty::Term<'tcx>, - expected_ty: ty::Term<'tcx>, - ) -> Option<String>; - - fn fuzzy_match_tys( - &self, - a: Ty<'tcx>, - b: Ty<'tcx>, - ignoring_lifetimes: bool, - ) -> Option<CandidateSimilarity>; - - fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str; - - fn find_similar_impl_candidates( - &self, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> Vec<ImplCandidate<'tcx>>; - - fn report_similar_impl_candidates( - &self, - impl_candidates: &[ImplCandidate<'tcx>], - trait_ref: ty::PolyTraitRef<'tcx>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - other: bool, - param_env: ty::ParamEnv<'tcx>, - ) -> bool; - - fn report_similar_impl_candidates_for_root_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - ); - - /// Gets the parent trait chain start - fn get_parent_trait_ref( - &self, - code: &ObligationCauseCode<'tcx>, - ) -> Option<(Ty<'tcx>, Option<Span>)>; - - /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait - /// with the same path as `trait_ref`, a help message about - /// a probable version mismatch is added to `err` - fn note_version_mismatch( - &self, - err: &mut Diagnostic, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> bool; - - /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the - /// `trait_ref`. - /// - /// For this to work, `new_self_ty` must have no escaping bound variables. - fn mk_trait_obligation_with_new_self_ty( - &self, - param_env: ty::ParamEnv<'tcx>, - trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, - ) -> PredicateObligation<'tcx>; - - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed; - - fn predicate_can_apply( - &self, - param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>); - - fn suggest_unsized_bound_if_applicable( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - ); - - fn annotate_source_of_ambiguity( - &self, - err: &mut Diagnostic, - impls: &[ambiguity::Ambiguity], - predicate: ty::Predicate<'tcx>, - ); - - fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>); - - fn maybe_indirection_for_unsized( - &self, - err: &mut Diagnostic, - item: &'tcx Item<'tcx>, - param: &'tcx GenericParam<'tcx>, - ) -> bool; - - fn is_recursive_obligation( - &self, - obligated_types: &mut Vec<Ty<'tcx>>, - cause_code: &ObligationCauseCode<'tcx>, - ) -> bool; - - fn get_standard_error_message( - &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - message: Option<String>, - predicate_is_const: bool, - append_const_msg: Option<AppendConstMessage>, - post_message: String, - ) -> String; - - fn get_safe_transmute_error_and_reason( - &self, - obligation: PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - span: Span, - ) -> GetSafeTransmuteErrorAndReason; - - fn add_tuple_trait_message( - &self, - obligation_cause_code: &ObligationCauseCode<'tcx>, - err: &mut Diagnostic, - ); - - fn try_to_add_help_message( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - is_fn_trait: bool, - suggested: bool, - unsatisfied_const: bool, - ); - - fn add_help_message_for_fn_trait( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - err: &mut Diagnostic, - implemented_kind: ty::ClosureKind, - params: ty::Binder<'tcx, Ty<'tcx>>, - ); - - fn maybe_add_note_for_unsatisfied_const( - &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - ) -> UnsatisfiedConst; - - fn report_closure_error( - &self, - obligation: &PredicateObligation<'tcx>, - closure_def_id: DefId, - found_kind: ty::ClosureKind, - kind: ty::ClosureKind, - trait_prefix: &'static str, - ) -> DiagnosticBuilder<'tcx>; - - fn report_cyclic_signature_error( - &self, - obligation: &PredicateObligation<'tcx>, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - terr: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx>; - - fn report_opaque_type_auto_trait_leakage( - &self, - obligation: &PredicateObligation<'tcx>, - def_id: DefId, - ) -> DiagnosticBuilder<'tcx>; - - fn report_signature_mismatch_error( - &self, - obligation: &PredicateObligation<'tcx>, - span: Span, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>; - - fn report_not_const_evaluatable_error( - &self, - obligation: &PredicateObligation<'tcx>, - span: Span, - ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>; -} - -impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub(super) impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { @@ -2414,6 +2146,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { suggested } + /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the + /// `trait_ref`. + /// + /// For this to work, `new_self_ty` must have no escaping bound variables. fn mk_trait_obligation_with_new_self_ty( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 52631d4353b..c4e8ea45dd3 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -11,25 +11,6 @@ pub use rustc_middle::traits::query::OutlivesBound; pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a; pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a; -pub trait InferCtxtExt<'a, 'tcx> { - /// Do *NOT* call this directly. - fn implied_bounds_tys_compat( - &'a self, - param_env: ty::ParamEnv<'tcx>, - body_id: LocalDefId, - tys: &'a FxIndexSet<Ty<'tcx>>, - compat: bool, - ) -> BoundsCompat<'a, 'tcx>; - - /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` - /// with `compat` set to `true`, otherwise `false`. - fn implied_bounds_tys( - &'a self, - param_env: ty::ParamEnv<'tcx>, - body_id: LocalDefId, - tys: &'a FxIndexSet<Ty<'tcx>>, - ) -> Bounds<'a, 'tcx>; -} /// Implied bounds are region relationships that we deduce /// automatically. The idea is that (e.g.) a caller must check that a @@ -130,7 +111,9 @@ fn implied_outlives_bounds<'a, 'tcx>( bounds } -impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { + /// Do *NOT* call this directly. fn implied_bounds_tys_compat( &'a self, param_env: ParamEnv<'tcx>, @@ -142,6 +125,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat)) } + /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` + /// with `compat` set to `true`, otherwise `false`. fn implied_bounds_tys( &'a self, param_env: ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 049877bc5fe..807540a1720 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -52,12 +52,22 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>; pub(super) struct InProgress; -pub trait NormalizeExt<'tcx> { +#[extension] +pub impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { /// Normalize a value using the `AssocTypeNormalizer`. /// /// This normalization should be used when the type contains inference variables or the /// projection may be fallible. - fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>; + fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> { + if self.infcx.next_trait_solver() { + InferOk { value, obligations: Vec::new() } + } else { + let mut selcx = SelectionContext::new(self.infcx); + let Normalized { value, obligations } = + normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); + InferOk { value, obligations } + } + } /// Deeply normalizes `value`, replacing all aliases which can by normalized in /// the current environment. In the new solver this errors in case normalization @@ -77,25 +87,6 @@ pub trait NormalizeExt<'tcx> { self, value: T, fulfill_cx: &mut dyn TraitEngine<'tcx>, - ) -> Result<T, Vec<FulfillmentError<'tcx>>>; -} - -impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { - fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> { - if self.infcx.next_trait_solver() { - InferOk { value, obligations: Vec::new() } - } else { - let mut selcx = SelectionContext::new(self.infcx); - let Normalized { value, obligations } = - normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); - InferOk { value, obligations } - } - } - - fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>( - self, - value: T, - fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result<T, Vec<FulfillmentError<'tcx>>> { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index a050b30317a..e56ad101d29 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -4,32 +4,8 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; -pub trait InferCtxtExt<'tcx> { - fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool; - - fn predicate_must_hold_considering_regions( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> bool; - - fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool; - - fn evaluate_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> Result<EvaluationResult, OverflowError>; - - // Helper function that canonicalizes and runs the query. If an - // overflow results, we re-run it in the local context so we can - // report a nice error. - /*crate*/ - fn evaluate_obligation_no_overflow( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> EvaluationResult; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) /// in the given `ParamEnv`. fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { @@ -114,9 +90,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } } - // Helper function that canonicalizes and runs the query. If an - // overflow results, we re-run it in the local context so we can - // report a nice error. + /// Helper function that canonicalizes and runs the query. If an + /// overflow results, we re-run it in the local context so we can + /// report a nice error. fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 0b73fefd2da..7dd8a990c3f 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -22,20 +22,8 @@ use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; -pub trait QueryNormalizeExt<'tcx> { - /// Normalize a value using the `QueryNormalizer`. - /// - /// This normalization should *only* be used when the projection does not - /// have possible ambiguity or may not be well-formed. - /// - /// After codegen, when lifetimes do not matter, it is preferable to instead - /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. - fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution> - where - T: TypeFoldable<TyCtxt<'tcx>>; -} - -impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { +#[extension] +pub impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { /// Normalize `value` in the context of the inference context, /// yielding a resulting type, or an error if `value` cannot be /// normalized. If you don't care about regions, you should prefer 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 e9a592bdee7..57e3f72a2f3 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -33,19 +33,7 @@ enum Inserted<'tcx> { ShouldRecurseOn(DefId), } -trait ChildrenExt<'tcx> { - fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); - fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); - - fn insert( - &mut self, - tcx: TyCtxt<'tcx>, - impl_def_id: DefId, - simplified_self: Option<SimplifiedType>, - overlap_mode: OverlapMode, - ) -> Result<Inserted<'tcx>, OverlapError<'tcx>>; -} - +#[extension] impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { @@ -247,22 +235,8 @@ where } } -pub trait GraphExt<'tcx> { - /// Insert a local impl into the specialization graph. If an existing impl - /// conflicts with it (has overlap, but neither specializes the other), - /// information about the area of overlap is returned in the `Err`. - fn insert( - &mut self, - tcx: TyCtxt<'tcx>, - impl_def_id: DefId, - overlap_mode: OverlapMode, - ) -> Result<Option<FutureCompatOverlapError<'tcx>>, OverlapError<'tcx>>; - - /// Insert cached metadata mapping from a child impl back to its parent. - fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId); -} - -impl<'tcx> GraphExt<'tcx> for Graph { +#[extension] +pub impl<'tcx> GraphExt<'tcx> for Graph { /// Insert a local impl into the specialization graph. If an existing impl /// conflicts with it (has overlap, but neither specializes the other), /// information about the area of overlap is returned in the `Err`. diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index ed5d01d7048..7b0a4a69501 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -5,15 +5,8 @@ use rustc_middle::ty::{self, Ty}; use crate::traits::{NormalizeExt, Obligation}; -pub trait StructurallyNormalizeExt<'tcx> { - fn structurally_normalize( - &self, - ty: Ty<'tcx>, - fulfill_cx: &mut dyn TraitEngine<'tcx>, - ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>; -} - -impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { +#[extension] +pub impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { fn structurally_normalize( &self, ty: Ty<'tcx>, | 
