Auto merge of #65989 - Aaron1011:fix/normalize-param-env, r=nikomatsakis

Normalize all opaque types when converting ParamEnv to Reveal::All

When we normalize a type using a ParamEnv with a reveal mode of
RevealMode::All, we will normalize opaque types to their underlying
types (e.g. `type MyOpaque = impl Foo` -> `StructThatImplsFoo`).
However, the ParamEnv may still have predicates referring to the
un-normalized opaque type (e.g. `<T as MyTrait<MyOpaque>>`). This can
cause trait projection to fail, since a type containing normalized
opaque types will not match up with the un-normalized type in the
`ParamEnv`.

To fix this, we now explicitly normalize all opaque types in
caller_bounds of a `ParamEnv` when changing its mode to
`RevealMode::All`. This ensures that all predicatse will refer to the
underlying types of any opaque types involved, allowing them to be
matched up properly during projection. To reflect the fact that
normalization is occuring, `ParamEnv::with_reveal_all` is renamed to
`ParamEnv::with_reveal_all_normalized`

Fixes #65918
This commit is contained in:
bors 2020-07-31 18:14:59 +00:00
commit 6e87bacd37
19 changed files with 152 additions and 89 deletions

View File

@ -18,7 +18,7 @@ impl<'tcx> TyCtxt<'tcx> {
let substs = InternalSubsts::identity_for_item(self, def_id); let substs = InternalSubsts::identity_for_item(self, def_id);
let instance = ty::Instance::new(def_id, substs); let instance = ty::Instance::new(def_id, substs);
let cid = GlobalId { instance, promoted: None }; let cid = GlobalId { instance, promoted: None };
let param_env = self.param_env(def_id).with_reveal_all(); let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
self.const_eval_global_id(param_env, cid, None) self.const_eval_global_id(param_env, cid, None)
} }

View File

@ -78,7 +78,7 @@ impl<'tcx> ConstValue<'tcx> {
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Option<u128> { ) -> Option<u128> {
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
self.try_to_bits(size) self.try_to_bits(size)
} }

View File

@ -864,11 +864,17 @@ rustc_queries! {
/// type-checking etc, and it does not normalize specializable /// type-checking etc, and it does not normalize specializable
/// associated types. This is almost always what you want, /// associated types. This is almost always what you want,
/// unless you are doing MIR optimizations, in which case you /// unless you are doing MIR optimizations, in which case you
/// might want to use `reveal_all()` method to change modes.
query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> {
desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) }
} }
/// Like `param_env`, but returns the `ParamEnv in `Reveal::All` mode.
/// Prefer this over `tcx.param_env(def_id).with_reveal_all_normalized(tcx)`,
/// as this method is more efficient.
query param_env_reveal_all_normalized(def_id: DefId) -> ty::ParamEnv<'tcx> {
desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) }
}
/// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
/// `ty.is_copy()`, etc, since that will prune the environment where possible. /// `ty.is_copy()`, etc, since that will prune the environment where possible.
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
@ -1527,5 +1533,9 @@ rustc_queries! {
ty::Instance::new(key.value.0.to_def_id(), key.value.2), ty::Instance::new(key.value.0.to_def_id(), key.value.2),
} }
} }
query normalize_opaque_types(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
desc { "normalizing opaque types in {:?}", key }
}
} }
} }

View File

@ -158,7 +158,7 @@ impl<'tcx> Const<'tcx> {
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Option<u128> { ) -> Option<u128> {
assert_eq!(self.ty, ty); assert_eq!(self.ty, ty);
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
// if `ty` does not depend on generic parameters, use an empty param_env // if `ty` does not depend on generic parameters, use an empty param_env
self.val.eval(tcx, param_env).try_to_bits(size) self.val.eval(tcx, param_env).try_to_bits(size)
} }

View File

@ -96,12 +96,16 @@ impl<'tcx> ConstKind<'tcx> {
if let ConstKind::Unevaluated(def, substs, promoted) = self { if let ConstKind::Unevaluated(def, substs, promoted) = self {
use crate::mir::interpret::ErrorHandled; use crate::mir::interpret::ErrorHandled;
let param_env_and_substs = param_env.with_reveal_all().and(substs);
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve` // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
// also does later, but we want to do it before checking for // also does later, but we want to do it before checking for
// inference variables. // inference variables.
let param_env_and_substs = tcx.erase_regions(&param_env_and_substs); // Note that we erase regions *before* calling `with_reveal_all_normalized`,
// so that we don't try to invoke this query with
// any region variables.
let param_env_and_substs = tcx
.erase_regions(&param_env)
.with_reveal_all_normalized(tcx)
.and(tcx.erase_regions(&substs));
// HACK(eddyb) when the query key would contain inference variables, // HACK(eddyb) when the query key would contain inference variables,
// attempt using identity substs and `ParamEnv` instead, that will succeed // attempt using identity substs and `ParamEnv` instead, that will succeed

View File

@ -1903,7 +1903,7 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
/// Computes the layout of a type. Note that this implicitly /// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode. /// executes in "reveal all" mode.
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
let param_env = self.param_env.with_reveal_all(); let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
let ty = self.tcx.normalize_erasing_regions(param_env, ty); let ty = self.tcx.normalize_erasing_regions(param_env, ty);
let layout = self.tcx.layout_raw(param_env.and(ty))?; let layout = self.tcx.layout_raw(param_env.and(ty))?;
let layout = TyAndLayout { ty, layout }; let layout = TyAndLayout { ty, layout };
@ -1927,7 +1927,7 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
/// Computes the layout of a type. Note that this implicitly /// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode. /// executes in "reveal all" mode.
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
let param_env = self.param_env.with_reveal_all(); let param_env = self.param_env.with_reveal_all_normalized(*self.tcx);
let ty = self.tcx.normalize_erasing_regions(param_env, ty); let ty = self.tcx.normalize_erasing_regions(param_env, ty);
let layout = self.tcx.layout_raw(param_env.and(ty))?; let layout = self.tcx.layout_raw(param_env.and(ty))?;
let layout = TyAndLayout { ty, layout }; let layout = TyAndLayout { ty, layout };

View File

@ -1,5 +1,5 @@
// ignore-tidy-filelength // ignore-tidy-filelength
pub use self::fold::{TypeFoldable, TypeVisitor}; pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor};
pub use self::AssocItemContainer::*; pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*; pub use self::BorrowKind::*;
pub use self::IntVarValue::*; pub use self::IntVarValue::*;
@ -1874,9 +1874,15 @@ impl<'tcx> ParamEnv<'tcx> {
/// the desired behavior during codegen and certain other special /// the desired behavior during codegen and certain other special
/// contexts; normally though we want to use `Reveal::UserFacing`, /// contexts; normally though we want to use `Reveal::UserFacing`,
/// which is the default. /// which is the default.
pub fn with_reveal_all(mut self) -> Self { /// All opaque types in the caller_bounds of the `ParamEnv`
self.packed_data |= 1; /// will be normalized to their underlying types.
self /// See PR #65989 and issue #65918 for more details
pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
if self.packed_data & 1 == 1 {
return self;
}
ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All, self.def_id)
} }
/// Returns this same environment but with no caller bounds. /// Returns this same environment but with no caller bounds.
@ -3116,6 +3122,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
context::provide(providers); context::provide(providers);
erase_regions::provide(providers); erase_regions::provide(providers);
layout::provide(providers); layout::provide(providers);
util::provide(providers);
super::util::bug::provide(providers); super::util::bug::provide(providers);
*providers = ty::query::Providers { *providers = ty::query::Providers {
trait_impls_of: trait_def::trait_impls_of_provider, trait_impls_of: trait_def::trait_impls_of_provider,

View File

@ -270,6 +270,17 @@ impl<'tcx> Key for Ty<'tcx> {
} }
} }
impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
type CacheSelector = DefaultCacheSelector;
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for ty::ParamEnv<'tcx> { impl<'tcx> Key for ty::ParamEnv<'tcx> {
type CacheSelector = DefaultCacheSelector; type CacheSelector = DefaultCacheSelector;

View File

@ -3,11 +3,12 @@
use crate::ich::NodeIdHashingMode; use crate::ich::NodeIdHashingMode;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::interpret::{sign_extend, truncate}; use crate::mir::interpret::{sign_extend, truncate};
use crate::ty::fold::TypeFolder;
use crate::ty::layout::IntegerExt; use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt; use crate::ty::query::TyCtxtAt;
use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef}; use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
use crate::ty::TyKind::*; use crate::ty::TyKind::*;
use crate::ty::{self, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable}; use crate::ty::{self, DefIdTree, GenericParamDefKind, List, Ty, TyCtxt, TypeFoldable};
use rustc_apfloat::Float as _; use rustc_apfloat::Float as _;
use rustc_ast::ast; use rustc_ast::ast;
use rustc_attr::{self as attr, SignedInt, UnsignedInt}; use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@ -557,82 +558,84 @@ impl<'tcx> TyCtxt<'tcx> {
def_id: DefId, def_id: DefId,
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
) -> Result<Ty<'tcx>, Ty<'tcx>> { ) -> Result<Ty<'tcx>, Ty<'tcx>> {
use crate::ty::fold::TypeFolder;
struct OpaqueTypeExpander<'tcx> {
// Contains the DefIds of the opaque types that are currently being
// expanded. When we expand an opaque type we insert the DefId of
// that type, and when we finish expanding that type we remove the
// its DefId.
seen_opaque_tys: FxHashSet<DefId>,
// Cache of all expansions we've seen so far. This is a critical
// optimization for some large types produced by async fn trees.
expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
primary_def_id: DefId,
found_recursion: bool,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> OpaqueTypeExpander<'tcx> {
fn expand_opaque_ty(
&mut self,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Option<Ty<'tcx>> {
if self.found_recursion {
return None;
}
let substs = substs.fold_with(self);
if self.seen_opaque_tys.insert(def_id) {
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
Some(expanded_ty) => expanded_ty,
None => {
let generic_ty = self.tcx.type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx, substs);
let expanded_ty = self.fold_ty(concrete_ty);
self.expanded_cache.insert((def_id, substs), expanded_ty);
expanded_ty
}
};
self.seen_opaque_tys.remove(&def_id);
Some(expanded_ty)
} else {
// If another opaque type that we contain is recursive, then it
// will report the error, so we don't have to.
self.found_recursion = def_id == self.primary_def_id;
None
}
}
}
impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Opaque(def_id, substs) = t.kind {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else if t.has_opaque_types() {
t.super_fold_with(self)
} else {
t
}
}
}
let mut visitor = OpaqueTypeExpander { let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(), seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(), expanded_cache: FxHashMap::default(),
primary_def_id: def_id, primary_def_id: Some(def_id),
found_recursion: false, found_recursion: false,
check_recursion: true,
tcx: self, tcx: self,
}; };
let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap(); let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap();
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
} }
} }
struct OpaqueTypeExpander<'tcx> {
// Contains the DefIds of the opaque types that are currently being
// expanded. When we expand an opaque type we insert the DefId of
// that type, and when we finish expanding that type we remove the
// its DefId.
seen_opaque_tys: FxHashSet<DefId>,
// Cache of all expansions we've seen so far. This is a critical
// optimization for some large types produced by async fn trees.
expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
primary_def_id: Option<DefId>,
found_recursion: bool,
/// Whether or not to check for recursive opaque types.
/// This is `true` when we're explicitly checking for opaque type
/// recursion, and 'false' otherwise to avoid unecessary work.
check_recursion: bool,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> OpaqueTypeExpander<'tcx> {
fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
if self.found_recursion {
return None;
}
let substs = substs.fold_with(self);
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
Some(expanded_ty) => expanded_ty,
None => {
let generic_ty = self.tcx.type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx, substs);
let expanded_ty = self.fold_ty(concrete_ty);
self.expanded_cache.insert((def_id, substs), expanded_ty);
expanded_ty
}
};
if self.check_recursion {
self.seen_opaque_tys.remove(&def_id);
}
Some(expanded_ty)
} else {
// If another opaque type that we contain is recursive, then it
// will report the error, so we don't have to.
self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
None
}
}
}
impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Opaque(def_id, substs) = t.kind {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else if t.has_opaque_types() {
t.super_fold_with(self)
} else {
t
}
}
}
impl<'tcx> ty::TyS<'tcx> { impl<'tcx> ty::TyS<'tcx> {
/// Returns the maximum value for the given numeric type (including `char`s) /// Returns the maximum value for the given numeric type (including `char`s)
/// or returns `None` if the type is not numeric. /// or returns `None` if the type is not numeric.
@ -1142,3 +1145,24 @@ pub fn needs_drop_components(
#[derive(Copy, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)] #[derive(Copy, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
pub struct AlwaysRequiresDrop; pub struct AlwaysRequiresDrop;
/// Normalizes all opaque types in the given value, replacing them
/// with their underlying types.
pub fn normalize_opaque_types(
tcx: TyCtxt<'tcx>,
val: &'tcx List<ty::Predicate<'tcx>>,
) -> &'tcx List<ty::Predicate<'tcx>> {
let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(),
primary_def_id: None,
found_recursion: false,
check_recursion: false,
tcx,
};
val.fold_with(&mut visitor)
}
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { normalize_opaque_types, ..*providers }
}

View File

@ -193,7 +193,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
); );
} }
let patch = { let patch = {
let param_env = tcx.param_env(def_id).with_reveal_all(); let param_env = tcx.param_env_reveal_all_normalized(def_id);
let mut elaborator = let mut elaborator =
DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env }; DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env };
let dropee = tcx.mk_place_deref(dropee_ptr); let dropee = tcx.mk_place_deref(dropee_ptr);

View File

@ -328,7 +328,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
) -> ConstPropagator<'mir, 'tcx> { ) -> ConstPropagator<'mir, 'tcx> {
let def_id = source.def_id(); let def_id = source.def_id();
let substs = &InternalSubsts::identity_for_item(tcx, def_id); let substs = &InternalSubsts::identity_for_item(tcx, def_id);
let param_env = tcx.param_env(def_id).with_reveal_all(); let param_env = tcx.param_env_reveal_all_normalized(def_id);
let span = tcx.def_span(def_id); let span = tcx.def_span(def_id);
let can_const_prop = CanConstProp::check(body); let can_const_prop = CanConstProp::check(body);

View File

@ -25,7 +25,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
debug!("elaborate_drops({:?} @ {:?})", src, body.span); debug!("elaborate_drops({:?} @ {:?})", src, body.span);
let def_id = src.def_id(); let def_id = src.def_id();
let param_env = tcx.param_env(src.def_id()).with_reveal_all(); let param_env = tcx.param_env_reveal_all_normalized(src.def_id());
let move_data = match MoveData::gather_moves(body, tcx, param_env) { let move_data = match MoveData::gather_moves(body, tcx, param_env) {
Ok(move_data) => move_data, Ok(move_data) => move_data,
Err((move_data, _)) => { Err((move_data, _)) => {

View File

@ -72,7 +72,7 @@ impl Inliner<'tcx> {
let mut callsites = VecDeque::new(); let mut callsites = VecDeque::new();
let param_env = self.tcx.param_env(self.source.def_id()).with_reveal_all(); let param_env = self.tcx.param_env_reveal_all_normalized(self.source.def_id());
// Only do inlining into fn bodies. // Only do inlining into fn bodies.
let id = self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local()); let id = self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());

View File

@ -189,7 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// Normalize projections and things like that. // Normalize projections and things like that.
// FIXME: We need to reveal_all, as some optimizations change types in ways // FIXME: We need to reveal_all, as some optimizations change types in ways
// that require unfolding opaque types. // that require unfolding opaque types.
let param_env = self.param_env.with_reveal_all(); let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
let src = self.tcx.normalize_erasing_regions(param_env, src); let src = self.tcx.normalize_erasing_regions(param_env, src);
let dest = self.tcx.normalize_erasing_regions(param_env, dest); let dest = self.tcx.normalize_erasing_regions(param_env, dest);

View File

@ -776,7 +776,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// Use `Reveal::All` here because patterns are always monomorphic even if their function // Use `Reveal::All` here because patterns are always monomorphic even if their function
// isn't. // isn't.
let param_env_reveal_all = self.param_env.with_reveal_all(); let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
let substs = self.typeck_results.node_substs(id); let substs = self.typeck_results.node_substs(id);
let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
Ok(Some(i)) => i, Ok(Some(i)) => i,

View File

@ -82,8 +82,10 @@ impl LayoutTest<'tcx> {
} }
sym::debug => { sym::debug => {
let normalized_ty = let normalized_ty = self.tcx.normalize_erasing_regions(
self.tcx.normalize_erasing_regions(param_env.with_reveal_all(), ty); param_env.with_reveal_all_normalized(self.tcx),
ty,
);
self.tcx.sess.span_err( self.tcx.sess.span_err(
item.span, item.span,
&format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout), &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),

View File

@ -271,7 +271,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
let key = self.tcx.def_key(impl_def_id); let key = self.tcx.def_key(impl_def_id);
let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
let mut param_env = self.tcx.param_env(impl_def_id).with_reveal_all(); let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id);
if !substs.is_empty() { if !substs.is_empty() {
param_env = param_env.subst(self.tcx, substs); param_env = param_env.subst(self.tcx, substs);
} }

View File

@ -137,7 +137,7 @@ fn resolve_associated_item<'tcx>(
}); });
let substs = tcx.infer_ctxt().enter(|infcx| { let substs = tcx.infer_ctxt().enter(|infcx| {
let param_env = param_env.with_reveal_all(); let param_env = param_env.with_reveal_all_normalized(tcx);
let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
let substs = translate_substs( let substs = translate_substs(
&infcx, &infcx,

View File

@ -276,6 +276,10 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
} }
fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
tcx.param_env(def_id).with_reveal_all_normalized(tcx)
}
fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator { fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
assert_eq!(crate_num, LOCAL_CRATE); assert_eq!(crate_num, LOCAL_CRATE);
tcx.sess.local_crate_disambiguator() tcx.sess.local_crate_disambiguator()
@ -502,6 +506,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
adt_sized_constraint, adt_sized_constraint,
def_span, def_span,
param_env, param_env,
param_env_reveal_all_normalized,
trait_of_item, trait_of_item,
crate_disambiguator, crate_disambiguator,
original_crate_name, original_crate_name,