Permit recursive weak type aliases
This commit is contained in:
parent
7659abc63d
commit
5d850e0f50
@ -910,19 +910,24 @@ fn ast_path_to_ty(
|
|||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let args = self.ast_path_args_for_ty(span, did, item_segment);
|
let args = self.ast_path_args_for_ty(span, did, item_segment);
|
||||||
let ty = tcx.at(span).type_of(did);
|
|
||||||
|
|
||||||
if let DefKind::TyAlias { lazy } = tcx.def_kind(did)
|
if let DefKind::TyAlias { lazy: true } = tcx.def_kind(did) {
|
||||||
&& (lazy || ty.skip_binder().has_opaque_types())
|
// Type aliases defined in crates that have the
|
||||||
{
|
|
||||||
// Type aliases referring to types that contain opaque types (but aren't just directly
|
|
||||||
// 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
|
// feature `lazy_type_alias` enabled get encoded as a type alias that normalization will
|
||||||
// then actually instantiate the where bounds of.
|
// then actually instantiate the where bounds of.
|
||||||
let alias_ty = tcx.mk_alias_ty(did, args);
|
let alias_ty = tcx.mk_alias_ty(did, args);
|
||||||
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
||||||
} else {
|
} else {
|
||||||
ty.instantiate(tcx, args)
|
let ty = tcx.at(span).type_of(did);
|
||||||
|
if 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
|
||||||
|
// then actually instantiate the where bounds of.
|
||||||
|
let alias_ty = tcx.mk_alias_ty(did, args);
|
||||||
|
Ty::new_alias(tcx, ty::Weak, alias_ty)
|
||||||
|
} else {
|
||||||
|
ty.instantiate(tcx, args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,4 +40,5 @@ trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a
|
|||||||
.label = expected value here
|
.label = expected value here
|
||||||
.note = eg `#[rustc_on_unimplemented(message="foo")]`
|
.note = eg `#[rustc_on_unimplemented(message="foo")]`
|
||||||
|
|
||||||
|
trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||||
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
|
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
|
||||||
|
@ -659,6 +659,18 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|||||||
normalized_ty
|
normalized_ty
|
||||||
}
|
}
|
||||||
ty::Weak => {
|
ty::Weak => {
|
||||||
|
let recursion_limit = self.interner().recursion_limit();
|
||||||
|
if !recursion_limit.value_within_limit(self.depth) {
|
||||||
|
self.selcx.infcx.err_ctxt().report_overflow_error(
|
||||||
|
&ty,
|
||||||
|
self.cause.span,
|
||||||
|
false,
|
||||||
|
|diag| {
|
||||||
|
diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let infcx = self.selcx.infcx;
|
let infcx = self.selcx.infcx;
|
||||||
self.obligations.extend(
|
self.obligations.extend(
|
||||||
infcx.tcx.predicates_of(data.def_id).instantiate_own(infcx.tcx, data.args).map(
|
infcx.tcx.predicates_of(data.def_id).instantiate_own(infcx.tcx, data.args).map(
|
||||||
@ -678,7 +690,14 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
infcx.tcx.type_of(data.def_id).instantiate(infcx.tcx, data.args).fold_with(self)
|
self.depth += 1;
|
||||||
|
let res = infcx
|
||||||
|
.tcx
|
||||||
|
.type_of(data.def_id)
|
||||||
|
.instantiate(infcx.tcx, data.args)
|
||||||
|
.fold_with(self);
|
||||||
|
self.depth -= 1;
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Inherent if !data.has_escaping_bound_vars() => {
|
ty::Inherent if !data.has_escaping_bound_vars() => {
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
error[E0275]: overflow evaluating the requirement `X2`
|
||||||
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:6:11
|
||||||
|
|
|
||||||
|
LL | type X1 = X2;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `X3`
|
||||||
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
|
||||||
|
|
|
||||||
|
LL | type X2 = X3;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `X1`
|
||||||
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:11:11
|
||||||
|
|
|
||||||
|
LL | type X3 = X1;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0275`.
|
@ -1,16 +1,16 @@
|
|||||||
error[E0391]: cycle detected when expanding type alias `X1`
|
error[E0391]: cycle detected when expanding type alias `X1`
|
||||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:1:11
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:6:11
|
||||||
|
|
|
|
||||||
LL | type X1 = X2;
|
LL | type X1 = X2;
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
note: ...which requires expanding type alias `X2`...
|
note: ...which requires expanding type alias `X2`...
|
||||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:3:11
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
|
||||||
|
|
|
|
||||||
LL | type X2 = X3;
|
LL | type X2 = X3;
|
||||||
| ^^
|
| ^^
|
||||||
note: ...which requires expanding type alias `X3`...
|
note: ...which requires expanding type alias `X3`...
|
||||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:4:11
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:11:11
|
||||||
|
|
|
|
||||||
LL | type X3 = X1;
|
LL | type X3 = X1;
|
||||||
| ^^
|
| ^^
|
||||||
@ -19,12 +19,13 @@ LL | type X3 = X1;
|
|||||||
= help: consider using a struct, enum, or union instead to break the cycle
|
= help: consider using a struct, enum, or union instead to break the cycle
|
||||||
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
|
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
|
||||||
note: cycle used when collecting item types in top-level module
|
note: cycle used when collecting item types in top-level module
|
||||||
--> $DIR/infinite-type-alias-mutual-recursion.rs:1:1
|
--> $DIR/infinite-type-alias-mutual-recursion.rs:3:1
|
||||||
|
|
|
|
||||||
LL | / type X1 = X2;
|
LL | / #![cfg_attr(feature, feature(lazy_type_alias))]
|
||||||
|
LL | | #![allow(incomplete_features)]
|
||||||
LL | |
|
LL | |
|
||||||
LL | | type X2 = X3;
|
LL | | type X1 = X2;
|
||||||
LL | | type X3 = X1;
|
... |
|
||||||
LL | |
|
LL | |
|
||||||
LL | | fn main() {}
|
LL | | fn main() {}
|
||||||
| |____________^
|
| |____________^
|
@ -1,6 +1,14 @@
|
|||||||
|
// revisions: feature gated
|
||||||
|
|
||||||
|
#![cfg_attr(feature, feature(lazy_type_alias))]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
type X1 = X2;
|
type X1 = X2;
|
||||||
//~^ ERROR cycle detected when expanding type alias `X1`
|
//[gated]~^ ERROR cycle detected when expanding type alias `X1`
|
||||||
|
//[feature]~^^ ERROR: overflow evaluating the requirement `X2`
|
||||||
type X2 = X3;
|
type X2 = X3;
|
||||||
|
//[feature]~^ ERROR: overflow evaluating the requirement `X3`
|
||||||
type X3 = X1;
|
type X3 = X1;
|
||||||
|
//[feature]~^ ERROR: overflow evaluating the requirement `X1`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
11
tests/ui/infinite/infinite-vec-type-recursion.feature.stderr
Normal file
11
tests/ui/infinite/infinite-vec-type-recursion.feature.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error[E0275]: overflow evaluating the requirement `X`
|
||||||
|
--> $DIR/infinite-vec-type-recursion.rs:6:10
|
||||||
|
|
|
||||||
|
LL | type X = Vec<X>;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0275`.
|
@ -1,5 +1,5 @@
|
|||||||
error[E0391]: cycle detected when expanding type alias `X`
|
error[E0391]: cycle detected when expanding type alias `X`
|
||||||
--> $DIR/infinite-vec-type-recursion.rs:1:14
|
--> $DIR/infinite-vec-type-recursion.rs:6:14
|
||||||
|
|
|
|
||||||
LL | type X = Vec<X>;
|
LL | type X = Vec<X>;
|
||||||
| ^
|
| ^
|
||||||
@ -9,11 +9,14 @@ LL | type X = Vec<X>;
|
|||||||
= help: consider using a struct, enum, or union instead to break the cycle
|
= help: consider using a struct, enum, or union instead to break the cycle
|
||||||
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
|
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
|
||||||
note: cycle used when collecting item types in top-level module
|
note: cycle used when collecting item types in top-level module
|
||||||
--> $DIR/infinite-vec-type-recursion.rs:1:1
|
--> $DIR/infinite-vec-type-recursion.rs:3:1
|
||||||
|
|
|
|
||||||
LL | / type X = Vec<X>;
|
LL | / #![cfg_attr(feature, feature(lazy_type_alias))]
|
||||||
LL | |
|
LL | | #![allow(incomplete_features)]
|
||||||
LL | |
|
LL | |
|
||||||
|
LL | | type X = Vec<X>;
|
||||||
|
... |
|
||||||
|
LL | | #[rustfmt::skip]
|
||||||
LL | | fn main() { let b: X = Vec::new(); }
|
LL | | fn main() { let b: X = Vec::new(); }
|
||||||
| |____________________________________^
|
| |____________________________________^
|
||||||
= 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
|
= 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
|
@ -1,4 +1,11 @@
|
|||||||
type X = Vec<X>;
|
// revisions: feature gated
|
||||||
//~^ ERROR cycle detected
|
|
||||||
|
|
||||||
|
#![cfg_attr(feature, feature(lazy_type_alias))]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
type X = Vec<X>;
|
||||||
|
//[gated]~^ ERROR cycle detected
|
||||||
|
//[feature]~^^ ERROR: overflow evaluating the requirement `X`
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
fn main() { let b: X = Vec::new(); }
|
fn main() { let b: X = Vec::new(); }
|
||||||
|
Loading…
Reference in New Issue
Block a user