Use a query rather than recomputing the tail repeatedly
This commit is contained in:
parent
ccdfd310be
commit
830aeb6102
13 changed files with 234 additions and 90 deletions
|
@ -937,27 +937,7 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
|
|
||||||
let trait_def = tcx.trait_def(trait_ref.def_id);
|
let trait_def = tcx.trait_def(trait_ref.def_id);
|
||||||
|
|
||||||
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
|
let self_is_guaranteed_unsize_self = tcx.impl_self_is_guaranteed_unsized(impl_id);
|
||||||
|
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
|
||||||
let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id);
|
|
||||||
let param_env = tcx.param_env(impl_id);
|
|
||||||
|
|
||||||
let self_is_guaranteed_unsized = tcx
|
|
||||||
.struct_tail_raw(
|
|
||||||
trait_ref.self_ty(),
|
|
||||||
|ty| {
|
|
||||||
ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
|
|
||||||
Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
tcx.def_span(impl_id),
|
|
||||||
"struct tail should be computable",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|| (),
|
|
||||||
)
|
|
||||||
.is_guaranteed_unsized_raw();
|
|
||||||
|
|
||||||
for &impl_item in impl_item_refs {
|
for &impl_item in impl_item_refs {
|
||||||
let ty_impl_item = tcx.associated_item(impl_item);
|
let ty_impl_item = tcx.associated_item(impl_item);
|
||||||
|
@ -988,7 +968,7 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self_is_guaranteed_unsized && tcx.generics_require_sized_self(ty_trait_item.def_id) {
|
if self_is_guaranteed_unsize_self && tcx.generics_require_sized_self(ty_trait_item.def_id) {
|
||||||
tcx.emit_node_span_lint(
|
tcx.emit_node_span_lint(
|
||||||
rustc_lint_defs::builtin::DEAD_CODE,
|
rustc_lint_defs::builtin::DEAD_CODE,
|
||||||
tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()),
|
tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()),
|
||||||
|
@ -1023,7 +1003,7 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
if !is_implemented
|
if !is_implemented
|
||||||
&& tcx.defaultness(impl_id).is_final()
|
&& tcx.defaultness(impl_id).is_final()
|
||||||
// unsized types don't need to implement methods that have `Self: Sized` bounds.
|
// unsized types don't need to implement methods that have `Self: Sized` bounds.
|
||||||
&& !(self_is_guaranteed_unsized && tcx.generics_require_sized_self(trait_item_id))
|
&& !(self_is_guaranteed_unsize_self && tcx.generics_require_sized_self(trait_item_id))
|
||||||
{
|
{
|
||||||
missing_items.push(tcx.associated_item(trait_item_id));
|
missing_items.push(tcx.associated_item(trait_item_id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1026,6 +1026,13 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due
|
||||||
|
/// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct
|
||||||
|
/// whose tail is one of those types.
|
||||||
|
query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool {
|
||||||
|
desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Maps a `DefId` of a type to a list of its inherent impls.
|
/// Maps a `DefId` of a type to a list of its inherent impls.
|
||||||
/// Contains implementations of methods that are inherent to a type.
|
/// Contains implementations of methods that are inherent to a type.
|
||||||
/// Methods in these implementations don't need to be exported.
|
/// Methods in these implementations don't need to be exported.
|
||||||
|
|
|
@ -437,6 +437,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool {
|
||||||
|
self.impl_self_is_guaranteed_unsized(impl_def_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn has_target_features(self, def_id: DefId) -> bool {
|
fn has_target_features(self, def_id: DefId) -> bool {
|
||||||
!self.codegen_fn_attrs(def_id).target_features.is_empty()
|
!self.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2029,43 +2029,6 @@ impl<'tcx> Ty<'tcx> {
|
||||||
pub fn is_known_rigid(self) -> bool {
|
pub fn is_known_rigid(self) -> bool {
|
||||||
self.kind().is_known_rigid()
|
self.kind().is_known_rigid()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the type is guaranteed to be one of the three built-in unsized types:
|
|
||||||
/// `dyn Trait`/`[T]`/`str`. This function is *raw* because it does not compute the struct
|
|
||||||
/// tail of the type, so you are responsible for doing that yourself.
|
|
||||||
// NOTE: Keep this in sync with `rustc_type_ir`'s copy.
|
|
||||||
pub fn is_guaranteed_unsized_raw(self) -> bool {
|
|
||||||
match self.kind() {
|
|
||||||
Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true,
|
|
||||||
Bool
|
|
||||||
| Char
|
|
||||||
| Int(_)
|
|
||||||
| Uint(_)
|
|
||||||
| Float(_)
|
|
||||||
| Adt(_, _)
|
|
||||||
| Foreign(_)
|
|
||||||
| Array(_, _)
|
|
||||||
| Pat(_, _)
|
|
||||||
| RawPtr(_, _)
|
|
||||||
| Ref(_, _, _)
|
|
||||||
| FnDef(_, _)
|
|
||||||
| FnPtr(_, _)
|
|
||||||
| UnsafeBinder(_)
|
|
||||||
| Closure(_, _)
|
|
||||||
| CoroutineClosure(_, _)
|
|
||||||
| Coroutine(_, _)
|
|
||||||
| CoroutineWitness(_, _)
|
|
||||||
| Never
|
|
||||||
| Tuple(_)
|
|
||||||
| Alias(_, _)
|
|
||||||
| Param(_)
|
|
||||||
| Bound(_, _)
|
|
||||||
| Placeholder(_)
|
|
||||||
| Infer(_)
|
|
||||||
| Error(_)
|
|
||||||
| Dynamic(_, _, ty::DynStar) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
|
impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
|
||||||
|
|
|
@ -237,7 +237,7 @@ where
|
||||||
// has a trivially false `Sized` predicate). If it's the latter, we cannot
|
// has a trivially false `Sized` predicate). If it's the latter, we cannot
|
||||||
// delay a bug because we can have trivially false where clauses, so we
|
// delay a bug because we can have trivially false where clauses, so we
|
||||||
// treat it as rigid.
|
// treat it as rigid.
|
||||||
if goal_trait_ref.self_ty().is_guaranteed_unsized_raw() {
|
if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
|
||||||
ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
|
ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
|
||||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2007,21 +2007,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||||
"confirm_impl_candidate: no associated type {:?} for {:?}",
|
"confirm_impl_candidate: no associated type {:?} for {:?}",
|
||||||
assoc_ty.item.name, obligation.predicate
|
assoc_ty.item.name, obligation.predicate
|
||||||
);
|
);
|
||||||
let tail = selcx.tcx().struct_tail_raw(
|
if tcx.impl_self_is_guaranteed_unsized(impl_def_id) {
|
||||||
tcx.type_of(impl_def_id).instantiate(tcx, args),
|
|
||||||
|ty| {
|
|
||||||
normalize_with_depth_to(
|
|
||||||
selcx,
|
|
||||||
obligation.param_env,
|
|
||||||
obligation.cause.clone(),
|
|
||||||
obligation.recursion_depth + 1,
|
|
||||||
ty,
|
|
||||||
&mut nested,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|| {},
|
|
||||||
);
|
|
||||||
if tail.is_guaranteed_unsized_raw() {
|
|
||||||
// We treat this projection as rigid here, which is represented via
|
// We treat this projection as rigid here, which is represented via
|
||||||
// `Projected::NoProgress`. This will ensure that the projection is
|
// `Projected::NoProgress`. This will ensure that the projection is
|
||||||
// checked for well-formedness, and it's either satisfied by a trivial
|
// checked for well-formedness, and it's either satisfied by a trivial
|
||||||
|
|
|
@ -3,6 +3,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_index::bit_set::DenseBitSet;
|
use rustc_index::bit_set::DenseBitSet;
|
||||||
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
|
@ -312,6 +313,61 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> DenseBitSe
|
||||||
unsizing_params
|
unsizing_params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) -> bool {
|
||||||
|
debug_assert_eq!(tcx.def_kind(impl_def_id), DefKind::Impl { of_trait: true });
|
||||||
|
|
||||||
|
let infcx = tcx.infer_ctxt().ignoring_regions().build(ty::TypingMode::non_body_analysis());
|
||||||
|
|
||||||
|
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
|
||||||
|
let cause = traits::ObligationCause::dummy();
|
||||||
|
let param_env = tcx.param_env(impl_def_id);
|
||||||
|
|
||||||
|
let tail = tcx.struct_tail_raw(
|
||||||
|
tcx.type_of(impl_def_id).instantiate_identity(),
|
||||||
|
|ty| {
|
||||||
|
ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
|
||||||
|
Ty::new_error_with_message(
|
||||||
|
tcx,
|
||||||
|
tcx.def_span(impl_def_id),
|
||||||
|
"struct tail should be computable",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|| (),
|
||||||
|
);
|
||||||
|
|
||||||
|
match tail.kind() {
|
||||||
|
ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true,
|
||||||
|
ty::Bool
|
||||||
|
| ty::Char
|
||||||
|
| ty::Int(_)
|
||||||
|
| ty::Uint(_)
|
||||||
|
| ty::Float(_)
|
||||||
|
| ty::Adt(_, _)
|
||||||
|
| ty::Foreign(_)
|
||||||
|
| ty::Array(_, _)
|
||||||
|
| ty::Pat(_, _)
|
||||||
|
| ty::RawPtr(_, _)
|
||||||
|
| ty::Ref(_, _, _)
|
||||||
|
| ty::FnDef(_, _)
|
||||||
|
| ty::FnPtr(_, _)
|
||||||
|
| ty::UnsafeBinder(_)
|
||||||
|
| ty::Closure(_, _)
|
||||||
|
| ty::CoroutineClosure(_, _)
|
||||||
|
| ty::Coroutine(_, _)
|
||||||
|
| ty::CoroutineWitness(_, _)
|
||||||
|
| ty::Never
|
||||||
|
| ty::Tuple(_)
|
||||||
|
| ty::Alias(_, _)
|
||||||
|
| ty::Param(_)
|
||||||
|
| ty::Bound(_, _)
|
||||||
|
| ty::Placeholder(_)
|
||||||
|
| ty::Infer(_)
|
||||||
|
| ty::Error(_)
|
||||||
|
| ty::Dynamic(_, _, ty::DynStar) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers {
|
*providers = Providers {
|
||||||
asyncness,
|
asyncness,
|
||||||
|
@ -320,6 +376,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
param_env_normalized_for_post_analysis,
|
param_env_normalized_for_post_analysis,
|
||||||
defaultness,
|
defaultness,
|
||||||
unsizing_params_for_adt,
|
unsizing_params_for_adt,
|
||||||
|
impl_self_is_guaranteed_unsized,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,6 +255,8 @@ pub trait Interner:
|
||||||
def_id: Self::DefId,
|
def_id: Self::DefId,
|
||||||
) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
|
) -> ty::EarlyBinder<Self, impl IntoIterator<Item = ty::Binder<Self, ty::TraitRef<Self>>>>;
|
||||||
|
|
||||||
|
fn impl_self_is_guaranteed_unsized(self, def_id: Self::DefId) -> bool;
|
||||||
|
|
||||||
fn has_target_features(self, def_id: Self::DefId) -> bool;
|
fn has_target_features(self, def_id: Self::DefId) -> bool;
|
||||||
|
|
||||||
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
|
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
|
||||||
|
|
|
@ -2,7 +2,7 @@ trait Filter {
|
||||||
type ToMatch;
|
type ToMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Filter for T //~ ERROR overflow evaluating the requirement
|
impl<T> Filter for T //~ ERROR cycle detected when
|
||||||
where
|
where
|
||||||
T: Fn(Self::ToMatch),
|
T: Fn(Self::ToMatch),
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0275]: overflow evaluating the requirement `<T as Filter>::ToMatch == <T as Filter>::ToMatch`
|
error[E0391]: cycle detected when computing normalized predicates of `<impl at $DIR/impl-wf-cycle-4.rs:5:1: 7:26>`
|
||||||
--> $DIR/impl-wf-cycle-4.rs:5:1
|
--> $DIR/impl-wf-cycle-4.rs:5:1
|
||||||
|
|
|
|
||||||
LL | / impl<T> Filter for T
|
LL | / impl<T> Filter for T
|
||||||
|
@ -6,20 +6,23 @@ LL | | where
|
||||||
LL | | T: Fn(Self::ToMatch),
|
LL | | T: Fn(Self::ToMatch),
|
||||||
| |_________________________^
|
| |_________________________^
|
||||||
|
|
|
|
||||||
note: required for `T` to implement `Filter`
|
note: ...which requires computing whether `<impl at $DIR/impl-wf-cycle-4.rs:5:1: 7:26>` has a guaranteed unsized self type...
|
||||||
--> $DIR/impl-wf-cycle-4.rs:5:9
|
--> $DIR/impl-wf-cycle-4.rs:5:1
|
||||||
|
|
|
|
||||||
LL | impl<T> Filter for T
|
LL | / impl<T> Filter for T
|
||||||
| ^^^^^^ ^
|
LL | | where
|
||||||
LL | where
|
LL | | T: Fn(Self::ToMatch),
|
||||||
LL | T: Fn(Self::ToMatch),
|
| |_________________________^
|
||||||
| ----------------- unsatisfied trait bound introduced here
|
= note: ...which again requires computing normalized predicates of `<impl at $DIR/impl-wf-cycle-4.rs:5:1: 7:26>`, completing the cycle
|
||||||
note: associated types for the current `impl` cannot be restricted in `where` clauses
|
note: cycle used when checking that `<impl at $DIR/impl-wf-cycle-4.rs:5:1: 7:26>` is well-formed
|
||||||
--> $DIR/impl-wf-cycle-4.rs:7:11
|
--> $DIR/impl-wf-cycle-4.rs:5:1
|
||||||
|
|
|
|
||||||
LL | T: Fn(Self::ToMatch),
|
LL | / impl<T> Filter for T
|
||||||
| ^^^^^^^^^^^^^
|
LL | | where
|
||||||
|
LL | | T: Fn(Self::ToMatch),
|
||||||
|
| |_________________________^
|
||||||
|
= 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 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
For more information about this error, try `rustc --explain E0391`.
|
||||||
|
|
54
tests/ui/traits/trivial-unsized-projection-2.bad.stderr
Normal file
54
tests/ui/traits/trivial-unsized-projection-2.bad.stderr
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:22:12
|
||||||
|
|
|
||||||
|
LL | const FOO: <Tail as Bad>::Assert = todo!();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: within `Tail`, the trait `Sized` is not implemented for `[()]`
|
||||||
|
note: required because it appears within the type `Tail`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:17:8
|
||||||
|
|
|
||||||
|
LL | struct Tail([()]);
|
||||||
|
| ^^^^
|
||||||
|
note: required by a bound in `Bad::Assert`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:14:15
|
||||||
|
|
|
||||||
|
LL | type Assert
|
||||||
|
| ------ required by a bound in this associated type
|
||||||
|
LL | where
|
||||||
|
LL | Self: Sized;
|
||||||
|
| ^^^^^ required by this bound in `Bad::Assert`
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | type Assert: ?Sized
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:22:12
|
||||||
|
|
|
||||||
|
LL | const FOO: <Tail as Bad>::Assert = todo!();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: within `Tail`, the trait `Sized` is not implemented for `[()]`
|
||||||
|
note: required because it appears within the type `Tail`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:17:8
|
||||||
|
|
|
||||||
|
LL | struct Tail([()]);
|
||||||
|
| ^^^^
|
||||||
|
note: required by a bound in `Bad::Assert`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:14:15
|
||||||
|
|
|
||||||
|
LL | type Assert
|
||||||
|
| ------ required by a bound in this associated type
|
||||||
|
LL | where
|
||||||
|
LL | Self: Sized;
|
||||||
|
| ^^^^^ required by this bound in `Bad::Assert`
|
||||||
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | type Assert: ?Sized
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
54
tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr
Normal file
54
tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:22:12
|
||||||
|
|
|
||||||
|
LL | const FOO: <Tail as Bad>::Assert = todo!();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: within `Tail`, the trait `Sized` is not implemented for `[()]`
|
||||||
|
note: required because it appears within the type `Tail`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:17:8
|
||||||
|
|
|
||||||
|
LL | struct Tail([()]);
|
||||||
|
| ^^^^
|
||||||
|
note: required by a bound in `Bad::Assert`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:14:15
|
||||||
|
|
|
||||||
|
LL | type Assert
|
||||||
|
| ------ required by a bound in this associated type
|
||||||
|
LL | where
|
||||||
|
LL | Self: Sized;
|
||||||
|
| ^^^^^ required by this bound in `Bad::Assert`
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | type Assert: ?Sized
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:22:12
|
||||||
|
|
|
||||||
|
LL | const FOO: <Tail as Bad>::Assert = todo!();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: within `Tail`, the trait `Sized` is not implemented for `[()]`
|
||||||
|
note: required because it appears within the type `Tail`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:17:8
|
||||||
|
|
|
||||||
|
LL | struct Tail([()]);
|
||||||
|
| ^^^^
|
||||||
|
note: required by a bound in `Bad::Assert`
|
||||||
|
--> $DIR/trivial-unsized-projection-2.rs:14:15
|
||||||
|
|
|
||||||
|
LL | type Assert
|
||||||
|
| ------ required by a bound in this associated type
|
||||||
|
LL | where
|
||||||
|
LL | Self: Sized;
|
||||||
|
| ^^^^^ required by this bound in `Bad::Assert`
|
||||||
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | type Assert: ?Sized
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
34
tests/ui/traits/trivial-unsized-projection-2.rs
Normal file
34
tests/ui/traits/trivial-unsized-projection-2.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//@ revisions: good bad good_new bad_new
|
||||||
|
//@[good_new] compile-flags: -Znext-solver
|
||||||
|
//@[bad_new] compile-flags: -Znext-solver
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[good] check-pass
|
||||||
|
//@[good_new] check-pass
|
||||||
|
|
||||||
|
#![feature(trivial_bounds)]
|
||||||
|
#![allow(trivial_bounds)]
|
||||||
|
|
||||||
|
trait Bad {
|
||||||
|
type Assert
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Tail([()]);
|
||||||
|
|
||||||
|
impl Bad for Tail {}
|
||||||
|
|
||||||
|
#[cfg(any(bad, bad_new))]
|
||||||
|
const FOO: <Tail as Bad>::Assert = todo!();
|
||||||
|
//[bad]~^ ERROR the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
//[bad]~| ERROR the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
//[bad_new]~^^^ ERROR the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
//[bad_new]~| ERROR the size for values of type `[()]` cannot be known at compilation time
|
||||||
|
|
||||||
|
#[cfg(any(good, good_new))]
|
||||||
|
// Well-formed in trivially false param-env
|
||||||
|
fn foo() where Tail: Sized {
|
||||||
|
let _: <Tail as Bad>::Assert;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue