Skip to content

Commit

Permalink
Auto merge of rust-lang#87201 - GuillaumeGomez:rollup-4loi2q9, r=Guil…
Browse files Browse the repository at this point in the history
…laumeGomez

Rollup of 7 pull requests

Successful merges:

 - rust-lang#87107 (Loop over all opaque types instead of looking at just the first one with the same DefId)
 - rust-lang#87158 (Suggest full enum variant for local modules)
 - rust-lang#87174 (Stabilize `[T; N]::map()`)
 - rust-lang#87179 (Mark `const_trait_impl` as active)
 - rust-lang#87180 (feat(rustdoc): open sidebar menu when links inside it are focused)
 - rust-lang#87188 (Add GUI test for auto-hide-trait-implementations setting)
 - rust-lang#87200 (TAIT: Infer all inference variables in opaque type substitutions via InferCx)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 16, 2021
2 parents c49895d + 7d36d69 commit 74ef0c3
Show file tree
Hide file tree
Showing 57 changed files with 162 additions and 233 deletions.
10 changes: 6 additions & 4 deletions compiler/rustc_data_structures/src/vec_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,15 @@ impl<K, V> IntoIterator for VecMap<K, V> {
}
}

impl<K, V> Extend<(K, V)> for VecMap<K, V> {
impl<K: PartialEq, V> Extend<(K, V)> for VecMap<K, V> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
self.0.extend(iter);
for (k, v) in iter {
self.insert(k, v);
}
}

fn extend_one(&mut self, item: (K, V)) {
self.0.extend_one(item);
fn extend_one(&mut self, (k, v): (K, V)) {
self.insert(k, v);
}

fn extend_reserve(&mut self, additional: usize) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ declare_features! (
(active, bindings_after_at, "1.41.0", Some(65490), None),

/// Allows `impl const Trait for T` syntax.
(incomplete, const_trait_impl, "1.42.0", Some(67792), None),
(active, const_trait_impl, "1.42.0", Some(67792), None),

/// Allows `T: ?const Trait` syntax in bounds.
(incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, TypeFoldable)]
pub struct OpaqueTypeKey<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
Expand Down
14 changes: 6 additions & 8 deletions compiler/rustc_trait_selection/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
/// - `substs`, the substs used to instantiate this opaque type
/// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
/// `opaque_defn.concrete_ty`
#[instrument(skip(self))]
fn infer_opaque_definition_from_instantiation(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
Expand All @@ -576,18 +577,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let OpaqueTypeKey { def_id, substs } = opaque_type_key;

debug!(
"infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
def_id, instantiated_ty
);

// Use substs to build up a reverse map from regions to their
// identity mappings. This is necessary because of `impl
// Trait` lifetimes are computed by replacing existing
// lifetimes with 'static and remapping only those used in the
// `impl Trait` return type, resulting in the parameters
// shifting.
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
debug!(?id_substs);
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();

Expand All @@ -602,7 +599,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
instantiated_ty,
span,
));
debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
debug!(?definition_ty);

definition_ty
}
Expand Down Expand Up @@ -857,14 +854,15 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
self.tcx.mk_generator(def_id, substs, movability)
}

ty::Param(..) => {
ty::Param(param) => {
// Look it up in the substitution list.
match self.map.get(&ty.into()).map(|k| k.unpack()) {
// Found it in the substitution list; replace with the parameter from the
// opaque type.
Some(GenericArgKind::Type(t1)) => t1,
Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
None => {
debug!(?param, ?self.map);
self.tcx
.sess
.struct_span_err(
Expand Down Expand Up @@ -931,8 +929,8 @@ struct Instantiator<'a, 'tcx> {
}

impl<'a, 'tcx> Instantiator<'a, 'tcx> {
#[instrument(skip(self))]
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
debug!("instantiate_opaque_types_in_map(value={:?})", value);
let tcx = self.infcx.tcx;
value.fold_with(&mut BottomUpFolder {
tcx,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::{is_range_literal, Node};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
use rustc_span::symbol::sym;
use rustc_span::Span;
Expand Down Expand Up @@ -201,7 +202,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let sole_field = &variant.fields[0];
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.can_coerce(expr_ty, sole_field_ty) {
let variant_path = self.tcx.def_path_str(variant.def_id);
let variant_path =
with_no_trimmed_paths(|| self.tcx.def_path_str(variant.def_id));
// FIXME #56861: DRYer prelude filtering
if let Some(path) = variant_path.strip_prefix("std::prelude::") {
if let Some((_, path)) = path.split_once("::") {
Expand Down
117 changes: 1 addition & 116 deletions compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,9 @@ use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType};
use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
use rustc_session::config;
use rustc_session::parse::feature_err;
use rustc_session::Session;
Expand Down Expand Up @@ -321,117 +319,6 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDe
&*tcx.typeck(def_id).used_trait_imports
}

/// Inspects the substs of opaque types, replacing any inference variables
/// with proper generic parameter from the identity substs.
///
/// This is run after we normalize the function signature, to fix any inference
/// variables introduced by the projection of associated types. This ensures that
/// any opaque types used in the signature continue to refer to generic parameters,
/// allowing them to be considered for defining uses in the function body
///
/// For example, consider this code.
///
/// ```rust
/// trait MyTrait {
/// type MyItem;
/// fn use_it(self) -> Self::MyItem
/// }
/// impl<T, I> MyTrait for T where T: Iterator<Item = I> {
/// type MyItem = impl Iterator<Item = I>;
/// fn use_it(self) -> Self::MyItem {
/// self
/// }
/// }
/// ```
///
/// When we normalize the signature of `use_it` from the impl block,
/// we will normalize `Self::MyItem` to the opaque type `impl Iterator<Item = I>`
/// However, this projection result may contain inference variables, due
/// to the way that projection works. We didn't have any inference variables
/// in the signature to begin with - leaving them in will cause us to incorrectly
/// conclude that we don't have a defining use of `MyItem`. By mapping inference
/// variables back to the actual generic parameters, we will correctly see that
/// we have a defining use of `MyItem`
fn fixup_opaque_types<'tcx, T>(tcx: TyCtxt<'tcx>, val: T) -> T
where
T: TypeFoldable<'tcx>,
{
struct FixupFolder<'tcx> {
tcx: TyCtxt<'tcx>,
}

impl<'tcx> TypeFolder<'tcx> for FixupFolder<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
}

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match *ty.kind() {
ty::Opaque(def_id, substs) => {
debug!("fixup_opaque_types: found type {:?}", ty);
// Here, we replace any inference variables that occur within
// the substs of an opaque type. By definition, any type occurring
// in the substs has a corresponding generic parameter, which is what
// we replace it with.
// This replacement is only run on the function signature, so any
// inference variables that we come across must be the rust of projection
// (there's no other way for a user to get inference variables into
// a function signature).
if ty.needs_infer() {
let new_substs = InternalSubsts::for_item(self.tcx, def_id, |param, _| {
let old_param = substs[param.index as usize];
match old_param.unpack() {
GenericArgKind::Type(old_ty) => {
if let ty::Infer(_) = old_ty.kind() {
// Replace inference type with a generic parameter
self.tcx.mk_param_from_def(param)
} else {
old_param.fold_with(self)
}
}
GenericArgKind::Const(old_const) => {
if let ty::ConstKind::Infer(_) = old_const.val {
// This should never happen - we currently do not support
// 'const projections', e.g.:
// `impl<T: SomeTrait> MyTrait for T where <T as SomeTrait>::MyConst == 25`
// which should be the only way for us to end up with a const inference
// variable after projection. If Rust ever gains support for this kind
// of projection, this should *probably* be changed to
// `self.tcx.mk_param_from_def(param)`
bug!(
"Found infer const: `{:?}` in opaque type: {:?}",
old_const,
ty
);
} else {
old_param.fold_with(self)
}
}
GenericArgKind::Lifetime(old_region) => {
if let RegionKind::ReVar(_) = old_region {
self.tcx.mk_param_from_def(param)
} else {
old_param.fold_with(self)
}
}
}
});
let new_ty = self.tcx.mk_opaque(def_id, new_substs);
debug!("fixup_opaque_types: new type: {:?}", new_ty);
new_ty
} else {
ty
}
}
_ => ty.super_fold_with(self),
}
}
}

debug!("fixup_opaque_types({:?})", val);
val.fold_with(&mut FixupFolder { tcx })
}

fn typeck_const_arg<'tcx>(
tcx: TyCtxt<'tcx>,
(did, param_did): (LocalDefId, DefId),
Expand Down Expand Up @@ -510,8 +397,6 @@ fn typeck_with_fallback<'tcx>(
fn_sig,
);

let fn_sig = fixup_opaque_types(tcx, fn_sig);

let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
fcx
} else {
Expand Down
52 changes: 28 additions & 24 deletions compiler/rustc_typeck/src/check/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {

debug_assert!(!instantiated_ty.has_escaping_bound_vars());

let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap();

// Prevent:
// * `fn foo<T>() -> Foo<T>`
// * `fn foo<T: Bound + Other>() -> Foo<T>`
Expand All @@ -508,6 +510,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
// fn foo<U>() -> Foo<U> { .. }
// ```
// figures out the concrete type with `U`, but the stored type is with `T`.

// FIXME: why are we calling this here? This seems too early, and duplicated.
let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
opaque_type_key,
instantiated_ty,
Expand All @@ -529,33 +533,33 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
}

if !opaque_type_key.substs.needs_infer() {
// We only want to add an entry into `concrete_opaque_types`
// if we actually found a defining usage of this opaque type.
// Otherwise, we do nothing - we'll either find a defining usage
// in some other location, or we'll end up emitting an error due
// to the lack of defining usage
if !skip_add {
let old_concrete_ty = self
.typeck_results
.concrete_opaque_types
.insert(opaque_type_key, definition_ty);
if let Some(old_concrete_ty) = old_concrete_ty {
if old_concrete_ty != definition_ty {
span_bug!(
span,
"`visit_opaque_types` tried to write different types for the same \
if opaque_type_key.substs.needs_infer() {
span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs)
}

// We only want to add an entry into `concrete_opaque_types`
// if we actually found a defining usage of this opaque type.
// Otherwise, we do nothing - we'll either find a defining usage
// in some other location, or we'll end up emitting an error due
// to the lack of defining usage
if !skip_add {
let old_concrete_ty = self
.typeck_results
.concrete_opaque_types
.insert(opaque_type_key, definition_ty);
if let Some(old_concrete_ty) = old_concrete_ty {
if old_concrete_ty != definition_ty {
span_bug!(
span,
"`visit_opaque_types` tried to write different types for the same \
opaque type: {:?}, {:?}, {:?}, {:?}",
opaque_type_key.def_id,
definition_ty,
opaque_defn,
old_concrete_ty,
);
}
opaque_type_key.def_id,
definition_ty,
opaque_defn,
old_concrete_ty,
);
}
}
} else {
self.tcx().sess.delay_span_bug(span, "`opaque_defn` has inference variables");
}
}
}
Expand Down
Loading

0 comments on commit 74ef0c3

Please sign in to comment.