1
Fork 0

Rollup merge of #121059 - compiler-errors:extension, r=davidtwco,Nilstrieb

Add and use a simple extension trait derive macro in the compiler

Adds `#[extension]` to `rustc_macros` for implementing an extension trait. This expands an impl (with an optional visibility) into two parallel trait + impl definitions.

before:
```rust
pub trait Extension {
  fn a();
}
impl Extension for () {
  fn a() {}
}
```

to:
```rust
#[extension]
pub impl Extension for () {
  fn a() {}
}
```

Opted to just implement it by hand because I couldn't figure if there was a "canonical" choice of extension trait macro in the ecosystem. It's really lightweight anyways, and can always be changed.

I'm interested in adding this because I'd like to later split up the large `TypeErrCtxtExt` traits into several different files. This should make it one step easier.
This commit is contained in:
Guillaume Boisseau 2024-02-17 11:23:04 +01:00 committed by GitHub
commit 5ff9022306
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 293 additions and 979 deletions

View file

@ -57,6 +57,7 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate}; use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate};
use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_session::parse::{add_feature_diagnostics, feature_err};
@ -190,16 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
trait ResolverAstLoweringExt { #[extension(trait ResolverAstLoweringExt)]
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; impl ResolverAstLowering {
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
}
impl ResolverAstLoweringExt for ResolverAstLowering {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> { fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
if let ExprKind::Path(None, path) = &expr.kind { if let ExprKind::Path(None, path) = &expr.kind {
// Don't perform legacy const generics rewriting if the path already // Don't perform legacy const generics rewriting if the path already

View file

@ -2,6 +2,7 @@ use crate::location::{LocationIndex, LocationTable};
use crate::BorrowIndex; use crate::BorrowIndex;
use polonius_engine::AllFacts as PoloniusFacts; use polonius_engine::AllFacts as PoloniusFacts;
use polonius_engine::Atom; use polonius_engine::Atom;
use rustc_macros::extension;
use rustc_middle::mir::Local; use rustc_middle::mir::Local;
use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MovePathIndex; use rustc_mir_dataflow::move_paths::MovePathIndex;
@ -24,20 +25,10 @@ impl polonius_engine::FactTypes for RustcFacts {
pub type AllFacts = PoloniusFacts<RustcFacts>; pub type AllFacts = PoloniusFacts<RustcFacts>;
pub(crate) trait AllFactsExt { #[extension(pub(crate) trait AllFactsExt)]
impl AllFacts {
/// Returns `true` if there is a need to gather `AllFacts` given the /// Returns `true` if there is a need to gather `AllFacts` given the
/// current `-Z` flags. /// current `-Z` flags.
fn enabled(tcx: TyCtxt<'_>) -> bool;
fn write_to_dir(
&self,
dir: impl AsRef<Path>,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>>;
}
impl AllFactsExt for AllFacts {
/// Return
fn enabled(tcx: TyCtxt<'_>) -> bool { fn enabled(tcx: TyCtxt<'_>) -> bool {
tcx.sess.opts.unstable_opts.nll_facts tcx.sess.opts.unstable_opts.nll_facts
|| tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() || tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled()

View file

@ -1,24 +1,16 @@
use crate::borrow_set::LocalsStateAtExit; use crate::borrow_set::LocalsStateAtExit;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_macros::extension;
use rustc_middle::mir::ProjectionElem; use rustc_middle::mir::ProjectionElem;
use rustc_middle::mir::{Body, Mutability, Place}; use rustc_middle::mir::{Body, Mutability, Place};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
/// Extension methods for the `Place` type. #[extension(pub trait PlaceExt<'tcx>)]
pub trait PlaceExt<'tcx> { impl<'tcx> Place<'tcx> {
/// Returns `true` if we can safely ignore borrows of this place. /// Returns `true` if we can safely ignore borrows of this place.
/// This is true whenever there is no action that the user can do /// This is true whenever there is no action that the user can do
/// to the place `self` that would invalidate the borrow. This is true /// to the place `self` that would invalidate the borrow. This is true
/// for borrows of raw pointer dereferents as well as shared references. /// for borrows of raw pointer dereferents as well as shared references.
fn ignore_borrow(
&self,
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
locals_state_at_exit: &LocalsStateAtExit,
) -> bool;
}
impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
fn ignore_borrow( fn ignore_borrow(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View file

@ -6,6 +6,7 @@ use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::InferCtxt; use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_macros::extension;
use rustc_middle::traits::DefiningAnchor; use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
@ -225,15 +226,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
} }
} }
pub trait InferCtxtExt<'tcx> { #[extension(pub trait InferCtxtExt<'tcx>)]
fn infer_opaque_definition_from_instantiation( impl<'tcx> InferCtxt<'tcx> {
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
) -> Ty<'tcx>;
}
impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// Given the fully resolved, instantiated type for an opaque /// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2 /// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an opaque type /// (*), computes the "definition type" for an opaque type

View file

@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::BodyOwnerKind; use rustc_hir::BodyOwnerKind;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_macros::extension;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt}; use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt};
@ -793,27 +794,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
} }
} }
trait InferCtxtExt<'tcx> { #[extension(trait InferCtxtExt<'tcx>)]
fn replace_free_regions_with_nll_infer_vars<T>( impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
&self,
origin: NllRegionVariableOrigin,
value: T,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>;
fn replace_bound_regions_with_nll_infer_vars<T>(
&self,
origin: NllRegionVariableOrigin,
all_outlive_scope: LocalDefId,
value: ty::Binder<'tcx, T>,
indices: &mut UniversalRegionIndices<'tcx>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>;
}
impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn replace_free_regions_with_nll_infer_vars<T>( fn replace_free_regions_with_nll_infer_vars<T>(
&self, &self,

View file

@ -14,6 +14,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_macros::extension;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*; use rustc_middle::middle::resolve_bound_vars::*;
@ -27,17 +28,8 @@ use std::fmt;
use crate::errors; use crate::errors;
trait RegionExt { #[extension(trait RegionExt)]
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); impl ResolvedArg {
fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
fn id(&self) -> Option<DefId>;
fn shifted(self, amount: u32) -> ResolvedArg;
}
impl RegionExt for ResolvedArg {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
debug!("ResolvedArg::early: def_id={:?}", param.def_id); debug!("ResolvedArg::early: def_id={:?}", param.def_id);
(param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id())) (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))

View file

@ -13,30 +13,10 @@ use rustc_middle::ty::{self, TyCtxt};
/// FIXME(-Znext-solver): This or public because it is shared with the /// FIXME(-Znext-solver): This or public because it is shared with the
/// new trait solver implementation. We should deduplicate canonicalization. /// new trait solver implementation. We should deduplicate canonicalization.
pub trait CanonicalExt<'tcx, V> { #[extension(pub trait CanonicalExt<'tcx, V>)]
impl<'tcx, V> Canonical<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value /// Instantiate the wrapped value, replacing each canonical value
/// with the value given in `var_values`. /// with the value given in `var_values`.
fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
where
V: TypeFoldable<TyCtxt<'tcx>>;
/// Allows one to apply a instantiation to some subset of
/// `self.value`. Invoke `projection_fn` with `self.value` to get
/// a value V that is expressed in terms of the same canonical
/// variables bound in `self` (usually this extracts from subset
/// of `self`). Apply the instantiation `var_values` to this value
/// V, replacing each of the canonical variables.
fn instantiate_projected<T>(
&self,
tcx: TyCtxt<'tcx>,
var_values: &CanonicalVarValues<'tcx>,
projection_fn: impl FnOnce(&V) -> T,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>;
}
impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
where where
V: TypeFoldable<TyCtxt<'tcx>>, V: TypeFoldable<TyCtxt<'tcx>>,
@ -44,6 +24,12 @@ impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
self.instantiate_projected(tcx, var_values, |value| value.clone()) self.instantiate_projected(tcx, var_values, |value| value.clone())
} }
/// Allows one to apply a instantiation to some subset of
/// `self.value`. Invoke `projection_fn` with `self.value` to get
/// a value V that is expressed in terms of the same canonical
/// variables bound in `self` (usually this extracts from subset
/// of `self`). Apply the instantiation `var_values` to this value
/// V, replacing each of the canonical variables.
fn instantiate_projected<T>( fn instantiate_projected<T>(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View file

@ -2786,19 +2786,8 @@ pub enum FailureCode {
Error0644, Error0644,
} }
pub trait ObligationCauseExt<'tcx> { #[extension(pub trait ObligationCauseExt<'tcx>)]
fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode; impl<'tcx> ObligationCause<'tcx> {
fn as_failure_code_diag(
&self,
terr: TypeError<'tcx>,
span: Span,
subdiags: Vec<TypeErrorAdditionalDiags>,
) -> ObligationCauseFailureCode;
fn as_requirement_str(&self) -> &'static str;
}
impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode { fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode {
use self::FailureCode::*; use self::FailureCode::*;
use crate::traits::ObligationCauseCode::*; use crate::traits::ObligationCauseCode::*;

View file

@ -626,11 +626,8 @@ pub struct InferCtxtBuilder<'tcx> {
next_trait_solver: bool, next_trait_solver: bool,
} }
pub trait TyCtxtInferExt<'tcx> { #[extension(pub trait TyCtxtInferExt<'tcx>)]
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; impl<'tcx> TyCtxt<'tcx> {
}
impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
InferCtxtBuilder { InferCtxtBuilder {
tcx: self, tcx: self,

View file

@ -52,18 +52,8 @@ pub trait TraitEngine<'tcx>: 'tcx {
) -> Vec<PredicateObligation<'tcx>>; ) -> Vec<PredicateObligation<'tcx>>;
} }
pub trait TraitEngineExt<'tcx> { #[extension(pub trait TraitEngineExt<'tcx>)]
fn register_predicate_obligations( impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T {
&mut self,
infcx: &InferCtxt<'tcx>,
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
);
#[must_use]
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
}
impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
fn register_predicate_obligations( fn register_predicate_obligations(
&mut self, &mut self,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
@ -74,6 +64,7 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
} }
} }
#[must_use]
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
let errors = self.select_where_possible(infcx); let errors = self.select_where_possible(infcx);
if !errors.is_empty() { if !errors.is_empty() {

View file

@ -0,0 +1,154 @@
use proc_macro2::Ident;
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{
braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature,
Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility,
};
pub(crate) fn extension(
attr: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr);
let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl);
let headers: Vec<_> = items
.iter()
.map(|item| match item {
ImplItem::Fn(f) => TraitItem::Fn(TraitItemFn {
attrs: scrub_attrs(&f.attrs),
sig: scrub_header(f.sig.clone()),
default: None,
semi_token: Some(Token![;](f.block.span())),
}),
ImplItem::Const(ct) => TraitItem::Const(TraitItemConst {
attrs: scrub_attrs(&ct.attrs),
const_token: ct.const_token,
ident: ct.ident.clone(),
generics: ct.generics.clone(),
colon_token: ct.colon_token,
ty: ct.ty.clone(),
default: None,
semi_token: ct.semi_token,
}),
ImplItem::Type(ty) => TraitItem::Type(TraitItemType {
attrs: scrub_attrs(&ty.attrs),
type_token: ty.type_token,
ident: ty.ident.clone(),
generics: ty.generics.clone(),
colon_token: None,
bounds: Punctuated::new(),
default: None,
semi_token: ty.semi_token,
}),
ImplItem::Macro(mac) => TraitItem::Macro(TraitItemMacro {
attrs: scrub_attrs(&mac.attrs),
mac: mac.mac.clone(),
semi_token: mac.semi_token,
}),
ImplItem::Verbatim(stream) => TraitItem::Verbatim(stream.clone()),
_ => unimplemented!(),
})
.collect();
quote! {
#(#attrs)*
#vis trait #trait_ {
#(#headers)*
}
impl #generics #trait_ for #self_ty {
#(#items)*
}
}
.into()
}
/// Only keep `#[doc]` attrs.
fn scrub_attrs(attrs: &[Attribute]) -> Vec<Attribute> {
attrs
.into_iter()
.cloned()
.filter(|attr| {
let ident = &attr.path().segments[0].ident;
ident == "doc" || ident == "must_use"
})
.collect()
}
/// Scrub arguments so that they're valid for trait signatures.
fn scrub_header(mut sig: Signature) -> Signature {
for (idx, input) in sig.inputs.iter_mut().enumerate() {
match input {
syn::FnArg::Receiver(rcvr) => {
// `mut self` -> `self`
if rcvr.reference.is_none() {
rcvr.mutability.take();
}
}
syn::FnArg::Typed(arg) => match &mut *arg.pat {
Pat::Ident(arg) => {
// `ref mut ident @ pat` -> `ident`
arg.by_ref.take();
arg.mutability.take();
arg.subpat.take();
}
_ => {
// `pat` -> `__arg0`
arg.pat = Box::new(
PatIdent {
attrs: vec![],
by_ref: None,
mutability: None,
ident: Ident::new(&format!("__arg{idx}"), arg.pat.span()),
subpat: None,
}
.into(),
)
}
},
}
}
sig
}
struct ExtensionAttr {
vis: Visibility,
trait_: Path,
}
impl Parse for ExtensionAttr {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let vis = input.parse()?;
let _: Token![trait] = input.parse()?;
let trait_ = input.parse()?;
Ok(ExtensionAttr { vis, trait_ })
}
}
struct Impl {
attrs: Vec<Attribute>,
generics: Generics,
self_ty: Type,
items: Vec<ImplItem>,
}
impl Parse for Impl {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let _: Token![impl] = input.parse()?;
let generics = input.parse()?;
let self_ty = input.parse()?;
let content;
let _brace_token = braced!(content in input);
let mut items = Vec::new();
while !content.is_empty() {
items.push(content.parse()?);
}
Ok(Impl { attrs, generics, self_ty, items })
}
}

View file

@ -14,6 +14,7 @@ use proc_macro::TokenStream;
mod current_version; mod current_version;
mod diagnostics; mod diagnostics;
mod extension;
mod hash_stable; mod hash_stable;
mod lift; mod lift;
mod query; mod query;
@ -40,6 +41,11 @@ pub fn symbols(input: TokenStream) -> TokenStream {
symbols::symbols(input.into()).into() symbols::symbols(input.into()).into()
} }
#[proc_macro_attribute]
pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream {
extension::extension(attr, input)
}
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
decl_derive!( decl_derive!(
[HashStable_Generic, attributes(stable_hasher)] => [HashStable_Generic, attributes(stable_hasher)] =>

View file

@ -23,20 +23,8 @@ use std::fmt;
use std::num::NonZero; use std::num::NonZero;
use std::ops::Bound; use std::ops::Bound;
pub trait IntegerExt { #[extension(pub trait IntegerExt)]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; impl Integer {
fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer;
fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer;
fn repr_discr<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
repr: &ReprOptions,
min: i128,
max: i128,
) -> (Integer, bool);
}
impl IntegerExt for Integer {
#[inline] #[inline]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> {
match (*self, signed) { match (*self, signed) {
@ -123,12 +111,8 @@ impl IntegerExt for Integer {
} }
} }
pub trait PrimitiveExt { #[extension(pub trait PrimitiveExt)]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; impl Primitive {
fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
}
impl PrimitiveExt for Primitive {
#[inline] #[inline]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self { match *self {

View file

@ -96,13 +96,8 @@ impl<'tcx> Discr<'tcx> {
} }
} }
pub trait IntTypeExt { #[extension(pub trait IntTypeExt)]
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; impl IntegerType {
fn disr_incr<'tcx>(&self, tcx: TyCtxt<'tcx>, val: Option<Discr<'tcx>>) -> Option<Discr<'tcx>>;
fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>;
}
impl IntTypeExt for IntegerType {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self { match self {
IntegerType::Pointer(true) => tcx.types.isize, IntegerType::Pointer(true) => tcx.types.isize,

View file

@ -17,49 +17,8 @@ use std::fmt::Debug;
pub use rustc_infer::infer::*; pub use rustc_infer::infer::*;
pub trait InferCtxtExt<'tcx> { #[extension(pub trait InferCtxtExt<'tcx>)]
fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; impl<'tcx> InferCtxt<'tcx> {
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> {
fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
let ty = self.resolve_vars_if_possible(ty); 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) 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)] #[instrument(level = "debug", skip(self, params), ret)]
fn type_implements_trait( fn type_implements_trait(
&self, &self,
@ -99,6 +69,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) 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( fn type_implements_trait_shallow(
&self, &self,
trait_def_id: DefId, trait_def_id: DefId,
@ -124,19 +105,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
} }
} }
pub trait InferCtxtBuilderExt<'tcx> { #[extension(pub trait InferCtxtBuilderExt<'tcx>)]
fn enter_canonical_trait_query<K, R>( impl<'tcx> InferCtxtBuilder<'tcx> {
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> {
/// The "main method" for a canonicalized trait query. Given the /// The "main method" for a canonicalized trait query. Given the
/// canonical key `canonical_key`, this method will create a new /// canonical key `canonical_key`, this method will create a new
/// inference context, instantiate the key, and run your operation /// inference context, instantiate the key, and run your operation

View file

@ -3,20 +3,14 @@ use rustc_infer::infer::{InferCtxt, RegionResolutionError};
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
pub trait InferCtxtRegionExt<'tcx> { #[extension(pub trait InferCtxtRegionExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> {
/// Resolve regions, using the deep normalizer to normalize any type-outlives /// Resolve regions, using the deep normalizer to normalize any type-outlives
/// obligations in the process. This is in `rustc_trait_selection` because /// obligations in the process. This is in `rustc_trait_selection` because
/// we need to normalize. /// we need to normalize.
/// ///
/// Prefer this method over `resolve_regions_with_normalize`, unless you are /// Prefer this method over `resolve_regions_with_normalize`, unless you are
/// doing something specific for normalization. /// doing something specific for normalization.
fn resolve_regions(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
) -> Vec<RegionResolutionError<'tcx>>;
}
impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
fn resolve_regions( fn resolve_regions(
&self, &self,
outlives_env: &OutlivesEnvironment<'tcx>, outlives_env: &OutlivesEnvironment<'tcx>,

View file

@ -131,22 +131,12 @@ pub enum GenerateProofTree {
Never, Never,
} }
pub trait InferCtxtEvalExt<'tcx> { #[extension(pub trait InferCtxtEvalExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> {
/// Evaluates a goal from **outside** of the trait solver. /// Evaluates a goal from **outside** of the trait solver.
/// ///
/// Using this while inside of the solver is wrong as it uses a new /// Using this while inside of the solver is wrong as it uses a new
/// search graph which would break cycle detection. /// 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))] #[instrument(level = "debug", skip(self))]
fn evaluate_root_goal( fn evaluate_root_goal(
&self, &self,

View file

@ -17,14 +17,8 @@ use crate::solve::inspect::ProofTreeBuilder;
use crate::traits::StructurallyNormalizeExt; use crate::traits::StructurallyNormalizeExt;
use crate::traits::TraitEngineExt; use crate::traits::TraitEngineExt;
pub trait InferCtxtSelectExt<'tcx> { #[extension(pub trait InferCtxtSelectExt<'tcx>)]
fn select_in_new_trait_solver( impl<'tcx> InferCtxt<'tcx> {
&self,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>>;
}
impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
fn select_in_new_trait_solver( fn select_in_new_trait_solver(
&self, &self,
obligation: &PolyTraitObligation<'tcx>, obligation: &PolyTraitObligation<'tcx>,

View file

@ -216,15 +216,8 @@ pub trait ProofTreeVisitor<'tcx> {
fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>; fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>;
} }
pub trait ProofTreeInferCtxtExt<'tcx> { #[extension(pub trait ProofTreeInferCtxtExt<'tcx>)]
fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( impl<'tcx> InferCtxt<'tcx> {
&self,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
visitor: &mut V,
) -> ControlFlow<V::BreakTy>;
}
impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(
&self, &self,
goal: Goal<'tcx, ty::Predicate<'tcx>>, goal: Goal<'tcx, ty::Predicate<'tcx>>,

View file

@ -61,11 +61,8 @@ enum GoalEvaluationKind {
Nested { is_normalizes_to_hack: IsNormalizesToHack }, Nested { is_normalizes_to_hack: IsNormalizesToHack },
} }
trait CanonicalResponseExt { #[extension(trait CanonicalResponseExt)]
fn has_no_inference_or_external_constraints(&self) -> bool; impl<'tcx> Canonical<'tcx, Response<'tcx>> {
}
impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> {
fn has_no_inference_or_external_constraints(&self) -> bool { fn has_no_inference_or_external_constraints(&self) -> bool {
self.value.external_constraints.region_constraints.is_empty() self.value.external_constraints.region_constraints.is_empty()
&& self.value.var_values.is_identity() && self.value.var_values.is_identity()

View file

@ -27,11 +27,8 @@ use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::Variance; use rustc_middle::ty::Variance;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
pub trait TraitEngineExt<'tcx> { #[extension(pub trait TraitEngineExt<'tcx>)]
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>; impl<'tcx> dyn TraitEngine<'tcx> {
}
impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> { fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
if infcx.next_trait_solver() { if infcx.next_trait_solver() {
Box::new(NextFulfillmentCtxt::new(infcx)) Box::new(NextFulfillmentCtxt::new(infcx))

View file

@ -11,38 +11,8 @@ use super::ArgKind;
pub use rustc_infer::traits::error_reporting::*; pub use rustc_infer::traits::error_reporting::*;
pub trait InferCtxtExt<'tcx> { #[extension(pub trait InferCtxtExt<'tcx>)]
/// Given some node representing a fn-like thing in the HIR map, impl<'tcx> InferCtxt<'tcx> {
/// 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> {
/// Given some node representing a fn-like thing in the HIR map, /// Given some node representing a fn-like thing in the HIR map,
/// returns a span and `ArgKind` information that describes the /// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to /// arguments it expects. This can be supplied to
@ -229,6 +199,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
err 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( fn type_implements_fn_trait(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,

View file

@ -23,24 +23,6 @@ use crate::errors::{
use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; 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 /// The symbols which are always allowed in a format string
static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
kw::SelfUpper, kw::SelfUpper,
@ -56,7 +38,8 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
sym::Trait, sym::Trait,
]; ];
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { #[extension(pub trait TypeErrCtxtExt<'tcx>)]
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn impl_similar_to( fn impl_similar_to(
&self, &self,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,

View file

@ -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) { fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
( (
generics.tail_span_for_predicate_suggestion(), generics.tail_span_for_predicate_suggestion(),
@ -509,7 +236,8 @@ pub fn suggest_restriction<'tcx>(
} }
} }
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { #[extension(pub trait TypeErrCtxtExt<'tcx>)]
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn suggest_restricting_param_bound( fn suggest_restricting_param_bound(
&self, &self,
err: &mut Diagnostic, err: &mut Diagnostic,

View file

@ -57,78 +57,8 @@ use super::{
pub use rustc_infer::traits::error_reporting::*; pub use rustc_infer::traits::error_reporting::*;
pub trait TypeErrCtxtExt<'tcx> { #[extension(pub trait TypeErrCtxtExt<'tcx>)]
fn build_overflow_error<T>( impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&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> {
fn report_fulfillment_errors( fn report_fulfillment_errors(
&self, &self,
mut errors: Vec<FulfillmentError<'tcx>>, mut errors: Vec<FulfillmentError<'tcx>>,
@ -382,6 +312,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.emit() 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( fn report_selection_error(
&self, &self,
mut obligation: PredicateObligation<'tcx>, mut obligation: PredicateObligation<'tcx>,
@ -1393,209 +1326,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} }
} }
pub(super) trait InferCtxtPrivExt<'tcx> { #[extension(pub(super) trait InferCtxtPrivExt<'tcx>)]
// returns if `cond` not occurring implies that `error` does not occur - i.e., that impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// `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> {
// returns if `cond` not occurring implies that `error` does not occur - i.e., that // returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs. // `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { 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 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( fn mk_trait_obligation_with_new_self_ty(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,

View file

@ -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 BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
pub type Bounds<'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 /// Implied bounds are region relationships that we deduce
/// automatically. The idea is that (e.g.) a caller must check that a /// automatically. The idea is that (e.g.) a caller must check that a
@ -130,7 +111,9 @@ fn implied_outlives_bounds<'a, 'tcx>(
bounds bounds
} }
impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { #[extension(pub trait InferCtxtExt<'a, 'tcx>)]
impl<'a, 'tcx: 'a> InferCtxt<'tcx> {
/// Do *NOT* call this directly.
fn implied_bounds_tys_compat( fn implied_bounds_tys_compat(
&'a self, &'a self,
param_env: ParamEnv<'tcx>, 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)) .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( fn implied_bounds_tys(
&'a self, &'a self,
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,

View file

@ -52,12 +52,22 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
pub(super) struct InProgress; pub(super) struct InProgress;
pub trait NormalizeExt<'tcx> { #[extension(pub trait NormalizeExt<'tcx>)]
impl<'tcx> At<'_, 'tcx> {
/// Normalize a value using the `AssocTypeNormalizer`. /// Normalize a value using the `AssocTypeNormalizer`.
/// ///
/// This normalization should be used when the type contains inference variables or the /// This normalization should be used when the type contains inference variables or the
/// projection may be fallible. /// 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 /// Deeply normalizes `value`, replacing all aliases which can by normalized in
/// the current environment. In the new solver this errors in case normalization /// the current environment. In the new solver this errors in case normalization
@ -73,25 +83,6 @@ pub trait NormalizeExt<'tcx> {
/// existing fulfillment context in the old solver. Once we also eagerly prove goals with /// existing fulfillment context in the old solver. Once we also eagerly prove goals with
/// the old solver or have removed the old solver, remove `traits::fully_normalize` and /// the old solver or have removed the old solver, remove `traits::fully_normalize` and
/// rename this function to `At::fully_normalize`. /// rename this function to `At::fully_normalize`.
fn deeply_normalize<T: TypeFoldable<TyCtxt<'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>>>( fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
self, self,
value: T, value: T,

View file

@ -4,32 +4,8 @@ use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
pub trait InferCtxtExt<'tcx> { #[extension(pub trait InferCtxtExt<'tcx>)]
fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool; impl<'tcx> InferCtxt<'tcx> {
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> {
/// Evaluates whether the predicate can be satisfied (by any means) /// Evaluates whether the predicate can be satisfied (by any means)
/// in the given `ParamEnv`. /// in the given `ParamEnv`.
fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { 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 /// Helper function that canonicalizes and runs the query. If an
// overflow results, we re-run it in the local context so we can /// overflow results, we re-run it in the local context so we can
// report a nice error. /// report a nice error.
fn evaluate_obligation_no_overflow( fn evaluate_obligation_no_overflow(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,

View file

@ -22,20 +22,8 @@ use super::NoSolution;
pub use rustc_middle::traits::query::NormalizationResult; pub use rustc_middle::traits::query::NormalizationResult;
pub trait QueryNormalizeExt<'tcx> { #[extension(pub trait QueryNormalizeExt<'tcx>)]
/// Normalize a value using the `QueryNormalizer`. impl<'cx, 'tcx> At<'cx, 'tcx> {
///
/// 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> {
/// Normalize `value` in the context of the inference context, /// Normalize `value` in the context of the inference context,
/// yielding a resulting type, or an error if `value` cannot be /// yielding a resulting type, or an error if `value` cannot be
/// normalized. If you don't care about regions, you should prefer /// normalized. If you don't care about regions, you should prefer
@ -49,6 +37,12 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
/// normalizing, but for now should be used only when we actually /// normalizing, but for now should be used only when we actually
/// know that normalization will succeed, since error reporting /// know that normalization will succeed, since error reporting
/// and other details are still "under development". /// and other details are still "under development".
///
/// 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> fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where where
T: TypeFoldable<TyCtxt<'tcx>>, T: TypeFoldable<TyCtxt<'tcx>>,

View file

@ -33,20 +33,8 @@ enum Inserted<'tcx> {
ShouldRecurseOn(DefId), ShouldRecurseOn(DefId),
} }
trait ChildrenExt<'tcx> { #[extension(trait ChildrenExt<'tcx>)]
fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); impl<'tcx> Children {
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>>;
}
impl<'tcx> ChildrenExt<'tcx> for Children {
/// Insert an impl into this set of children without comparing to any existing impls. /// 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) { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
@ -247,22 +235,8 @@ where
} }
} }
pub trait GraphExt<'tcx> { #[extension(pub trait GraphExt<'tcx>)]
/// Insert a local impl into the specialization graph. If an existing impl impl<'tcx> Graph {
/// 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 {
/// Insert a local impl into the specialization graph. If an existing impl /// Insert a local impl into the specialization graph. If an existing impl
/// conflicts with it (has overlap, but neither specializes the other), /// conflicts with it (has overlap, but neither specializes the other),
/// information about the area of overlap is returned in the `Err`. /// information about the area of overlap is returned in the `Err`.

View file

@ -5,15 +5,8 @@ use rustc_middle::ty::{self, Ty};
use crate::traits::{NormalizeExt, Obligation}; use crate::traits::{NormalizeExt, Obligation};
pub trait StructurallyNormalizeExt<'tcx> { #[extension(pub trait StructurallyNormalizeExt<'tcx>)]
fn structurally_normalize( impl<'tcx> At<'_, 'tcx> {
&self,
ty: Ty<'tcx>,
fulfill_cx: &mut dyn TraitEngine<'tcx>,
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>;
}
impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
fn structurally_normalize( fn structurally_normalize(
&self, &self,
ty: Ty<'tcx>, ty: Ty<'tcx>,