Rollup merge of #114253 - fmease:compute-variances-for-lazy-ty-aliases, r=oli-obk
Compute variances for lazy type aliases Fixes #114221. CC ``@oli-obk`` r? types
This commit is contained in:
commit
5ea536b35f
22 changed files with 226 additions and 85 deletions
|
@ -245,13 +245,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||||
}
|
}
|
||||||
// `ForeignItem`s are handled separately.
|
// `ForeignItem`s are handled separately.
|
||||||
hir::ItemKind::ForeignMod { .. } => {}
|
hir::ItemKind::ForeignMod { .. } => {}
|
||||||
hir::ItemKind::TyAlias(hir_ty, ..) => {
|
hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
|
||||||
if tcx.features().lazy_type_alias
|
if tcx.features().lazy_type_alias
|
||||||
|| tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
|
|| tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
|
||||||
{
|
{
|
||||||
// Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
|
// Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
|
||||||
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
|
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
|
||||||
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
|
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
|
||||||
|
check_variances_for_type_defn(tcx, item, ast_generics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1700,10 +1701,27 @@ fn check_variances_for_type_defn<'tcx>(
|
||||||
hir_generics: &hir::Generics<'_>,
|
hir_generics: &hir::Generics<'_>,
|
||||||
) {
|
) {
|
||||||
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
|
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
|
||||||
for field in tcx.adt_def(item.owner_id).all_fields() {
|
|
||||||
if field.ty(tcx, identity_args).references_error() {
|
match item.kind {
|
||||||
return;
|
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
||||||
|
for field in tcx.adt_def(item.owner_id).all_fields() {
|
||||||
|
if field.ty(tcx, identity_args).references_error() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ItemKind::TyAlias(..) => {
|
||||||
|
let ty = tcx.type_of(item.owner_id).instantiate_identity();
|
||||||
|
|
||||||
|
if tcx.features().lazy_type_alias || ty.has_opaque_types() {
|
||||||
|
if ty.references_error() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bug!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => bug!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty_predicates = tcx.predicates_of(item.owner_id);
|
let ty_predicates = tcx.predicates_of(item.owner_id);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
use hir::def_id::{DefId, LocalDefId};
|
use hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
|
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
|
||||||
|
|
||||||
use super::terms::VarianceTerm::*;
|
use super::terms::VarianceTerm::*;
|
||||||
|
@ -78,6 +78,12 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
|
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() =>
|
||||||
|
{
|
||||||
|
constraint_cx.build_constraints_for_item(def_id)
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +107,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
|
|
||||||
let inferred_start = self.terms_cx.inferred_starts[&def_id];
|
let inferred_start = self.terms_cx.inferred_starts[&def_id];
|
||||||
let current_item = &CurrentItem { inferred_start };
|
let current_item = &CurrentItem { inferred_start };
|
||||||
match tcx.type_of(def_id).instantiate_identity().kind() {
|
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||||
|
|
||||||
|
// 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())
|
||||||
|
{
|
||||||
|
self.add_constraints_from_ty(current_item, ty, self.covariant);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match ty.kind() {
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
// Not entirely obvious: constraints on structs/enums do not
|
// Not entirely obvious: constraints on structs/enums do not
|
||||||
// affect the variance of their type parameters. See discussion
|
// affect the variance of their type parameters. See discussion
|
||||||
|
@ -127,6 +144,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Error(_) => {}
|
ty::Error(_) => {}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
tcx.def_span(def_id),
|
tcx.def_span(def_id),
|
||||||
|
@ -252,10 +270,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
self.add_constraints_from_args(current, def.did(), args, variance);
|
self.add_constraints_from_args(current, def.did(), args, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(_, ref data) => {
|
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, ref data) => {
|
||||||
self.add_constraints_from_invariant_args(current, data.args, variance);
|
self.add_constraints_from_invariant_args(current, data.args, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::Alias(ty::Weak, ref data) => {
|
||||||
|
self.add_constraints_from_args(current, data.def_id, data.args, variance);
|
||||||
|
}
|
||||||
|
|
||||||
ty::Dynamic(data, r, _) => {
|
ty::Dynamic(data, r, _) => {
|
||||||
// The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
|
// The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
|
||||||
self.add_constraints_from_region(current, r, variance);
|
self.add_constraints_from_region(current, r, variance);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
|
use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
|
||||||
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
|
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// Defines the `TermsContext` basically houses an arena where we can
|
/// Defines the `TermsContext` basically houses an arena where we can
|
||||||
|
@ -56,6 +56,14 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
|
||||||
let crate_map = tcx.crate_variances(());
|
let crate_map = tcx.crate_variances(());
|
||||||
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
|
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() =>
|
||||||
|
{
|
||||||
|
// These are inferred.
|
||||||
|
let crate_map = tcx.crate_variances(());
|
||||||
|
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
|
||||||
|
}
|
||||||
DefKind::OpaqueTy => {
|
DefKind::OpaqueTy => {
|
||||||
return variance_of_opaque(tcx, item_def_id);
|
return variance_of_opaque(tcx, item_def_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
use rustc_arena::DroplessArena;
|
use rustc_arena::DroplessArena;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
|
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use self::VarianceTerm::*;
|
use self::VarianceTerm::*;
|
||||||
|
@ -97,6 +97,12 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
|
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() =>
|
||||||
|
{
|
||||||
|
terms_cx.add_inferreds_for_item(def_id)
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ use rustc_middle::query::Providers;
|
||||||
use rustc_middle::traits::specialization_graph;
|
use rustc_middle::traits::specialization_graph;
|
||||||
use rustc_middle::ty::codec::TyEncoder;
|
use rustc_middle::ty::codec::TyEncoder;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
|
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
|
||||||
|
use rustc_middle::ty::TypeVisitableExt;
|
||||||
use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
|
use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
|
||||||
use rustc_middle::util::common::to_readable_str;
|
use rustc_middle::util::common::to_readable_str;
|
||||||
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
|
||||||
|
@ -1034,7 +1035,7 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_encode_variances(def_kind: DefKind) -> bool {
|
fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool {
|
||||||
match def_kind {
|
match def_kind {
|
||||||
DefKind::Struct
|
DefKind::Struct
|
||||||
| DefKind::Union
|
| DefKind::Union
|
||||||
|
@ -1053,7 +1054,6 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Static(..)
|
| DefKind::Static(..)
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ForeignMod
|
| DefKind::ForeignMod
|
||||||
| DefKind::TyAlias
|
|
||||||
| DefKind::Impl { .. }
|
| DefKind::Impl { .. }
|
||||||
| DefKind::Trait
|
| DefKind::Trait
|
||||||
| DefKind::TraitAlias
|
| DefKind::TraitAlias
|
||||||
|
@ -1067,6 +1067,10 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Closure
|
| DefKind::Closure
|
||||||
| DefKind::Generator
|
| DefKind::Generator
|
||||||
| DefKind::ExternCrate => false,
|
| DefKind::ExternCrate => false,
|
||||||
|
DefKind::TyAlias => {
|
||||||
|
tcx.features().lazy_type_alias
|
||||||
|
|| tcx.type_of(def_id).instantiate_identity().has_opaque_types()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,7 +1353,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
self.encode_default_body_stability(def_id);
|
self.encode_default_body_stability(def_id);
|
||||||
self.encode_deprecation(def_id);
|
self.encode_deprecation(def_id);
|
||||||
}
|
}
|
||||||
if should_encode_variances(def_kind) {
|
if should_encode_variances(tcx, def_id, def_kind) {
|
||||||
let v = self.tcx.variances_of(def_id);
|
let v = self.tcx.variances_of(def_id);
|
||||||
record_array!(self.tables.variances_of[def_id] <- v);
|
record_array!(self.tables.variances_of[def_id] <- v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -749,7 +749,7 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a map with the variance of every item; use `item_variance` instead.
|
/// Gets a map with the variance of every item; use `variances_of` instead.
|
||||||
query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> {
|
query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> {
|
||||||
arena_cache
|
arena_cache
|
||||||
desc { "computing the variances for items in this crate" }
|
desc { "computing the variances for items in this crate" }
|
||||||
|
|
|
@ -5,14 +5,15 @@
|
||||||
// @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
|
// @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
|
||||||
pub struct Carrier<'a>(&'a ());
|
pub struct Carrier<'a>(&'a ());
|
||||||
|
|
||||||
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.generic_params[*].name' \""'b"\"
|
// @count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
|
||||||
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
|
// @is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
|
||||||
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
|
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
|
||||||
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
|
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
|
||||||
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.trait' null
|
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
|
||||||
// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
|
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
|
||||||
|
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
|
||||||
pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
|
// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
|
||||||
|
pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {}
|
||||||
|
|
||||||
impl<'a> Carrier<'a> {
|
impl<'a> Carrier<'a> {
|
||||||
pub type Focus<T> = &'a mut T;
|
pub type Focus<T> = &'a mut T;
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
// @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
|
// @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
|
||||||
pub struct Parametrized<T>(T);
|
pub struct Parametrized<T>(T);
|
||||||
|
|
||||||
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.id' $Parametrized
|
// @count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
|
||||||
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
|
// @is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
|
||||||
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.name' '"Proj"'
|
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
|
||||||
// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.trait' null
|
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
|
||||||
pub type Test = Parametrized<i32>::Proj;
|
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
|
||||||
|
// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
|
||||||
|
pub fn test(_: Parametrized<i32>::Proj) {}
|
||||||
|
|
||||||
/// param_bool
|
/// param_bool
|
||||||
impl Parametrized<bool> {
|
impl Parametrized<bool> {
|
||||||
|
|
|
@ -13,8 +13,8 @@ impl Owner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we handle bound vars correctly.
|
// Make sure we handle bound vars correctly.
|
||||||
// @has 'inherent_projections/type.User.html' '//pre[@class="rust item-decl"]' "for<'a> fn(_: Carrier<'a>::Focus)"
|
// @has 'inherent_projections/fn.user.html' '//pre[@class="rust item-decl"]' "user(_: for<'a> fn(_: Carrier<'a>::Focus))"
|
||||||
pub type User = for<'a> fn(Carrier<'a>::Focus);
|
pub fn user(_: for<'a> fn(Carrier<'a>::Focus)) {}
|
||||||
|
|
||||||
pub struct Carrier<'a>(&'a ());
|
pub struct Carrier<'a>(&'a ());
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@ impl<'a> Carrier<'a> {
|
||||||
// FIXME(inherent_associated_types): Below we link to `Proj` but we should link to `Proj-1`.
|
// FIXME(inherent_associated_types): Below we link to `Proj` but we should link to `Proj-1`.
|
||||||
// The current test checks for the buggy behavior for demonstration purposes.
|
// The current test checks for the buggy behavior for demonstration purposes.
|
||||||
|
|
||||||
// @has 'inherent_projections/type.Test.html'
|
// @has 'inherent_projections/fn.test.html'
|
||||||
// @has - '//pre[@class="rust item-decl"]' "Parametrized<i32>"
|
// @has - '//pre[@class="rust item-decl"]' "test(_: Parametrized<i32>::Proj)"
|
||||||
// @has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj'
|
// @has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj'
|
||||||
// @!has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj-1'
|
// @!has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj-1'
|
||||||
pub type Test = Parametrized<i32>::Proj;
|
pub fn test(_: Parametrized<i32>::Proj) {}
|
||||||
|
|
||||||
pub struct Parametrized<T>(T);
|
pub struct Parametrized<T>(T);
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
|
|
||||||
pub struct Carrier<'a>(&'a ());
|
pub struct Carrier<'a>(&'a ());
|
||||||
|
|
||||||
pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
|
|
||||||
|
|
||||||
impl<'a> Carrier<'a> {
|
impl<'a> Carrier<'a> {
|
||||||
pub type Focus<T> = &'a mut User; //~ ERROR overflow evaluating associated type
|
pub type Focus<T> = &'a mut for<'b> fn(Carrier<'b>::Focus<i32>); //~ ERROR overflow evaluating associated type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: overflow evaluating associated type `Carrier<'b>::Focus<i32>`
|
error: overflow evaluating associated type `Carrier<'b>::Focus<i32>`
|
||||||
--> $DIR/issue-111879-0.rs:11:25
|
--> $DIR/issue-111879-0.rs:9:25
|
||||||
|
|
|
|
||||||
LL | pub type Focus<T> = &'a mut User;
|
LL | pub type Focus<T> = &'a mut for<'b> fn(Carrier<'b>::Focus<i32>);
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
// Test if we correctly normalize `S<'a>::P` with respect to late-bound regions.
|
// Test if we correctly normalize `S<'a>::P` with respect to late-bound regions.
|
||||||
|
|
||||||
type Function = for<'a> fn(&'a i32) -> S<'a>::P;
|
|
||||||
|
|
||||||
struct S<'a>(&'a ());
|
struct S<'a>(&'a ());
|
||||||
|
|
||||||
trait Inter {
|
trait Inter {
|
||||||
|
@ -16,7 +14,7 @@ impl<'a> S<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret_ref_local<'e>() -> &'e i32 {
|
fn ret_ref_local<'e>() -> &'e i32 {
|
||||||
let f: Function = |x| x;
|
let f: for<'a> fn(&'a i32) -> S<'a>::P = |x| x;
|
||||||
|
|
||||||
let local = 0;
|
let local = 0;
|
||||||
f(&local) //~ ERROR cannot return value referencing local variable `local`
|
f(&local) //~ ERROR cannot return value referencing local variable `local`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0515]: cannot return value referencing local variable `local`
|
error[E0515]: cannot return value referencing local variable `local`
|
||||||
--> $DIR/late-bound-regions.rs:22:5
|
--> $DIR/late-bound-regions.rs:20:5
|
||||||
|
|
|
|
||||||
LL | f(&local)
|
LL | f(&local)
|
||||||
| ^^------^
|
| ^^------^
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the current scope
|
|
||||||
--> $DIR/not-found-self-type-differs.rs:17:34
|
|
||||||
|
|
|
||||||
LL | struct Family<T>(T);
|
|
||||||
| ---------------- associated item `Proj` not found for this struct
|
|
||||||
...
|
|
||||||
LL | type Alias = Family<Option<()>>::Proj;
|
|
||||||
| ^^^^ associated item not found in `Family<Option<()>>`
|
|
||||||
|
|
|
||||||
= note: the associated type was found for
|
|
||||||
- `Family<()>`
|
|
||||||
- `Family<Result<T, ()>>`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0220`.
|
|
|
@ -1,16 +0,0 @@
|
||||||
error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the current scope
|
|
||||||
--> $DIR/not-found-self-type-differs.rs:21:40
|
|
||||||
|
|
|
||||||
LL | struct Family<T>(T);
|
|
||||||
| ---------------- associated item `Proj` not found for this struct
|
|
||||||
...
|
|
||||||
LL | let _: Family<std::path::PathBuf>::Proj = ();
|
|
||||||
| ^^^^ associated item not found in `Family<PathBuf>`
|
|
||||||
|
|
|
||||||
= note: the associated type was found for
|
|
||||||
- `Family<()>`
|
|
||||||
- `Family<Result<T, ()>>`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0220`.
|
|
|
@ -1,5 +1,3 @@
|
||||||
// revisions: local alias
|
|
||||||
|
|
||||||
#![feature(inherent_associated_types)]
|
#![feature(inherent_associated_types)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
@ -13,10 +11,7 @@ impl<T> Family<Result<T, ()>> {
|
||||||
type Proj = Self;
|
type Proj = Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(alias)]
|
|
||||||
type Alias = Family<Option<()>>::Proj; //[alias]~ ERROR associated type `Proj` not found for `Family<Option<()>>`
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[cfg(local)]
|
let _: Family<Option<()>>::Proj; //~ ERROR associated type `Proj` not found for `Family<Option<()>>`
|
||||||
let _: Family<std::path::PathBuf>::Proj = (); //[local]~ ERROR associated type `Proj` not found for `Family<PathBuf>`
|
let _: Family<std::path::PathBuf>::Proj = (); //~ ERROR associated type `Proj` not found for `Family<PathBuf>`
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the current scope
|
||||||
|
--> $DIR/not-found-self-type-differs.rs:15:32
|
||||||
|
|
|
||||||
|
LL | struct Family<T>(T);
|
||||||
|
| ---------------- associated item `Proj` not found for this struct
|
||||||
|
...
|
||||||
|
LL | let _: Family<Option<()>>::Proj;
|
||||||
|
| ^^^^ associated item not found in `Family<Option<()>>`
|
||||||
|
|
|
||||||
|
= note: the associated type was found for
|
||||||
|
- `Family<()>`
|
||||||
|
- `Family<Result<T, ()>>`
|
||||||
|
|
||||||
|
error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the current scope
|
||||||
|
--> $DIR/not-found-self-type-differs.rs:16:40
|
||||||
|
|
|
||||||
|
LL | struct Family<T>(T);
|
||||||
|
| ---------------- associated item `Proj` not found for this struct
|
||||||
|
...
|
||||||
|
LL | let _: Family<std::path::PathBuf>::Proj = ();
|
||||||
|
| ^^^^ associated item not found in `Family<PathBuf>`
|
||||||
|
|
|
||||||
|
= note: the associated type was found for
|
||||||
|
- `Family<()>`
|
||||||
|
- `Family<Result<T, ()>>`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0220`.
|
|
@ -17,7 +17,7 @@ impl<T, S> Subj<(T, S)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
type A = S<()>::P;
|
let _: S<()>::P;
|
||||||
|
|
||||||
let _: Subj<(i32, i32)>::Un = 0i32; //~ ERROR mismatched types
|
let _: Subj<(i32, i32)>::Un = 0i32; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@ impl<T> S<(T,)> {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Regression test for issue #104240.
|
// Regression test for issue #104240.
|
||||||
type A = S<()>::P;
|
let _: S<()>::P = ();
|
||||||
let _: A = ();
|
|
||||||
|
|
||||||
// Regression test for issue #107468.
|
// Regression test for issue #107468.
|
||||||
let _: S<(i32,)>::Un = 0i32;
|
let _: S<(i32,)>::Un = 0i32;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// check-pass
|
// FIXME(inherent_associated_types): This should be `check-pass`
|
||||||
|
// known-bug: #108491
|
||||||
// compile-flags: --crate-type=lib
|
// compile-flags: --crate-type=lib
|
||||||
|
|
||||||
#![feature(inherent_associated_types)]
|
#![feature(inherent_associated_types)]
|
||||||
|
@ -17,7 +18,6 @@
|
||||||
|
|
||||||
pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||||
|
|
||||||
|
|
||||||
pub struct Source<T>(T);
|
pub struct Source<T>(T);
|
||||||
pub trait Bound {}
|
pub trait Bound {}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
error[E0391]: cycle detected when expanding type alias `Alias`
|
||||||
|
--> $DIR/type-alias-bounds-are-enforced.rs:19:1
|
||||||
|
|
|
||||||
|
LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires computing the variances of `Source`...
|
||||||
|
--> $DIR/type-alias-bounds-are-enforced.rs:21:1
|
||||||
|
|
|
||||||
|
LL | pub struct Source<T>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which requires computing the variances for items in this crate...
|
||||||
|
= note: ...which again requires expanding type alias `Alias`, completing the cycle
|
||||||
|
note: cycle used when collecting item types in top-level module
|
||||||
|
--> $DIR/type-alias-bounds-are-enforced.rs:5:1
|
||||||
|
|
|
||||||
|
LL | / #![feature(inherent_associated_types)]
|
||||||
|
LL | | #![allow(incomplete_features)]
|
||||||
|
LL | |
|
||||||
|
LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*).
|
||||||
|
... |
|
||||||
|
LL | | pub type Assoc = ();
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||||
|
|
||||||
|
error[E0391]: cycle detected when expanding type alias `Alias`
|
||||||
|
--> $DIR/type-alias-bounds-are-enforced.rs:19:1
|
||||||
|
|
|
||||||
|
LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: ...which requires computing the variances of `Source`...
|
||||||
|
--> $DIR/type-alias-bounds-are-enforced.rs:21:1
|
||||||
|
|
|
||||||
|
LL | pub struct Source<T>(T);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which requires computing the variances for items in this crate...
|
||||||
|
= note: ...which again requires expanding type alias `Alias`, completing the cycle
|
||||||
|
note: cycle used when collecting item types in top-level module
|
||||||
|
--> $DIR/type-alias-bounds-are-enforced.rs:5:1
|
||||||
|
|
|
||||||
|
LL | / #![feature(inherent_associated_types)]
|
||||||
|
LL | | #![allow(incomplete_features)]
|
||||||
|
LL | |
|
||||||
|
LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*).
|
||||||
|
... |
|
||||||
|
LL | | pub type Assoc = ();
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0391`.
|
38
tests/ui/lazy-type-alias/variance.rs
Normal file
38
tests/ui/lazy-type-alias/variance.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// This is a regression test for issue #114221.
|
||||||
|
// Check that we compute variances for lazy type aliases.
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(lazy_type_alias)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// [+] `A` is covariant over `'a`.
|
||||||
|
struct A<'a>(Co<'a>);
|
||||||
|
|
||||||
|
// [+] `Co` is covariant over `'a`.
|
||||||
|
type Co<'a> = &'a ();
|
||||||
|
|
||||||
|
fn co<'a>(x: A<'static>) {
|
||||||
|
let _: A<'a> = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [-] `B` is contravariant over `'a`.
|
||||||
|
struct B<'a>(Contra<'a>);
|
||||||
|
|
||||||
|
// [-] `Contra` is contravariant over `'a`.
|
||||||
|
type Contra<'a> = fn(&'a ());
|
||||||
|
|
||||||
|
fn contra<'a>(x: B<'a>) {
|
||||||
|
let _: B<'static> = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct C<T, U>(CoContra<T, U>);
|
||||||
|
|
||||||
|
// [+, -] `CoContra` is covariant over `T` and contravariant over `U`.
|
||||||
|
type CoContra<T, U> = Option<(T, fn(U))>;
|
||||||
|
|
||||||
|
fn co_contra<'a>(x: C<&'static (), &'a ()>) -> C<&'a (), &'static ()> {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue