Apply EarlyBinder only to TraitRef in ImplTraitHeader

This commit is contained in:
Yoshitomo Nakanishi 2024-03-05 20:19:05 +01:00
parent 8c9a75b323
commit 9669934798
22 changed files with 74 additions and 82 deletions

View file

@ -1612,10 +1612,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.any(|impl_def_id| { .any(|impl_def_id| {
let impl_header = tcx.impl_trait_header(impl_def_id); let impl_header = tcx.impl_trait_header(impl_def_id);
impl_header.is_some_and(|header| { impl_header.is_some_and(|header| {
let header = header.instantiate( let trait_ref = header.trait_ref.instantiate(
tcx, tcx,
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
); );
let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
// FIXME: Don't bother dealing with non-lifetime binders here... // FIXME: Don't bother dealing with non-lifetime binders here...
if value.has_escaping_bound_vars() { if value.has_escaping_bound_vars() {
@ -1624,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
infcx infcx
.can_eq( .can_eq(
ty::ParamEnv::empty(), ty::ParamEnv::empty(),
header.trait_ref.self_ty(), trait_ref.self_ty(),
value, value,
) && header.polarity != ty::ImplPolarity::Negative ) && header.polarity != ty::ImplPolarity::Negative
}) })
@ -1677,9 +1678,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.filter(|header| { .filter(|header| {
// Consider only accessible traits // Consider only accessible traits
tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
&& header.skip_binder().polarity != ty::ImplPolarity::Negative && header.polarity != ty::ImplPolarity::Negative
}) })
.map(|header| header.instantiate_identity().trait_ref.self_ty()) .map(|header| header.trait_ref.instantiate_identity().self_ty())
// We don't care about blanket impls. // We don't care about blanket impls.
.filter(|self_ty| !self_ty.has_non_region_param()) .filter(|self_ty| !self_ty.has_non_region_param())
.map(|self_ty| tcx.erase_regions(self_ty).to_string()) .map(|self_ty| tcx.erase_regions(self_ty).to_string())

View file

@ -530,11 +530,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
} }
DefKind::Impl { of_trait } => { DefKind::Impl { of_trait } => {
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
check_impl_items_against_trait( check_impl_items_against_trait(tcx, def_id, impl_trait_header);
tcx,
def_id,
impl_trait_header.instantiate_identity(),
);
check_on_unimplemented(tcx, def_id); check_on_unimplemented(tcx, def_id);
} }
} }
@ -725,10 +721,11 @@ fn check_impl_items_against_trait<'tcx>(
impl_id: LocalDefId, impl_id: LocalDefId,
impl_trait_header: ty::ImplTraitHeader<'tcx>, impl_trait_header: ty::ImplTraitHeader<'tcx>,
) { ) {
let trait_ref = impl_trait_header.trait_ref.instantiate_identity();
// If the trait reference itself is erroneous (so the compilation is going // If the trait reference itself is erroneous (so the compilation is going
// to fail), skip checking the items here -- the `impl_item` table in `tcx` // to fail), skip checking the items here -- the `impl_item` table in `tcx`
// isn't populated for such impls. // isn't populated for such impls.
if impl_trait_header.references_error() { if trait_ref.references_error() {
return; return;
} }
@ -752,7 +749,7 @@ fn check_impl_items_against_trait<'tcx>(
} }
} }
let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id); let trait_def = tcx.trait_def(trait_ref.def_id);
for &impl_item in impl_item_refs { for &impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item); let ty_impl_item = tcx.associated_item(impl_item);
@ -771,10 +768,10 @@ fn check_impl_items_against_trait<'tcx>(
)); ));
} }
ty::AssocKind::Fn => { ty::AssocKind::Fn => {
compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref);
} }
ty::AssocKind::Type => { ty::AssocKind::Type => {
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref);
} }
} }
@ -794,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>(
let mut must_implement_one_of: Option<&[Ident]> = let mut must_implement_one_of: Option<&[Ident]> =
trait_def.must_implement_one_of.as_deref(); trait_def.must_implement_one_of.as_deref();
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) { for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) {
let leaf_def = ancestors.leaf_def(tcx, trait_item_id); let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
let is_implemented = leaf_def let is_implemented = leaf_def
@ -872,7 +869,7 @@ fn check_impl_items_against_trait<'tcx>(
if let Some(missing_items) = must_implement_one_of { if let Some(missing_items) = must_implement_one_of {
let attr_span = tcx let attr_span = tcx
.get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of) .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of)
.map(|attr| attr.span); .map(|attr| attr.span);
missing_items_must_implement_one_of_err( missing_items_must_implement_one_of_err(

View file

@ -247,7 +247,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
hir::ItemKind::Impl(impl_) => { hir::ItemKind::Impl(impl_) => {
let header = tcx.impl_trait_header(def_id); let header = tcx.impl_trait_header(def_id);
let is_auto = header let is_auto = header
.is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id)); .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id));
crate::impl_wf_check::check_impl_wf(tcx, def_id)?; crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
let mut res = Ok(()); let mut res = Ok(());
@ -261,7 +261,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
.emit()); .emit());
} }
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match header.map(|h| h.skip_binder().polarity) { match header.map(|h| h.polarity) {
// `None` means this is an inherent impl // `None` means this is an inherent impl
Some(ty::ImplPolarity::Positive) | None => { Some(ty::ImplPolarity::Positive) | None => {
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));

View file

@ -25,7 +25,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCause}; use rustc_trait_selection::traits::{self, ObligationCause};
use std::collections::BTreeMap; use std::collections::BTreeMap;
pub fn check_trait<'tcx>( pub(super) fn check_trait<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_def_id: DefId, trait_def_id: DefId,
impl_def_id: LocalDefId, impl_def_id: LocalDefId,
@ -66,10 +66,9 @@ impl<'tcx> Checker<'tcx> {
fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
let tcx = checker.tcx; let tcx = checker.tcx;
let header = checker.impl_header;
let impl_did = checker.impl_def_id; let impl_did = checker.impl_def_id;
// Destructors only work on local ADT types. // Destructors only work on local ADT types.
match header.trait_ref.self_ty().kind() { match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() {
ty::Adt(def, _) if def.did().is_local() => return Ok(()), ty::Adt(def, _) if def.did().is_local() => return Ok(()),
ty::Error(_) => return Ok(()), ty::Error(_) => return Ok(()),
_ => {} _ => {}
@ -86,7 +85,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
let impl_did = checker.impl_def_id; let impl_did = checker.impl_def_id;
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
let self_type = impl_header.trait_ref.self_ty(); let self_type = impl_header.trait_ref.instantiate_identity().self_ty();
debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
let param_env = tcx.param_env(impl_did); let param_env = tcx.param_env(impl_did);
@ -120,7 +119,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
let tcx = checker.tcx; let tcx = checker.tcx;
let header = checker.impl_header; let header = checker.impl_header;
let impl_did = checker.impl_def_id; let impl_did = checker.impl_def_id;
let self_type = header.trait_ref.self_ty(); let self_type = header.trait_ref.instantiate_identity().self_ty();
assert!(!self_type.has_escaping_bound_vars()); assert!(!self_type.has_escaping_bound_vars());
let param_env = tcx.param_env(impl_did); let param_env = tcx.param_env(impl_did);
@ -157,9 +156,8 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E
fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
let tcx = checker.tcx; let tcx = checker.tcx;
let header = checker.impl_header;
let impl_did = checker.impl_def_id; let impl_did = checker.impl_def_id;
let trait_ref = header.trait_ref; let trait_ref = checker.impl_header.trait_ref.instantiate_identity();
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
let span = tcx.def_span(impl_did); let span = tcx.def_span(impl_did);

View file

@ -134,11 +134,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
let mut res = tcx.ensure().specialization_graph_of(def_id); let mut res = tcx.ensure().specialization_graph_of(def_id);
for &impl_def_id in impls { for &impl_def_id in impls {
let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); let trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
let trait_def = tcx.trait_def(trait_header.trait_ref.def_id); let trait_ref = trait_header.trait_ref.instantiate_identity();
let trait_def = tcx.trait_def(trait_ref.def_id);
res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def)); res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def));
res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref));
res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def));
res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));

View file

@ -13,9 +13,10 @@ pub(super) fn check_item(
trait_header: ImplTraitHeader<'_>, trait_header: ImplTraitHeader<'_>,
trait_def: &TraitDef, trait_def: &TraitDef,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let trait_ref = trait_header.trait_ref;
let unsafe_attr = let unsafe_attr =
tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
let trait_ref = trait_header.trait_ref.instantiate_identity();
match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) {
(Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => {
let span = tcx.def_span(def_id); let span = tcx.def_span(def_id);

View file

@ -1519,10 +1519,7 @@ fn suggest_impl_trait<'tcx>(
None None
} }
fn impl_trait_header( fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
let icx = ItemCtxt::new(tcx, def_id); let icx = ItemCtxt::new(tcx, def_id);
let item = tcx.hir().expect_item(def_id); let item = tcx.hir().expect_item(def_id);
let impl_ = item.expect_impl(); let impl_ = item.expect_impl();
@ -1558,11 +1555,11 @@ fn impl_trait_header(
} else { } else {
icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
}; };
ty::EarlyBinder::bind(ty::ImplTraitHeader { ty::ImplTraitHeader {
trait_ref, trait_ref: ty::EarlyBinder::bind(trait_ref),
unsafety: impl_.unsafety, unsafety: impl_.unsafety,
polarity: polarity_of_impl(tcx, def_id, impl_, item.span) polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
}) }
}) })
} }

View file

@ -3368,11 +3368,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"inherent impls can't be candidates, only trait impls can be", "inherent impls can't be candidates, only trait impls can be",
) )
}) })
.filter(|header| { .filter(|header| header.polarity == ty::ImplPolarity::Negative)
header.skip_binder().polarity == ty::ImplPolarity::Negative
})
.any(|header| { .any(|header| {
let imp = header.instantiate_identity().trait_ref; let imp = header.trait_ref.instantiate_identity();
let imp_simp = let imp_simp =
simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
imp_simp.is_some_and(|s| s == simp_rcvr_ty) imp_simp.is_some_and(|s| s == simp_rcvr_ty)

View file

@ -1993,9 +1993,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { if of_trait && let Some(header) = tcx.impl_trait_header(def_id) {
record!(self.tables.impl_trait_header[def_id] <- header); record!(self.tables.impl_trait_header[def_id] <- header);
let trait_ref = header.map_bound(|h| h.trait_ref);
let trait_ref = trait_ref.instantiate_identity(); let trait_ref = header.trait_ref.instantiate_identity();
let simplified_self_ty = fast_reject::simplify_type( let simplified_self_ty = fast_reject::simplify_type(
self.tcx, self.tcx,
trait_ref.self_ty(), trait_ref.self_ty(),

View file

@ -423,7 +423,7 @@ define_tables! {
variances_of: Table<DefIndex, LazyArray<ty::Variance>>, variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
impl_trait_header: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>, impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>,
const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>, const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>,
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>, optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,

View file

@ -177,8 +177,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> {
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()]; type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
} }
impl EraseType for Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> { impl EraseType for Option<ty::ImplTraitHeader<'_>> {
type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>()]; type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()];
} }
impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> { impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {

View file

@ -840,7 +840,7 @@ rustc_queries! {
/// Given an `impl_id`, return the trait it implements along with some header information. /// Given an `impl_id`, return the trait it implements along with some header information.
/// Return `None` if this is an inherent impl. /// Return `None` if this is an inherent impl.
query impl_trait_header(impl_id: DefId) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'tcx>>> { query impl_trait_header(impl_id: DefId) -> Option<ty::ImplTraitHeader<'tcx>> {
desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
cache_on_disk_if { impl_id.is_local() } cache_on_disk_if { impl_id.is_local() }
separate_provide_extern separate_provide_extern

View file

@ -2310,12 +2310,11 @@ impl<'tcx> TyCtxt<'tcx> {
self, self,
def_id: impl IntoQueryParam<DefId>, def_id: impl IntoQueryParam<DefId>,
) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> { ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref)) Some(self.impl_trait_header(def_id)?.trait_ref)
} }
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity { pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
self.impl_trait_header(def_id) self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity)
.map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity)
} }
} }

View file

@ -250,9 +250,9 @@ pub struct ImplHeader<'tcx> {
pub predicates: Vec<Predicate<'tcx>>, pub predicates: Vec<Predicate<'tcx>>,
} }
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable, HashStable)] #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ImplTraitHeader<'tcx> { pub struct ImplTraitHeader<'tcx> {
pub trait_ref: ty::TraitRef<'tcx>, pub trait_ref: ty::EarlyBinder<ty::TraitRef<'tcx>>,
pub polarity: ImplPolarity, pub polarity: ImplPolarity,
pub unsafety: hir::Unsafety, pub unsafety: hir::Unsafety,
} }
@ -1624,12 +1624,15 @@ impl<'tcx> TyCtxt<'tcx> {
def_id1: DefId, def_id1: DefId,
def_id2: DefId, def_id2: DefId,
) -> Option<ImplOverlapKind> { ) -> Option<ImplOverlapKind> {
let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity(); let impl1 = self.impl_trait_header(def_id1).unwrap();
let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity(); let impl2 = self.impl_trait_header(def_id2).unwrap();
let trait_ref1 = impl1.trait_ref.skip_binder();
let trait_ref2 = impl2.trait_ref.skip_binder();
// If either trait impl references an error, they're allowed to overlap, // If either trait impl references an error, they're allowed to overlap,
// as one of them essentially doesn't exist. // as one of them essentially doesn't exist.
if impl1.references_error() || impl2.references_error() { if trait_ref1.references_error() || trait_ref2.references_error() {
return Some(ImplOverlapKind::Permitted { marker: false }); return Some(ImplOverlapKind::Permitted { marker: false });
} }
@ -1650,7 +1653,7 @@ impl<'tcx> TyCtxt<'tcx> {
let is_marker_overlap = { let is_marker_overlap = {
let is_marker_impl = let is_marker_impl =
|trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker }; |trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker };
is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref) is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2)
}; };
if is_marker_overlap { if is_marker_overlap {

View file

@ -1361,7 +1361,7 @@ fn create_mono_items_for_default_impls<'tcx>(
return; return;
}; };
if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) { if matches!(impl_.polarity, ty::ImplPolarity::Negative) {
return; return;
} }
@ -1385,7 +1385,7 @@ fn create_mono_items_for_default_impls<'tcx>(
} }
}; };
let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params); let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref; let trait_ref = impl_.trait_ref.instantiate(tcx, impl_args);
// Unlike 'lazy' monomorphization that begins by collecting items transitively // Unlike 'lazy' monomorphization that begins by collecting items transitively
// called by `main` or other global items, when eagerly monomorphizing impl // called by `main` or other global items, when eagerly monomorphizing impl

View file

@ -166,13 +166,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
if !drcx.args_may_unify( if !drcx.args_may_unify(
goal.predicate.trait_ref(tcx).args, goal.predicate.trait_ref(tcx).args,
impl_trait_header.skip_binder().trait_ref.args, impl_trait_header.trait_ref.skip_binder().args,
) { ) {
return Err(NoSolution); return Err(NoSolution);
} }
// We have to ignore negative impls when projecting. // We have to ignore negative impls when projecting.
let impl_polarity = impl_trait_header.skip_binder().polarity; let impl_polarity = impl_trait_header.polarity;
match impl_polarity { match impl_polarity {
ty::ImplPolarity::Negative => return Err(NoSolution), ty::ImplPolarity::Negative => return Err(NoSolution),
ty::ImplPolarity::Reservation => { ty::ImplPolarity::Reservation => {
@ -183,7 +183,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id); let impl_args = ecx.fresh_args_for_item(impl_def_id);
let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref; let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args);
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?; ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;

View file

@ -47,14 +47,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
if !drcx.args_may_unify( if !drcx.args_may_unify(
goal.predicate.trait_ref.args, goal.predicate.trait_ref.args,
impl_trait_header.skip_binder().trait_ref.args, impl_trait_header.trait_ref.skip_binder().args,
) { ) {
return Err(NoSolution); return Err(NoSolution);
} }
// An upper bound of the certainty of this goal, used to lower the certainty // An upper bound of the certainty of this goal, used to lower the certainty
// of reservation impl to ambiguous during coherence. // of reservation impl to ambiguous during coherence.
let impl_polarity = impl_trait_header.skip_binder().polarity; let impl_polarity = impl_trait_header.polarity;
let maximal_certainty = match impl_polarity { let maximal_certainty = match impl_polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => { ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => {
match impl_polarity == goal.predicate.polarity { match impl_polarity == goal.predicate.polarity {
@ -70,7 +70,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id); let impl_args = ecx.fresh_args_for_item(impl_def_id);
let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref; let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args);
ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx let where_clause_bounds = tcx

View file

@ -1888,13 +1888,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
.tcx .tcx
.all_impls(trait_pred.def_id()) .all_impls(trait_pred.def_id())
.filter_map(|def_id| { .filter_map(|def_id| {
let imp = self.tcx.impl_trait_header(def_id).unwrap().skip_binder(); let imp = self.tcx.impl_trait_header(def_id).unwrap();
if imp.polarity == ty::ImplPolarity::Negative if imp.polarity == ty::ImplPolarity::Negative
|| !self.tcx.is_user_visible_dep(def_id.krate) || !self.tcx.is_user_visible_dep(def_id.krate)
{ {
return None; return None;
} }
let imp = imp.trait_ref; let imp = imp.trait_ref.skip_binder();
self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map( self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
|similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id }, |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
@ -2078,12 +2078,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
.all_impls(def_id) .all_impls(def_id)
// Ignore automatically derived impls and `!Trait` impls. // Ignore automatically derived impls and `!Trait` impls.
.filter_map(|def_id| self.tcx.impl_trait_header(def_id)) .filter_map(|def_id| self.tcx.impl_trait_header(def_id))
.map(ty::EarlyBinder::instantiate_identity) .filter_map(|header| {
.filter(|header| { (header.polarity != ty::ImplPolarity::Negative
header.polarity != ty::ImplPolarity::Negative || self.tcx.is_automatically_derived(def_id))
|| self.tcx.is_automatically_derived(def_id) .then(|| header.trait_ref.instantiate_identity())
}) })
.map(|header| header.trait_ref)
.filter(|trait_ref| { .filter(|trait_ref| {
let self_ty = trait_ref.self_ty(); let self_ty = trait_ref.self_ty();
// Avoid mentioning type parameters. // Avoid mentioning type parameters.

View file

@ -562,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// and so forth that we need to. // and so forth that we need to.
let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
if !drcx if !drcx
.args_may_unify(obligation_args, impl_trait_header.skip_binder().trait_ref.args) .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
{ {
return; return;
} }
@ -577,7 +577,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if self.reject_fn_ptr_impls( if self.reject_fn_ptr_impls(
impl_def_id, impl_def_id,
obligation, obligation,
impl_trait_header.skip_binder().trait_ref.self_ty(), impl_trait_header.trait_ref.skip_binder().self_ty(),
) { ) {
return; return;
} }

View file

@ -42,7 +42,7 @@ use rustc_middle::ty::_match::MatchAgainstFreshVars;
use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::Symbol; use rustc_span::Symbol;
@ -2441,7 +2441,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn match_impl( fn match_impl(
&mut self, &mut self,
impl_def_id: DefId, impl_def_id: DefId,
impl_trait_header: EarlyBinder<ty::ImplTraitHeader<'tcx>>, impl_trait_header: ty::ImplTraitHeader<'tcx>,
obligation: &PolyTraitObligation<'tcx>, obligation: &PolyTraitObligation<'tcx>,
) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> { ) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
let placeholder_obligation = let placeholder_obligation =
@ -2450,8 +2450,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
let impl_trait_header = impl_trait_header.instantiate(self.tcx(), impl_args); let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args);
if impl_trait_header.references_error() { if trait_ref.references_error() {
return Err(()); return Err(());
} }
@ -2464,7 +2464,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
obligation.param_env, obligation.param_env,
obligation.cause.clone(), obligation.cause.clone(),
obligation.recursion_depth + 1, obligation.recursion_depth + 1,
impl_trait_header.trait_ref, trait_ref,
) )
}); });

View file

@ -169,7 +169,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
} }
} }
let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap().instantiate_identity(); let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap();
// We determine whether there's a subset relationship by: // We determine whether there's a subset relationship by:
// //
@ -198,7 +198,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
fulfill_implication( fulfill_implication(
&infcx, &infcx,
penv, penv,
impl1_trait_header.trait_ref, impl1_trait_header.trait_ref.instantiate_identity(),
impl1_def_id, impl1_def_id,
impl2_def_id, impl2_def_id,
|_, _| ObligationCause::dummy(), |_, _| ObligationCause::dummy(),

View file

@ -255,10 +255,9 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
let impl_ = tcx let impl_ = tcx
.impl_trait_header(def_id) .impl_trait_header(def_id)
.unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)) .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
.skip_binder();
let trait_ref = impl_.trait_ref; let trait_ref = impl_.trait_ref.skip_binder();
debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive