Rollup merge of #114566 - fmease:type-alias-laziness-is-crate-specific, r=oli-obk
Store the laziness of type aliases in their `DefKind` Previously, we would treat paths referring to type aliases as *lazy* type aliases if the current crate had lazy type aliases enabled independently of whether the crate which the alias was defined in had the feature enabled or not. With this PR, the laziness of a type alias depends on the crate it is defined in. This generally makes more sense to me especially if / once lazy type aliases become the default in a new edition and we need to think about *edition interoperability*: Consider the hypothetical case where the dependency crate has an older edition (and thus eager type aliases), it exports a type alias with bounds & a where-clause (which are void but technically valid), the dependent crate has the latest edition (and thus lazy type aliases) and it uses that type alias. Arguably, the bounds should *not* be checked since at any time, the dependency crate should be allowed to change the bounds at will with a *non*-major version bump & without negatively affecting downstream crates. As for the reverse case (dependency: lazy type aliases, dependent: eager type aliases), I guess it rules out anything from slight confusion to mild annoyance from upstream crate authors that would be caused by the compiler ignoring the bounds of their type aliases in downstream crates with older editions. --- This fixes #114468 since before, my assumption that the type alias associated with a given weak projection was lazy (and therefore had its variances computed) did not necessarily hold in cross-crate scenarios (which [I kinda had a hunch about](https://github.com/rust-lang/rust/pull/114253#discussion_r1278608099)) as outlined above. Now it does hold. `@rustbot` label F-lazy_type_alias r? `@oli-obk`
This commit is contained in:
commit
3cd0a109a8
49 changed files with 208 additions and 93 deletions
|
@ -907,19 +907,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
did: DefId,
|
||||
item_segment: &hir::PathSegment<'_>,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let args = self.ast_path_args_for_ty(span, did, item_segment);
|
||||
let ty = self.tcx().at(span).type_of(did);
|
||||
let ty = tcx.at(span).type_of(did);
|
||||
|
||||
if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
|
||||
&& (ty.skip_binder().has_opaque_types() || self.tcx().features().lazy_type_alias)
|
||||
if let DefKind::TyAlias { lazy } = tcx.def_kind(did)
|
||||
&& (lazy || ty.skip_binder().has_opaque_types())
|
||||
{
|
||||
// Type aliases referring to types that contain opaque types (but aren't just directly
|
||||
// referencing a single opaque type) get encoded as a type alias that normalization will
|
||||
// referencing a single opaque type) as well as those defined in crates that have the
|
||||
// feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
|
||||
// then actually instantiate the where bounds of.
|
||||
let alias_ty = self.tcx().mk_alias_ty(did, args);
|
||||
Ty::new_alias(self.tcx(), ty::Weak, alias_ty)
|
||||
let alias_ty = tcx.mk_alias_ty(did, args);
|
||||
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
||||
} else {
|
||||
ty.instantiate(self.tcx(), args)
|
||||
ty.instantiate(tcx, args)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2158,7 +2160,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
Res::Def(
|
||||
DefKind::Enum
|
||||
| DefKind::TyAlias
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::ForeignTy,
|
||||
|
|
|
@ -728,7 +728,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
check_opaque(tcx, id);
|
||||
}
|
||||
}
|
||||
DefKind::TyAlias => {
|
||||
DefKind::TyAlias { .. } => {
|
||||
let pty_ty = tcx.type_of(id.owner_id).instantiate_identity();
|
||||
let generics = tcx.generics_of(id.owner_id);
|
||||
check_type_params_are_used(tcx, &generics, pty_ty);
|
||||
|
|
|
@ -1480,7 +1480,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::TyAlias
|
||||
| DefKind::TyAlias { .. }
|
||||
| DefKind::Trait,
|
||||
def_id,
|
||||
) if depth == 0 => Some(def_id),
|
||||
|
@ -1990,7 +1990,7 @@ fn is_late_bound_map(
|
|||
|
||||
hir::TyKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
|
||||
hir::Path { res: Res::Def(DefKind::TyAlias { .. }, alias_def), segments, span },
|
||||
)) => {
|
||||
// See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
|
||||
// args to be unconstrained.
|
||||
|
|
|
@ -78,9 +78,8 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
|
||||
DefKind::TyAlias
|
||||
if tcx.features().lazy_type_alias
|
||||
|| tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
|
||||
DefKind::TyAlias { lazy }
|
||||
if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
|
||||
{
|
||||
constraint_cx.build_constraints_for_item(def_id)
|
||||
}
|
||||
|
@ -111,8 +110,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
|
||||
// The type as returned by `type_of` is the underlying type and generally not a weak projection.
|
||||
// Therefore we need to check the `DefKind` first.
|
||||
if let DefKind::TyAlias = tcx.def_kind(def_id)
|
||||
&& (tcx.features().lazy_type_alias || ty.has_opaque_types())
|
||||
if let DefKind::TyAlias { lazy } = tcx.def_kind(def_id)
|
||||
&& (lazy || ty.has_opaque_types())
|
||||
{
|
||||
self.add_constraints_from_ty(current_item, ty, self.covariant);
|
||||
return;
|
||||
|
|
|
@ -56,9 +56,8 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
|
|||
let crate_map = tcx.crate_variances(());
|
||||
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
|
||||
}
|
||||
DefKind::TyAlias
|
||||
if tcx.features().lazy_type_alias
|
||||
|| tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() =>
|
||||
DefKind::TyAlias { lazy }
|
||||
if lazy || tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() =>
|
||||
{
|
||||
// These are inferred.
|
||||
let crate_map = tcx.crate_variances(());
|
||||
|
|
|
@ -97,9 +97,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
|
|||
}
|
||||
}
|
||||
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
|
||||
DefKind::TyAlias
|
||||
if tcx.features().lazy_type_alias
|
||||
|| tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
|
||||
DefKind::TyAlias { lazy }
|
||||
if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
|
||||
{
|
||||
terms_cx.add_inferreds_for_item(def_id)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue