mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #150843 - fmease:dyn-ace, r=BoxyUwU
mGCA: Make trait object types with type-level associated consts dyn compatible Under feature `min_generic_const_args` (mGCA) (rust-lang/rust#132980), render traits with non-parametrized type-level associated constants (i.e., `#[type_const]` ones) dyn compatible but force the user to specify all type-level associated consts in the trait object type via bindings (either directly, via supertrait bounds and/or behind trait aliases) just like associated types, their sibling. Fixes rust-lang/rust#130300 (feature request). Fixes rust-lang/rust#136063 (bug). Fixes rust-lang/rust#137260 (bug). Fixes rust-lang/rust#137514 (bug). While I'm accounting for most illegal `Self` references via const projections & params, I'm intentionally ignoring RUST-123140 (and duplicates) in this PR which is to be tackled some other time. Additional context: Crate `rustc-demangle` had to be updated to fix v0 demangling. I've patched it in PR https://github.com/rust-lang/rustc-demangle/pull/87 which was was released in version 0.1.27 via PR https://github.com/rust-lang/rustc-demangle/pull/88.
This commit is contained in:
+2
-2
@@ -3356,9 +3356,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
|
||||
@@ -242,7 +242,7 @@ pub(crate) fn define_function<'tcx>(
|
||||
let generics = tcx.generics_of(enclosing_fn_def_id);
|
||||
let args = instance.args.truncate_to(tcx, generics);
|
||||
|
||||
type_names::push_generic_params(
|
||||
type_names::push_generic_args(
|
||||
tcx,
|
||||
tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), args),
|
||||
&mut name,
|
||||
|
||||
@@ -456,7 +456,7 @@ fn dbg_scope_fn(
|
||||
let generics = tcx.generics_of(enclosing_fn_def_id);
|
||||
let args = instance.args.truncate_to(tcx, generics);
|
||||
|
||||
type_names::push_generic_params(
|
||||
type_names::push_generic_args(
|
||||
tcx,
|
||||
tcx.normalize_erasing_regions(self.typing_env(), args),
|
||||
&mut name,
|
||||
|
||||
@@ -109,14 +109,14 @@ fn push_debuginfo_type_name<'tcx>(
|
||||
ty_and_layout,
|
||||
&|output, visited| {
|
||||
push_item_name(tcx, def.did(), true, output);
|
||||
push_generic_params_internal(tcx, args, output, visited);
|
||||
push_generic_args_internal(tcx, args, output, visited);
|
||||
},
|
||||
output,
|
||||
visited,
|
||||
);
|
||||
} else {
|
||||
push_item_name(tcx, def.did(), qualified, output);
|
||||
push_generic_params_internal(tcx, args, output, visited);
|
||||
push_generic_args_internal(tcx, args, output, visited);
|
||||
}
|
||||
}
|
||||
ty::Tuple(component_types) => {
|
||||
@@ -253,19 +253,18 @@ fn push_debuginfo_type_name<'tcx>(
|
||||
);
|
||||
push_item_name(tcx, principal.def_id, qualified, output);
|
||||
let principal_has_generic_params =
|
||||
push_generic_params_internal(tcx, principal.args, output, visited);
|
||||
push_generic_args_internal(tcx, principal.args, output, visited);
|
||||
|
||||
let projection_bounds: SmallVec<[_; 4]> = trait_data
|
||||
.projection_bounds()
|
||||
.map(|bound| {
|
||||
let ExistentialProjection { def_id: item_def_id, term, .. } =
|
||||
tcx.instantiate_bound_regions_with_erased(bound);
|
||||
// FIXME(mgca): allow for consts here
|
||||
(item_def_id, term.expect_type())
|
||||
(item_def_id, term)
|
||||
})
|
||||
.collect();
|
||||
|
||||
if projection_bounds.len() != 0 {
|
||||
if !projection_bounds.is_empty() {
|
||||
if principal_has_generic_params {
|
||||
// push_generic_params_internal() above added a `>` but we actually
|
||||
// want to add more items to that list, so remove that again...
|
||||
@@ -279,17 +278,17 @@ fn push_debuginfo_type_name<'tcx>(
|
||||
output.push('<');
|
||||
}
|
||||
|
||||
for (item_def_id, ty) in projection_bounds {
|
||||
for (item_def_id, term) in projection_bounds {
|
||||
if cpp_like_debuginfo {
|
||||
output.push_str("assoc$<");
|
||||
push_item_name(tcx, item_def_id, false, output);
|
||||
push_arg_separator(cpp_like_debuginfo, output);
|
||||
push_debuginfo_type_name(tcx, ty, true, output, visited);
|
||||
push_debuginfo_term_name(tcx, term, true, output, visited);
|
||||
push_close_angle_bracket(cpp_like_debuginfo, output);
|
||||
} else {
|
||||
push_item_name(tcx, item_def_id, false, output);
|
||||
output.push('=');
|
||||
push_debuginfo_type_name(tcx, ty, true, output, visited);
|
||||
push_debuginfo_term_name(tcx, term, true, output, visited);
|
||||
}
|
||||
push_arg_separator(cpp_like_debuginfo, output);
|
||||
}
|
||||
@@ -533,7 +532,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
|
||||
tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
|
||||
push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name);
|
||||
visited.clear();
|
||||
push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);
|
||||
push_generic_args_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);
|
||||
} else {
|
||||
vtable_name.push('_');
|
||||
}
|
||||
@@ -631,7 +630,13 @@ fn push_unqualified_item_name(
|
||||
};
|
||||
}
|
||||
|
||||
fn push_generic_params_internal<'tcx>(
|
||||
pub fn push_generic_args<'tcx>(tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, output: &mut String) {
|
||||
let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name");
|
||||
let mut visited = FxHashSet::default();
|
||||
push_generic_args_internal(tcx, args, output, &mut visited);
|
||||
}
|
||||
|
||||
fn push_generic_args_internal<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
output: &mut String,
|
||||
@@ -646,14 +651,10 @@ fn push_generic_params_internal<'tcx>(
|
||||
|
||||
output.push('<');
|
||||
|
||||
for type_parameter in args {
|
||||
match type_parameter {
|
||||
GenericArgKind::Type(type_parameter) => {
|
||||
push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
|
||||
}
|
||||
GenericArgKind::Const(ct) => {
|
||||
push_const_param(tcx, ct, output);
|
||||
}
|
||||
for arg in args {
|
||||
match arg {
|
||||
GenericArgKind::Type(ty) => push_debuginfo_type_name(tcx, ty, true, output, visited),
|
||||
GenericArgKind::Const(ct) => push_debuginfo_const_name(tcx, ct, output),
|
||||
other => bug!("Unexpected non-erasable generic: {:?}", other),
|
||||
}
|
||||
|
||||
@@ -665,7 +666,20 @@ fn push_generic_params_internal<'tcx>(
|
||||
true
|
||||
}
|
||||
|
||||
fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut String) {
|
||||
fn push_debuginfo_term_name<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
term: ty::Term<'tcx>,
|
||||
qualified: bool,
|
||||
output: &mut String,
|
||||
visited: &mut FxHashSet<Ty<'tcx>>,
|
||||
) {
|
||||
match term.kind() {
|
||||
ty::TermKind::Ty(ty) => push_debuginfo_type_name(tcx, ty, qualified, output, visited),
|
||||
ty::TermKind::Const(ct) => push_debuginfo_const_name(tcx, ct, output),
|
||||
}
|
||||
}
|
||||
|
||||
fn push_debuginfo_const_name<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut String) {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Param(param) => {
|
||||
write!(output, "{}", param.name)
|
||||
@@ -715,16 +729,6 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn push_generic_params<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
output: &mut String,
|
||||
) {
|
||||
let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name");
|
||||
let mut visited = FxHashSet::default();
|
||||
push_generic_params_internal(tcx, args, output, &mut visited);
|
||||
}
|
||||
|
||||
fn push_closure_or_coroutine_name<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
@@ -767,7 +771,7 @@ fn push_closure_or_coroutine_name<'tcx>(
|
||||
// FIXME(async_closures): This is probably not going to be correct w.r.t.
|
||||
// multiple coroutine flavors. Maybe truncate to (parent + 1)?
|
||||
let args = args.truncate_to(tcx, generics);
|
||||
push_generic_params_internal(tcx, args, output, visited);
|
||||
push_generic_args_internal(tcx, args, output, visited);
|
||||
}
|
||||
|
||||
fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) {
|
||||
|
||||
@@ -165,6 +165,11 @@ hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
|
||||
hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice
|
||||
.label = parameter captured again here
|
||||
|
||||
hir_analysis_dyn_trait_assoc_item_binding_mentions_self =
|
||||
{$kind} binding in trait object type mentions `Self`
|
||||
.label = contains a mention of `Self`
|
||||
.binding_label = this binding mentions `Self`
|
||||
|
||||
hir_analysis_eii_with_generics =
|
||||
`{$impl_name}` cannot have generic parameters other than lifetimes
|
||||
.label = required by this attribute
|
||||
@@ -330,6 +335,31 @@ hir_analysis_manual_implementation =
|
||||
hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous
|
||||
.note = this method is `async` so it expects a future to be returned
|
||||
|
||||
hir_analysis_missing_generic_params =
|
||||
the {$descr} {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} {$parameters} must be explicitly specified
|
||||
.label = {$descr} {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} {$parameters} must be specified for this
|
||||
.suggestion = explicitly specify the {$descr} {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
}
|
||||
.no_suggestion_label = missing {$parameterCount ->
|
||||
[one] reference
|
||||
*[other] references
|
||||
} to {$parameters}
|
||||
.note = because the parameter {$parameterCount ->
|
||||
[one] default references
|
||||
*[other] defaults reference
|
||||
} `Self`, the {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} must be specified on the trait object type
|
||||
|
||||
hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
|
||||
.label = missing one of `{$missing_items_msg}` in implementation
|
||||
.note = required because of this annotation
|
||||
@@ -346,34 +376,6 @@ hir_analysis_missing_trait_item_unstable = not all trait items implemented, miss
|
||||
.some_note = use of unstable library feature `{$feature}`: {$reason}
|
||||
.none_note = use of unstable library feature `{$feature}`
|
||||
|
||||
hir_analysis_missing_type_params =
|
||||
the type {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} {$parameters} must be explicitly specified
|
||||
.label = type {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} {$parameters} must be specified for this
|
||||
.suggestion = set the type {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} to the desired {$parameterCount ->
|
||||
[one] type
|
||||
*[other] types
|
||||
}
|
||||
.no_suggestion_label = missing {$parameterCount ->
|
||||
[one] reference
|
||||
*[other] references
|
||||
} to {$parameters}
|
||||
.note = because the parameter {$parameterCount ->
|
||||
[one] default references
|
||||
*[other] defaults reference
|
||||
} `Self`, the {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} must be specified on the object type
|
||||
|
||||
hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}`
|
||||
|
||||
hir_analysis_not_supported_delegation = {$descr}
|
||||
@@ -481,9 +483,6 @@ hir_analysis_self_in_impl_self =
|
||||
`Self` is not valid in the self type of an impl block
|
||||
.note = replace `Self` with a different type
|
||||
|
||||
hir_analysis_self_in_type_alias = `Self` is not allowed in type aliases
|
||||
.label = `Self` is only available in impls, traits, and concrete type definitions
|
||||
|
||||
hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>`
|
||||
.label = `Self` type parameter is implicitly captured by this `impl Trait`
|
||||
.note = currently, all type parameters are required to be mentioned in the precise captures list
|
||||
|
||||
@@ -1960,7 +1960,7 @@ fn compare_generic_param_kinds<'tcx>(
|
||||
trait_item: ty::AssocItem,
|
||||
delay: bool,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
assert_eq!(impl_item.as_tag(), trait_item.as_tag());
|
||||
assert_eq!(impl_item.tag(), trait_item.tag());
|
||||
|
||||
let ty_const_params_of = |def_id| {
|
||||
tcx.generics_of(def_id).own_params.iter().filter(|param| {
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
|
||||
MultiSpan,
|
||||
MultiSpan, listify,
|
||||
};
|
||||
use rustc_hir::limit::Limit;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
@@ -400,35 +400,58 @@ pub(crate) struct UnconstrainedOpaqueType {
|
||||
pub what: &'static str,
|
||||
}
|
||||
|
||||
pub(crate) struct MissingTypeParams {
|
||||
pub(crate) struct MissingGenericParams {
|
||||
pub span: Span,
|
||||
pub def_span: Span,
|
||||
pub span_snippet: Option<String>,
|
||||
pub missing_type_params: Vec<Symbol>,
|
||||
pub missing_generic_params: Vec<(Symbol, ty::GenericParamDefKind)>,
|
||||
pub empty_generic_args: bool,
|
||||
}
|
||||
|
||||
// Manual implementation of `Diagnostic` to be able to call `span_to_snippet`.
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingTypeParams {
|
||||
// FIXME: This doesn't need to be a manual impl!
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams {
|
||||
#[track_caller]
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let mut err = Diag::new(dcx, level, fluent::hir_analysis_missing_type_params);
|
||||
let mut err = Diag::new(dcx, level, fluent::hir_analysis_missing_generic_params);
|
||||
err.span(self.span);
|
||||
err.code(E0393);
|
||||
err.arg("parameterCount", self.missing_type_params.len());
|
||||
err.arg(
|
||||
"parameters",
|
||||
self.missing_type_params
|
||||
.iter()
|
||||
.map(|n| format!("`{n}`"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
);
|
||||
|
||||
err.span_label(self.def_span, fluent::hir_analysis_label);
|
||||
|
||||
enum Descr {
|
||||
Generic,
|
||||
Type,
|
||||
Const,
|
||||
}
|
||||
|
||||
let mut descr = None;
|
||||
for (_, kind) in &self.missing_generic_params {
|
||||
descr = match (&descr, kind) {
|
||||
(None, ty::GenericParamDefKind::Type { .. }) => Some(Descr::Type),
|
||||
(None, ty::GenericParamDefKind::Const { .. }) => Some(Descr::Const),
|
||||
(Some(Descr::Type), ty::GenericParamDefKind::Const { .. })
|
||||
| (Some(Descr::Const), ty::GenericParamDefKind::Type { .. }) => {
|
||||
Some(Descr::Generic)
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
err.arg(
|
||||
"descr",
|
||||
match descr.unwrap() {
|
||||
Descr::Generic => "generic",
|
||||
Descr::Type => "type",
|
||||
Descr::Const => "const",
|
||||
},
|
||||
);
|
||||
err.arg("parameterCount", self.missing_generic_params.len());
|
||||
err.arg(
|
||||
"parameters",
|
||||
listify(&self.missing_generic_params, |(n, _)| format!("`{n}`")).unwrap(),
|
||||
);
|
||||
|
||||
let mut suggested = false;
|
||||
// Don't suggest setting the type params if there are some already: the order is
|
||||
// Don't suggest setting the generic params if there are some already: The order is
|
||||
// tricky to get right and the user will already know what the syntax is.
|
||||
if let Some(snippet) = self.span_snippet
|
||||
&& self.empty_generic_args
|
||||
@@ -438,16 +461,16 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
// we would have to preserve the right order. For now, as clearly the user is
|
||||
// aware of the syntax, we do nothing.
|
||||
} else {
|
||||
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
|
||||
// least we can clue them to the correct syntax `Iterator<Type>`.
|
||||
// The user wrote `Trait`, so we don't have a type we can suggest, but at
|
||||
// least we can clue them to the correct syntax `Trait</* Term */>`.
|
||||
err.span_suggestion_verbose(
|
||||
self.span.shrink_to_hi(),
|
||||
fluent::hir_analysis_suggestion,
|
||||
format!(
|
||||
"<{}>",
|
||||
self.missing_type_params
|
||||
self.missing_generic_params
|
||||
.iter()
|
||||
.map(|n| n.to_string())
|
||||
.map(|(n, _)| format!("/* {n} */"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
@@ -1609,11 +1632,14 @@ pub(crate) enum SupertraitItemShadowee {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_self_in_type_alias, code = E0411)]
|
||||
pub(crate) struct SelfInTypeAlias {
|
||||
#[diag(hir_analysis_dyn_trait_assoc_item_binding_mentions_self)]
|
||||
pub(crate) struct DynTraitAssocItemBindingMentionsSelf {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub kind: &'static str,
|
||||
#[label(hir_analysis_binding_label)]
|
||||
pub binding: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::HirTyLowerer;
|
||||
use crate::errors::SelfInTypeAlias;
|
||||
use crate::errors::DynTraitAssocItemBindingMentionsSelf;
|
||||
use crate::hir_ty_lowering::{
|
||||
GenericArgCountMismatch, ImpliedBoundsContext, OverlappingAsssocItemConstraints,
|
||||
PredicateFilter, RegionInferReason,
|
||||
@@ -56,8 +56,13 @@ pub(super) fn lower_trait_object_ty(
|
||||
}
|
||||
|
||||
let mut user_written_bounds = Vec::new();
|
||||
let mut potential_assoc_types = Vec::new();
|
||||
let mut potential_assoc_items = Vec::new();
|
||||
for poly_trait_ref in hir_bounds.iter() {
|
||||
// FIXME(mgca): We actually leak `trait_object_dummy_self` if the type of any assoc
|
||||
// const mentions `Self` (in "Self projections" which we intentionally
|
||||
// allow). That's because we query feed the instantiated type to `type_of`.
|
||||
// That's really bad, dummy self should never escape lowering! It leads us
|
||||
// to accept less code we'd like to support and can lead to ICEs later.
|
||||
let result = self.lower_poly_trait_ref(
|
||||
poly_trait_ref,
|
||||
dummy_self,
|
||||
@@ -66,7 +71,7 @@ pub(super) fn lower_trait_object_ty(
|
||||
OverlappingAsssocItemConstraints::Forbidden,
|
||||
);
|
||||
if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
|
||||
potential_assoc_types.extend(invalid_args);
|
||||
potential_assoc_items.extend(invalid_args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,31 +143,33 @@ pub(super) fn lower_trait_object_ty(
|
||||
}
|
||||
|
||||
// Map the projection bounds onto a key that makes it easy to remove redundant
|
||||
// bounds that are constrained by supertraits of the principal def id.
|
||||
// bounds that are constrained by supertraits of the principal trait.
|
||||
//
|
||||
// Also make sure we detect conflicting bounds from expanding a trait alias and
|
||||
// also specifying it manually, like:
|
||||
// ```
|
||||
// type Alias = Trait<Assoc = i32>;
|
||||
// let _: &dyn Alias<Assoc = u32> = /* ... */;
|
||||
// ```
|
||||
// Also make sure we detect conflicting bounds from expanding trait aliases.
|
||||
//
|
||||
// FIXME(#150936): Since the elaborated projection bounds also include the user-written ones
|
||||
// and we're separately rejecting duplicate+conflicting bindings for trait
|
||||
// object types when lowering assoc item bindings, there are basic cases
|
||||
// where we're emitting two distinct but very similar diagnostics.
|
||||
let mut projection_bounds = FxIndexMap::default();
|
||||
for (proj, proj_span) in elaborated_projection_bounds {
|
||||
let proj = proj.map_bound(|mut b| {
|
||||
if let Some(term_ty) = &b.term.as_type() {
|
||||
let references_self = term_ty.walk().any(|arg| arg == dummy_self.into());
|
||||
if references_self {
|
||||
// With trait alias and type alias combined, type resolver
|
||||
// may not be able to catch all illegal `Self` usages (issue 139082)
|
||||
let guar = self.dcx().emit_err(SelfInTypeAlias { span });
|
||||
b.term = replace_dummy_self_with_error(tcx, b.term, guar);
|
||||
}
|
||||
let item_def_id = proj.item_def_id();
|
||||
|
||||
let proj = proj.map_bound(|mut proj| {
|
||||
let references_self = proj.term.walk().any(|arg| arg == dummy_self.into());
|
||||
if references_self {
|
||||
let guar = self.dcx().emit_err(DynTraitAssocItemBindingMentionsSelf {
|
||||
span,
|
||||
kind: tcx.def_descr(item_def_id),
|
||||
binding: proj_span,
|
||||
});
|
||||
proj.term = replace_dummy_self_with_error(tcx, proj.term, guar);
|
||||
}
|
||||
b
|
||||
proj
|
||||
});
|
||||
|
||||
let key = (
|
||||
proj.skip_binder().projection_term.def_id,
|
||||
item_def_id,
|
||||
tcx.anonymize_bound_vars(
|
||||
proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
|
||||
),
|
||||
@@ -171,19 +178,17 @@ pub(super) fn lower_trait_object_ty(
|
||||
projection_bounds.insert(key, (proj, proj_span))
|
||||
&& tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
|
||||
{
|
||||
let item = tcx.item_name(proj.item_def_id());
|
||||
let kind = tcx.def_descr(item_def_id);
|
||||
let name = tcx.item_name(item_def_id);
|
||||
self.dcx()
|
||||
.struct_span_err(
|
||||
span,
|
||||
format!("conflicting associated type bounds for `{item}`"),
|
||||
)
|
||||
.struct_span_err(span, format!("conflicting {kind} bindings for `{name}`"))
|
||||
.with_span_label(
|
||||
old_proj_span,
|
||||
format!("`{item}` is specified to be `{}` here", old_proj.term()),
|
||||
format!("`{name}` is specified to be `{}` here", old_proj.term()),
|
||||
)
|
||||
.with_span_label(
|
||||
proj_span,
|
||||
format!("`{item}` is specified to be `{}` here", proj.term()),
|
||||
format!("`{name}` is specified to be `{}` here", proj.term()),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
@@ -191,13 +196,12 @@ pub(super) fn lower_trait_object_ty(
|
||||
|
||||
let principal_trait = regular_traits.into_iter().next();
|
||||
|
||||
// A stable ordering of associated types from the principal trait and all its
|
||||
// supertraits. We use this to ensure that different substitutions of a trait
|
||||
// don't result in `dyn Trait` types with different projections lists, which
|
||||
// can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
|
||||
// We achieve a stable ordering by walking over the unsubstituted principal
|
||||
// trait ref.
|
||||
let mut ordered_associated_types = vec![];
|
||||
// A stable ordering of associated types & consts from the principal trait and all its
|
||||
// supertraits. We use this to ensure that different substitutions of a trait don't
|
||||
// result in `dyn Trait` types with different projections lists, which can be unsound:
|
||||
// <https://github.com/rust-lang/rust/pull/136458>.
|
||||
// We achieve a stable ordering by walking over the unsubstituted principal trait ref.
|
||||
let mut ordered_associated_items = vec![];
|
||||
|
||||
if let Some((principal_trait, ref spans)) = principal_trait {
|
||||
let principal_trait = principal_trait.map_bound(|trait_pred| {
|
||||
@@ -223,12 +227,12 @@ pub(super) fn lower_trait_object_ty(
|
||||
// FIXME(negative_bounds): Handle this correctly...
|
||||
let trait_ref =
|
||||
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
|
||||
ordered_associated_types.extend(
|
||||
ordered_associated_items.extend(
|
||||
tcx.associated_items(pred.trait_ref.def_id)
|
||||
.in_definition_order()
|
||||
// We only care about associated types.
|
||||
.filter(|item| item.is_type())
|
||||
// No RPITITs -- they're not dyn-compatible for now.
|
||||
// Only associated types & consts can possibly be constrained via a binding.
|
||||
.filter(|item| item.is_type() || item.is_const())
|
||||
// Traits with RPITITs are simply not dyn compatible (for now).
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
.map(|item| (item.def_id, trait_ref)),
|
||||
);
|
||||
@@ -237,11 +241,8 @@ pub(super) fn lower_trait_object_ty(
|
||||
let pred = bound_predicate.rebind(pred);
|
||||
// A `Self` within the original bound will be instantiated with a
|
||||
// `trait_object_dummy_self`, so check for that.
|
||||
let references_self = match pred.skip_binder().term.kind() {
|
||||
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
||||
// FIXME(mgca): We should walk the const instead of not doing anything
|
||||
ty::TermKind::Const(_) => false,
|
||||
};
|
||||
let references_self =
|
||||
pred.skip_binder().term.walk().any(|arg| arg == dummy_self.into());
|
||||
|
||||
// If the projection output contains `Self`, force the user to
|
||||
// elaborate it explicitly to avoid a lot of complexity.
|
||||
@@ -262,7 +263,7 @@ pub(super) fn lower_trait_object_ty(
|
||||
// the discussion in #56288 for alternatives.
|
||||
if !references_self {
|
||||
let key = (
|
||||
pred.skip_binder().projection_term.def_id,
|
||||
pred.item_def_id(),
|
||||
tcx.anonymize_bound_vars(
|
||||
pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
|
||||
),
|
||||
@@ -283,15 +284,13 @@ pub(super) fn lower_trait_object_ty(
|
||||
}
|
||||
}
|
||||
|
||||
// `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where
|
||||
// <Self as Trait>::Assoc = Foo`. So every `Projection` clause is an
|
||||
// `Assoc = Foo` bound. `needed_associated_types` contains all associated
|
||||
// types that we expect to be provided by the user, so the following loop
|
||||
// removes all the associated types that have a corresponding `Projection`
|
||||
// clause, either from expanding trait aliases or written by the user.
|
||||
// Flag assoc item bindings that didn't really need to be specified.
|
||||
for &(projection_bound, span) in projection_bounds.values() {
|
||||
let def_id = projection_bound.item_def_id();
|
||||
if tcx.generics_require_sized_self(def_id) {
|
||||
// FIXME(mgca): Ideally we would generalize the name of this lint to sth. like
|
||||
// `unused_associated_item_bindings` since this can now also trigger on *const*
|
||||
// projections / assoc *const* bindings.
|
||||
tcx.emit_node_span_lint(
|
||||
UNUSED_ASSOCIATED_TYPE_BOUNDS,
|
||||
hir_id,
|
||||
@@ -301,35 +300,36 @@ pub(super) fn lower_trait_object_ty(
|
||||
}
|
||||
}
|
||||
|
||||
// We compute the list of projection bounds taking the ordered associated types,
|
||||
// and check if there was an entry in the collected `projection_bounds`. Those
|
||||
// are computed by first taking the user-written associated types, then elaborating
|
||||
// the principal trait ref, and only using those if there was no user-written.
|
||||
// See note below about how we handle missing associated types with `Self: Sized`,
|
||||
// which are not required to be provided, but are still used if they are provided.
|
||||
let mut missing_assoc_types = FxIndexSet::default();
|
||||
let projection_bounds: Vec<_> = ordered_associated_types
|
||||
// The user has to constrain all associated types & consts via bindings unless the
|
||||
// corresponding associated item has a `where Self: Sized` clause. This can be done
|
||||
// in the `dyn Trait` directly, in the supertrait bounds or behind trait aliases.
|
||||
//
|
||||
// Collect all associated items that weren't specified and compute the list of
|
||||
// projection bounds which we'll later turn into existential ones.
|
||||
//
|
||||
// We intentionally keep around projections whose associated item has a `Self: Sized`
|
||||
// bound in order to be able to wfcheck the RHS, allow the RHS to constrain generic
|
||||
// parameters and to imply bounds.
|
||||
// See also <https://github.com/rust-lang/rust/pull/140684>.
|
||||
let mut missing_assoc_items = FxIndexSet::default();
|
||||
let projection_bounds: Vec<_> = ordered_associated_items
|
||||
.into_iter()
|
||||
.filter_map(|key| {
|
||||
if let Some(assoc) = projection_bounds.get(&key) {
|
||||
Some(*assoc)
|
||||
} else {
|
||||
// If the associated type has a `where Self: Sized` bound, then
|
||||
// we do not need to provide the associated type. This results in
|
||||
// a `dyn Trait` type that has a different number of projection
|
||||
// bounds, which may lead to type mismatches.
|
||||
if !tcx.generics_require_sized_self(key.0) {
|
||||
missing_assoc_types.insert(key);
|
||||
}
|
||||
None
|
||||
.filter_map(|key @ (def_id, _)| {
|
||||
if let Some(&assoc) = projection_bounds.get(&key) {
|
||||
return Some(assoc);
|
||||
}
|
||||
if !tcx.generics_require_sized_self(def_id) {
|
||||
missing_assoc_items.insert(key);
|
||||
}
|
||||
None
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Err(guar) = self.check_for_required_assoc_tys(
|
||||
// If there are any associated items whose value wasn't provided, bail out with an error.
|
||||
if let Err(guar) = self.check_for_required_assoc_items(
|
||||
principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
|
||||
missing_assoc_types,
|
||||
potential_assoc_types,
|
||||
missing_assoc_items,
|
||||
potential_assoc_items,
|
||||
hir_bounds,
|
||||
) {
|
||||
return Ty::new_error(tcx, guar);
|
||||
@@ -354,9 +354,9 @@ pub(super) fn lower_trait_object_ty(
|
||||
|
||||
let span = *spans.first().unwrap();
|
||||
|
||||
// Verify that `dummy_self` did not leak inside default type parameters. This
|
||||
// Verify that `dummy_self` did not leak inside generic parameter defaults. This
|
||||
// could not be done at path creation, since we need to see through trait aliases.
|
||||
let mut missing_type_params = vec![];
|
||||
let mut missing_generic_params = Vec::new();
|
||||
let generics = tcx.generics_of(trait_ref.def_id);
|
||||
let args: Vec<_> = trait_ref
|
||||
.args
|
||||
@@ -367,8 +367,8 @@ pub(super) fn lower_trait_object_ty(
|
||||
.map(|(index, arg)| {
|
||||
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||
let param = &generics.own_params[index];
|
||||
missing_type_params.push(param.name);
|
||||
Ty::new_misc_error(tcx).into()
|
||||
missing_generic_params.push((param.name, param.kind.clone()));
|
||||
param.to_error(tcx)
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
@@ -379,8 +379,8 @@ pub(super) fn lower_trait_object_ty(
|
||||
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
|
||||
&& hir_bound.span.contains(span)
|
||||
});
|
||||
self.report_missing_type_params(
|
||||
missing_type_params,
|
||||
self.report_missing_generic_params(
|
||||
missing_generic_params,
|
||||
trait_ref.def_id,
|
||||
span,
|
||||
empty_generic_args,
|
||||
|
||||
@@ -28,31 +28,29 @@
|
||||
|
||||
use super::InherentAssocCandidate;
|
||||
use crate::errors::{
|
||||
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
|
||||
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
|
||||
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, ParenthesizedFnTraitExpansion,
|
||||
TraitObjectDeclaredWithNoTraits,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
|
||||
/// the type parameter's name as a placeholder.
|
||||
pub(crate) fn report_missing_type_params(
|
||||
pub(crate) fn report_missing_generic_params(
|
||||
&self,
|
||||
missing_type_params: Vec<Symbol>,
|
||||
missing_generic_params: Vec<(Symbol, ty::GenericParamDefKind)>,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
empty_generic_args: bool,
|
||||
) {
|
||||
if missing_type_params.is_empty() {
|
||||
if missing_generic_params.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.dcx().emit_err(MissingTypeParams {
|
||||
self.dcx().emit_err(errors::MissingGenericParams {
|
||||
span,
|
||||
def_span: self.tcx().def_span(def_id),
|
||||
span_snippet: self.tcx().sess.source_map().span_to_snippet(span).ok(),
|
||||
missing_type_params,
|
||||
missing_generic_params,
|
||||
empty_generic_args,
|
||||
});
|
||||
}
|
||||
@@ -171,7 +169,7 @@ pub(super) fn report_unresolved_assoc_item<I>(
|
||||
let all_candidate_names: Vec<_> = all_candidates()
|
||||
.flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
|
||||
.filter_map(|item| {
|
||||
if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag {
|
||||
if !item.is_impl_trait_in_trait() && item.tag() == assoc_tag {
|
||||
item.opt_name()
|
||||
} else {
|
||||
None
|
||||
@@ -207,7 +205,7 @@ pub(super) fn report_unresolved_assoc_item<I>(
|
||||
.iter()
|
||||
.flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
|
||||
.filter_map(|item| {
|
||||
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
|
||||
(!item.is_impl_trait_in_trait() && item.tag() == assoc_tag).then(|| item.name())
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -220,7 +218,7 @@ pub(super) fn report_unresolved_assoc_item<I>(
|
||||
.filter(|trait_def_id| {
|
||||
tcx.associated_items(trait_def_id)
|
||||
.filter_by_name_unhygienic(suggested_name)
|
||||
.any(|item| item.as_tag() == assoc_tag)
|
||||
.any(|item| item.tag() == assoc_tag)
|
||||
})
|
||||
.collect::<Vec<_>>()[..]
|
||||
{
|
||||
@@ -383,9 +381,9 @@ fn report_assoc_kind_mismatch(
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(ct) => ct.span,
|
||||
};
|
||||
(span, Some(ident.span), assoc_item.as_tag(), assoc_tag)
|
||||
(span, Some(ident.span), assoc_item.tag(), assoc_tag)
|
||||
} else {
|
||||
(ident.span, None, assoc_tag, assoc_item.as_tag())
|
||||
(ident.span, None, assoc_tag, assoc_item.tag())
|
||||
};
|
||||
|
||||
self.dcx().emit_err(errors::AssocKindMismatch {
|
||||
@@ -393,7 +391,7 @@ fn report_assoc_kind_mismatch(
|
||||
expected: assoc_tag_str(expected),
|
||||
got: assoc_tag_str(got),
|
||||
expected_because_label,
|
||||
assoc_kind: assoc_tag_str(assoc_item.as_tag()),
|
||||
assoc_kind: assoc_tag_str(assoc_item.tag()),
|
||||
def_span: tcx.def_span(assoc_item.def_id),
|
||||
bound_on_assoc_const_label,
|
||||
wrap_in_braces_sugg,
|
||||
@@ -909,43 +907,49 @@ pub(crate) fn report_unresolved_inherent_assoc_item(
|
||||
err.emit()
|
||||
}
|
||||
|
||||
/// When there are any missing associated types, emit an E0191 error and attempt to supply a
|
||||
/// reasonable suggestion on how to write it. For the case of multiple associated types in the
|
||||
/// same trait bound have the same name (as they come from different supertraits), we instead
|
||||
/// emit a generic note suggesting using a `where` clause to constraint instead.
|
||||
pub(crate) fn check_for_required_assoc_tys(
|
||||
/// If there are any missing associated items, emit an error instructing the user to provide
|
||||
/// them unless that's impossible due to shadowing. Moreover, if any corresponding trait refs
|
||||
/// are dyn incompatible due to associated items we emit an dyn incompatibility error instead.
|
||||
pub(crate) fn check_for_required_assoc_items(
|
||||
&self,
|
||||
spans: SmallVec<[Span; 1]>,
|
||||
missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
|
||||
potential_assoc_types: Vec<usize>,
|
||||
missing_assoc_items: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
|
||||
potential_assoc_items: Vec<usize>,
|
||||
trait_bounds: &[hir::PolyTraitRef<'_>],
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if missing_assoc_types.is_empty() {
|
||||
if missing_assoc_items.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let tcx = self.tcx();
|
||||
let principal_span = *spans.first().unwrap();
|
||||
|
||||
let tcx = self.tcx();
|
||||
// FIXME: This logic needs some more care w.r.t handling of conflicts
|
||||
let missing_assoc_types: Vec<_> = missing_assoc_types
|
||||
let missing_assoc_items: Vec<_> = missing_assoc_items
|
||||
.into_iter()
|
||||
.map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
|
||||
.collect();
|
||||
let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default();
|
||||
let mut names: FxIndexMap<_, Vec<_>> = Default::default();
|
||||
let mut names_len = 0;
|
||||
let mut descr = None;
|
||||
|
||||
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
|
||||
// `issue-22560.rs`.
|
||||
let mut dyn_compatibility_violations = Ok(());
|
||||
for (assoc_item, trait_ref) in &missing_assoc_types {
|
||||
names.entry(trait_ref).or_default().push(assoc_item.name());
|
||||
names_len += 1;
|
||||
enum Descr {
|
||||
Item,
|
||||
Tag(ty::AssocTag),
|
||||
}
|
||||
|
||||
for &(assoc_item, trait_ref) in &missing_assoc_items {
|
||||
// We don't want to suggest specifying associated items if there's something wrong with
|
||||
// any of them that renders the trait dyn incompatible; providing them certainly won't
|
||||
// fix the issue and we could also risk suggesting invalid code.
|
||||
//
|
||||
// Note that this check is only truly necessary in item ctxts where we merely perform
|
||||
// *minimal* dyn compatibility checks. In fn ctxts we would've already bailed out with
|
||||
// an error by this point if the trait was dyn incompatible.
|
||||
let violations =
|
||||
dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item);
|
||||
dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), assoc_item);
|
||||
if !violations.is_empty() {
|
||||
dyn_compatibility_violations = Err(report_dyn_incompatibility(
|
||||
return Err(report_dyn_incompatibility(
|
||||
tcx,
|
||||
principal_span,
|
||||
None,
|
||||
@@ -954,15 +958,20 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
)
|
||||
.emit());
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(guar) = dyn_compatibility_violations {
|
||||
return Err(guar);
|
||||
names.entry(trait_ref).or_default().push(assoc_item.name());
|
||||
names_len += 1;
|
||||
|
||||
descr = match descr {
|
||||
None => Some(Descr::Tag(assoc_item.tag())),
|
||||
Some(Descr::Tag(tag)) if tag != assoc_item.tag() => Some(Descr::Item),
|
||||
_ => continue,
|
||||
};
|
||||
}
|
||||
|
||||
// related to issue #91997, turbofishes added only when in an expr or pat
|
||||
let mut in_expr_or_pat = false;
|
||||
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
|
||||
if let ([], [bound]) = (&potential_assoc_items[..], &trait_bounds) {
|
||||
let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
|
||||
in_expr_or_pat = match grandparent {
|
||||
hir::Node::Expr(_) | hir::Node::Pat(_) => true,
|
||||
@@ -970,37 +979,41 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
};
|
||||
}
|
||||
|
||||
// We get all the associated items that _are_ set,
|
||||
// so that we can check if any of their names match one of the ones we are missing.
|
||||
// This would mean that they are shadowing the associated type we are missing,
|
||||
// and we can then use their span to indicate this to the user.
|
||||
let bound_names = trait_bounds
|
||||
.iter()
|
||||
.filter_map(|poly_trait_ref| {
|
||||
let path = poly_trait_ref.trait_ref.path.segments.last()?;
|
||||
let args = path.args?;
|
||||
// We get all the associated items that *are* set, so that we can check if any of
|
||||
// their names match one of the ones we are missing.
|
||||
// This would mean that they are shadowing the associated item we are missing, and
|
||||
// we can then use their span to indicate this to the user.
|
||||
//
|
||||
// FIXME: This does not account for trait aliases. I think we should just make
|
||||
// `lower_trait_object_ty` compute the list of all specified items or give us the
|
||||
// necessary ingredients if it's too expensive to compute in the happy path.
|
||||
let bound_names: UnordMap<_, _> =
|
||||
trait_bounds
|
||||
.iter()
|
||||
.filter_map(|poly_trait_ref| {
|
||||
let path = poly_trait_ref.trait_ref.path.segments.last()?;
|
||||
let args = path.args?;
|
||||
let Res::Def(DefKind::Trait, trait_def_id) = path.res else { return None };
|
||||
|
||||
Some(args.constraints.iter().filter_map(|constraint| {
|
||||
let ident = constraint.ident;
|
||||
Some(args.constraints.iter().filter_map(move |constraint| {
|
||||
let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let tag = match term {
|
||||
hir::Term::Ty(_) => ty::AssocTag::Type,
|
||||
hir::Term::Const(_) => ty::AssocTag::Const,
|
||||
};
|
||||
let assoc_item = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.find_by_ident_and_kind(tcx, constraint.ident, tag, trait_def_id)?;
|
||||
Some(((constraint.ident.name, tag), assoc_item.def_id))
|
||||
}))
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let Res::Def(DefKind::Trait, trait_def) = path.res else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind(
|
||||
tcx,
|
||||
ident,
|
||||
ty::AssocTag::Type,
|
||||
trait_def,
|
||||
);
|
||||
|
||||
Some((ident.name, assoc_item?))
|
||||
}))
|
||||
})
|
||||
.flatten()
|
||||
.collect::<UnordMap<Symbol, &ty::AssocItem>>();
|
||||
|
||||
let mut names = names
|
||||
let mut names: Vec<_> = names
|
||||
.into_iter()
|
||||
.map(|(trait_, mut assocs)| {
|
||||
assocs.sort();
|
||||
@@ -1010,66 +1023,69 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default()
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
.collect();
|
||||
names.sort();
|
||||
let names = names.join(", ");
|
||||
|
||||
let descr = match descr.unwrap() {
|
||||
Descr::Item => "associated item",
|
||||
Descr::Tag(tag) => tag.descr(),
|
||||
};
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
principal_span,
|
||||
E0191,
|
||||
"the value of the associated type{} {} must be specified",
|
||||
pluralize!(names_len),
|
||||
names,
|
||||
"the value of the {descr}{s} {names} must be specified",
|
||||
s = pluralize!(names_len),
|
||||
);
|
||||
let mut suggestions = vec![];
|
||||
let mut types_count = 0;
|
||||
let mut items_count = 0;
|
||||
let mut where_constraints = vec![];
|
||||
let mut already_has_generics_args_suggestion = false;
|
||||
|
||||
let mut names: UnordMap<_, usize> = Default::default();
|
||||
for (item, _) in &missing_assoc_types {
|
||||
types_count += 1;
|
||||
*names.entry(item.name()).or_insert(0) += 1;
|
||||
for (item, _) in &missing_assoc_items {
|
||||
items_count += 1;
|
||||
*names.entry((item.name(), item.tag())).or_insert(0) += 1;
|
||||
}
|
||||
let mut dupes = false;
|
||||
let mut shadows = false;
|
||||
for (item, trait_ref) in &missing_assoc_types {
|
||||
for (item, trait_ref) in &missing_assoc_items {
|
||||
let name = item.name();
|
||||
let prefix = if names[&name] > 1 {
|
||||
let trait_def_id = trait_ref.def_id();
|
||||
let key = (name, item.tag());
|
||||
|
||||
if names[&key] > 1 {
|
||||
dupes = true;
|
||||
format!("{}::", tcx.def_path_str(trait_def_id))
|
||||
} else if bound_names.get(&name).is_some_and(|x| *x != item) {
|
||||
let trait_def_id = trait_ref.def_id();
|
||||
} else if bound_names.get(&key).is_some_and(|&def_id| def_id != item.def_id) {
|
||||
shadows = true;
|
||||
format!("{}::", tcx.def_path_str(trait_def_id))
|
||||
}
|
||||
|
||||
let prefix = if dupes || shadows {
|
||||
format!("{}::", tcx.def_path_str(trait_ref.def_id()))
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let mut is_shadowed = false;
|
||||
|
||||
if let Some(assoc_item) = bound_names.get(&name)
|
||||
&& *assoc_item != item
|
||||
if let Some(&def_id) = bound_names.get(&key)
|
||||
&& def_id != item.def_id
|
||||
{
|
||||
is_shadowed = true;
|
||||
|
||||
let rename_message =
|
||||
if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
|
||||
let rename_message = if def_id.is_local() { ", consider renaming it" } else { "" };
|
||||
err.span_label(
|
||||
tcx.def_span(assoc_item.def_id),
|
||||
format!("`{}{}` shadowed here{}", prefix, name, rename_message),
|
||||
tcx.def_span(def_id),
|
||||
format!("`{prefix}{name}` shadowed here{rename_message}"),
|
||||
);
|
||||
}
|
||||
|
||||
let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
|
||||
|
||||
if let Some(sp) = tcx.hir_span_if_local(item.def_id) {
|
||||
err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message));
|
||||
err.span_label(sp, format!("`{prefix}{name}` defined here{rename_message}"));
|
||||
}
|
||||
}
|
||||
if potential_assoc_types.len() == missing_assoc_types.len() {
|
||||
if potential_assoc_items.len() == missing_assoc_items.len() {
|
||||
// When the amount of missing associated types equals the number of
|
||||
// extra type arguments present. A suggesting to replace the generic args with
|
||||
// associated types is already emitted.
|
||||
@@ -1077,30 +1093,48 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
} else if let (Ok(snippet), false, false) =
|
||||
(tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
|
||||
{
|
||||
let types: Vec<_> = missing_assoc_types
|
||||
let bindings: Vec<_> = missing_assoc_items
|
||||
.iter()
|
||||
.map(|(item, _)| format!("{} = Type", item.name()))
|
||||
.map(|(item, _)| {
|
||||
format!(
|
||||
"{} = /* {} */",
|
||||
item.name(),
|
||||
match item.kind {
|
||||
ty::AssocKind::Const { .. } => "CONST",
|
||||
ty::AssocKind::Type { .. } => "Type",
|
||||
ty::AssocKind::Fn { .. } => unreachable!(),
|
||||
}
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// FIXME(fmease): Does not account for `dyn Trait<>` (suggs `dyn Trait<, X = Y>`).
|
||||
let code = if let Some(snippet) = snippet.strip_suffix('>') {
|
||||
// The user wrote `Trait<'a>` or similar and we don't have a type we can
|
||||
// suggest, but at least we can clue them to the correct syntax
|
||||
// `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
|
||||
// suggestion.
|
||||
format!("{}, {}>", snippet, types.join(", "))
|
||||
// The user wrote `Trait<'a>` or similar and we don't have a term we can suggest,
|
||||
// but at least we can clue them to the correct syntax `Trait<'a, Item = /* ... */>`
|
||||
// while accounting for the `<'a>` in the suggestion.
|
||||
format!("{}, {}>", snippet, bindings.join(", "))
|
||||
} else if in_expr_or_pat {
|
||||
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
|
||||
// least we can clue them to the correct syntax `Iterator::<Item = Type>`.
|
||||
format!("{}::<{}>", snippet, types.join(", "))
|
||||
// The user wrote `Trait`, so we don't have a term we can suggest, but at least we
|
||||
// can clue them to the correct syntax `Trait::<Item = /* ... */>`.
|
||||
format!("{}::<{}>", snippet, bindings.join(", "))
|
||||
} else {
|
||||
// The user wrote `Iterator`, so we don't have a type we can suggest, but at
|
||||
// least we can clue them to the correct syntax `Iterator<Item = Type>`.
|
||||
format!("{}<{}>", snippet, types.join(", "))
|
||||
// The user wrote `Trait`, so we don't have a term we can suggest, but at least we
|
||||
// can clue them to the correct syntax `Trait<Item = /* ... */>`.
|
||||
format!("{}<{}>", snippet, bindings.join(", "))
|
||||
};
|
||||
suggestions.push((principal_span, code));
|
||||
} else if dupes {
|
||||
where_constraints.push(principal_span);
|
||||
}
|
||||
|
||||
// FIXME: This note doesn't make sense, get rid of this outright.
|
||||
// I don't see how adding a type param (to the trait?) would help.
|
||||
// If the user can modify the trait, they should just rename one of the assoc tys.
|
||||
// What does it mean with the rest of the message?
|
||||
// Does it suggest adding equality predicates (unimplemented) to the trait object
|
||||
// type? (pseudo) "dyn B + <Self as B>::X = T + <Self as A>::X = U"?
|
||||
// Instead, maybe mention shadowing if applicable (yes, even when no "relevant"
|
||||
// bindings were provided).
|
||||
let where_msg = "consider introducing a new type parameter, adding `where` constraints \
|
||||
using the fully-qualified path to the associated types";
|
||||
if !where_constraints.is_empty() && suggestions.is_empty() {
|
||||
@@ -1112,12 +1146,12 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
if suggestions.len() != 1 || already_has_generics_args_suggestion {
|
||||
// We don't need this label if there's an inline suggestion, show otherwise.
|
||||
let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
|
||||
for (item, _) in &missing_assoc_types {
|
||||
types_count += 1;
|
||||
for (item, _) in &missing_assoc_items {
|
||||
items_count += 1;
|
||||
*names.entry(item.name()).or_insert(0) += 1;
|
||||
}
|
||||
let mut label = vec![];
|
||||
for (item, trait_ref) in &missing_assoc_types {
|
||||
for (item, trait_ref) in &missing_assoc_items {
|
||||
let name = item.name();
|
||||
let postfix = if names[&name] > 1 {
|
||||
format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
|
||||
@@ -1130,9 +1164,9 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
err.span_label(
|
||||
principal_span,
|
||||
format!(
|
||||
"associated type{} {} must be specified",
|
||||
pluralize!(label.len()),
|
||||
label.join(", "),
|
||||
"{descr}{s} {names} must be specified",
|
||||
s = pluralize!(label.len()),
|
||||
names = label.join(", "),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1153,7 +1187,7 @@ pub(crate) fn check_for_required_assoc_tys(
|
||||
let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
|
||||
if !suggestions.is_empty() && !overlaps {
|
||||
err.multipart_suggestion(
|
||||
format!("specify the associated type{}", pluralize!(types_count)),
|
||||
format!("specify the {descr}{s}", s = pluralize!(items_count)),
|
||||
suggestions,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
|
||||
@@ -1768,7 +1768,7 @@ fn probe_assoc_item_unchecked(
|
||||
let item = tcx
|
||||
.associated_items(scope)
|
||||
.filter_by_name_unhygienic(ident.name)
|
||||
.find(|i| i.as_tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
|
||||
.find(|i| i.tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
|
||||
|
||||
Some((*item, def_scope))
|
||||
}
|
||||
|
||||
@@ -759,14 +759,14 @@ pub struct ImplSourceUserDefinedData<'tcx, N> {
|
||||
pub nested: ThinVec<N>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
pub enum DynCompatibilityViolation {
|
||||
/// `Self: Sized` declared on the trait.
|
||||
SizedSelf(SmallVec<[Span; 1]>),
|
||||
|
||||
/// Trait is marked `#[rustc_dyn_incompatible_trait]`.
|
||||
ExplicitlyDynIncompatible(SmallVec<[Span; 1]>),
|
||||
|
||||
/// `Self: Sized` declared on the trait.
|
||||
SizedSelf(SmallVec<[Span; 1]>),
|
||||
|
||||
/// Supertrait reference references `Self` an in illegal location
|
||||
/// (e.g., `trait Foo : Bar<Self>`).
|
||||
SupertraitSelf(SmallVec<[Span; 1]>),
|
||||
@@ -778,23 +778,24 @@ pub enum DynCompatibilityViolation {
|
||||
SupertraitConst(SmallVec<[Span; 1]>),
|
||||
|
||||
/// Method has something illegal.
|
||||
Method(Symbol, MethodViolationCode, Span),
|
||||
Method(Symbol, MethodViolation, Span),
|
||||
|
||||
/// Associated const.
|
||||
AssocConst(Symbol, Span),
|
||||
/// Associated constant is faulty.
|
||||
AssocConst(Symbol, AssocConstViolation, Span),
|
||||
|
||||
/// GAT
|
||||
GAT(Symbol, Span),
|
||||
/// Generic associated type (GAT).
|
||||
GenericAssocTy(Symbol, Span),
|
||||
}
|
||||
|
||||
impl DynCompatibilityViolation {
|
||||
pub fn error_msg(&self) -> Cow<'static, str> {
|
||||
// FIXME(mgca): For method violations we just say "method ..." but for assoc const ones we
|
||||
// say "it contains ... associated constant ...". Make it consistent.
|
||||
|
||||
match self {
|
||||
DynCompatibilityViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
|
||||
DynCompatibilityViolation::ExplicitlyDynIncompatible(_) => {
|
||||
"it opted out of dyn-compatibility".into()
|
||||
}
|
||||
DynCompatibilityViolation::SupertraitSelf(spans) => {
|
||||
Self::ExplicitlyDynIncompatible(_) => "it opted out of dyn-compatibility".into(),
|
||||
Self::SizedSelf(_) => "it requires `Self: Sized`".into(),
|
||||
Self::SupertraitSelf(spans) => {
|
||||
if spans.iter().any(|sp| *sp != DUMMY_SP) {
|
||||
"it uses `Self` as a type parameter".into()
|
||||
} else {
|
||||
@@ -802,94 +803,80 @@ pub fn error_msg(&self) -> Cow<'static, str> {
|
||||
.into()
|
||||
}
|
||||
}
|
||||
DynCompatibilityViolation::SupertraitNonLifetimeBinder(_) => {
|
||||
Self::SupertraitNonLifetimeBinder(_) => {
|
||||
"where clause cannot reference non-lifetime `for<...>` variables".into()
|
||||
}
|
||||
DynCompatibilityViolation::SupertraitConst(_) => {
|
||||
"it cannot have a `const` supertrait".into()
|
||||
}
|
||||
DynCompatibilityViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
|
||||
Self::SupertraitConst(_) => "it cannot have a `const` supertrait".into(),
|
||||
Self::Method(name, MethodViolation::StaticMethod(_), _) => {
|
||||
format!("associated function `{name}` has no `self` parameter").into()
|
||||
}
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::ReferencesSelfInput(_),
|
||||
DUMMY_SP,
|
||||
) => format!("method `{name}` references the `Self` type in its parameters").into(),
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::ReferencesSelfInput(_),
|
||||
_,
|
||||
) => format!("method `{name}` references the `Self` type in this parameter").into(),
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::ReferencesSelfOutput,
|
||||
_,
|
||||
) => format!("method `{name}` references the `Self` type in its return type").into(),
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::ReferencesImplTraitInTrait(_),
|
||||
_,
|
||||
) => {
|
||||
Self::Method(name, MethodViolation::ReferencesSelfInput(_), DUMMY_SP) => {
|
||||
format!("method `{name}` references the `Self` type in its parameters").into()
|
||||
}
|
||||
Self::Method(name, MethodViolation::ReferencesSelfInput(_), _) => {
|
||||
format!("method `{name}` references the `Self` type in this parameter").into()
|
||||
}
|
||||
Self::Method(name, MethodViolation::ReferencesSelfOutput, _) => {
|
||||
format!("method `{name}` references the `Self` type in its return type").into()
|
||||
}
|
||||
Self::Method(name, MethodViolation::ReferencesImplTraitInTrait(_), _) => {
|
||||
format!("method `{name}` references an `impl Trait` type in its return type").into()
|
||||
}
|
||||
DynCompatibilityViolation::Method(name, MethodViolationCode::AsyncFn, _) => {
|
||||
Self::Method(name, MethodViolation::AsyncFn, _) => {
|
||||
format!("method `{name}` is `async`").into()
|
||||
}
|
||||
DynCompatibilityViolation::Method(name, MethodViolationCode::CVariadic, _) => {
|
||||
Self::Method(name, MethodViolation::CVariadic, _) => {
|
||||
format!("method `{name}` is C-variadic").into()
|
||||
}
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::WhereClauseReferencesSelf,
|
||||
_,
|
||||
) => format!("method `{name}` references the `Self` type in its `where` clause").into(),
|
||||
DynCompatibilityViolation::Method(name, MethodViolationCode::Generic, _) => {
|
||||
Self::Method(name, MethodViolation::WhereClauseReferencesSelf, _) => {
|
||||
format!("method `{name}` references the `Self` type in its `where` clause").into()
|
||||
}
|
||||
Self::Method(name, MethodViolation::Generic, _) => {
|
||||
format!("method `{name}` has generic type parameters").into()
|
||||
}
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::UndispatchableReceiver(_),
|
||||
_,
|
||||
) => format!("method `{name}`'s `self` parameter cannot be dispatched on").into(),
|
||||
DynCompatibilityViolation::AssocConst(name, DUMMY_SP) => {
|
||||
format!("it contains associated `const` `{name}`").into()
|
||||
Self::Method(name, MethodViolation::UndispatchableReceiver(_), _) => {
|
||||
format!("method `{name}`'s `self` parameter cannot be dispatched on").into()
|
||||
}
|
||||
DynCompatibilityViolation::AssocConst(..) => {
|
||||
"it contains this associated `const`".into()
|
||||
Self::AssocConst(name, AssocConstViolation::FeatureNotEnabled, _) => {
|
||||
format!("it contains associated const `{name}`").into()
|
||||
}
|
||||
DynCompatibilityViolation::GAT(name, _) => {
|
||||
format!("it contains the generic associated type `{name}`").into()
|
||||
Self::AssocConst(name, AssocConstViolation::Generic, _) => {
|
||||
format!("it contains generic associated const `{name}`").into()
|
||||
}
|
||||
Self::AssocConst(name, AssocConstViolation::NonType, _) => {
|
||||
format!("it contains associated const `{name}` that's not marked `#[type_const]`")
|
||||
.into()
|
||||
}
|
||||
Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!(
|
||||
"it contains associated const `{name}` whose type references the `Self` type"
|
||||
)
|
||||
.into(),
|
||||
Self::GenericAssocTy(name, _) => {
|
||||
format!("it contains generic associated type `{name}`").into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn solution(&self) -> DynCompatibilityViolationSolution {
|
||||
match self {
|
||||
DynCompatibilityViolation::SizedSelf(_)
|
||||
| DynCompatibilityViolation::ExplicitlyDynIncompatible(_)
|
||||
| DynCompatibilityViolation::SupertraitSelf(_)
|
||||
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(..)
|
||||
| DynCompatibilityViolation::SupertraitConst(_) => {
|
||||
DynCompatibilityViolationSolution::None
|
||||
}
|
||||
DynCompatibilityViolation::Method(
|
||||
Self::ExplicitlyDynIncompatible(_)
|
||||
| Self::SizedSelf(_)
|
||||
| Self::SupertraitSelf(_)
|
||||
| Self::SupertraitNonLifetimeBinder(..)
|
||||
| Self::SupertraitConst(_) => DynCompatibilityViolationSolution::None,
|
||||
Self::Method(
|
||||
name,
|
||||
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
|
||||
MethodViolation::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
|
||||
_,
|
||||
) => DynCompatibilityViolationSolution::AddSelfOrMakeSized {
|
||||
name: *name,
|
||||
add_self_sugg: add_self_sugg.clone(),
|
||||
make_sized_sugg: make_sized_sugg.clone(),
|
||||
},
|
||||
DynCompatibilityViolation::Method(
|
||||
name,
|
||||
MethodViolationCode::UndispatchableReceiver(Some(span)),
|
||||
_,
|
||||
) => DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span),
|
||||
DynCompatibilityViolation::AssocConst(name, _)
|
||||
| DynCompatibilityViolation::GAT(name, _)
|
||||
| DynCompatibilityViolation::Method(name, ..) => {
|
||||
Self::Method(name, MethodViolation::UndispatchableReceiver(Some(span)), _) => {
|
||||
DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span)
|
||||
}
|
||||
Self::Method(name, ..) | Self::AssocConst(name, ..) | Self::GenericAssocTy(name, _) => {
|
||||
DynCompatibilityViolationSolution::MoveToAnotherTrait(*name)
|
||||
}
|
||||
}
|
||||
@@ -899,14 +886,14 @@ pub fn solution(&self) -> DynCompatibilityViolationSolution {
|
||||
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
|
||||
// diagnostics use a `note` instead of a `span_label`.
|
||||
match self {
|
||||
DynCompatibilityViolation::SupertraitSelf(spans)
|
||||
| DynCompatibilityViolation::SizedSelf(spans)
|
||||
| DynCompatibilityViolation::ExplicitlyDynIncompatible(spans)
|
||||
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)
|
||||
| DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(),
|
||||
DynCompatibilityViolation::AssocConst(_, span)
|
||||
| DynCompatibilityViolation::GAT(_, span)
|
||||
| DynCompatibilityViolation::Method(_, _, span) => {
|
||||
Self::ExplicitlyDynIncompatible(spans)
|
||||
| Self::SizedSelf(spans)
|
||||
| Self::SupertraitSelf(spans)
|
||||
| Self::SupertraitNonLifetimeBinder(spans)
|
||||
| Self::SupertraitConst(spans) => spans.clone(),
|
||||
Self::Method(_, _, span)
|
||||
| Self::AssocConst(_, _, span)
|
||||
| Self::GenericAssocTy(_, span) => {
|
||||
if *span != DUMMY_SP {
|
||||
smallvec![*span]
|
||||
} else {
|
||||
@@ -972,8 +959,8 @@ trait objects"
|
||||
}
|
||||
|
||||
/// Reasons a method might not be dyn-compatible.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
|
||||
pub enum MethodViolationCode {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
pub enum MethodViolation {
|
||||
/// e.g., `fn foo()`
|
||||
StaticMethod(Option<(/* add &self */ (String, Span), /* add Self: Sized */ (String, Span))>),
|
||||
|
||||
@@ -1002,6 +989,22 @@ pub enum MethodViolationCode {
|
||||
UndispatchableReceiver(Option<Span>),
|
||||
}
|
||||
|
||||
/// Reasons an associated const might not be dyn compatible.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
pub enum AssocConstViolation {
|
||||
/// Unstable feature `min_generic_const_args` wasn't enabled.
|
||||
FeatureNotEnabled,
|
||||
|
||||
/// Has own generic parameters (GAC).
|
||||
Generic,
|
||||
|
||||
/// Isn't marked `#[type_const]`.
|
||||
NonType,
|
||||
|
||||
/// Its type mentions the `Self` type parameter.
|
||||
TypeReferencesSelf,
|
||||
}
|
||||
|
||||
/// These are the error cases for `codegen_select_candidate`.
|
||||
#[derive(Copy, Clone, Debug, Hash, HashStable, Encodable, Decodable)]
|
||||
pub enum CodegenObligationError {
|
||||
|
||||
@@ -126,30 +126,19 @@ pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self.kind {
|
||||
ty::AssocKind::Const { .. } => "associated const",
|
||||
ty::AssocKind::Fn { has_self: true, .. } => "method",
|
||||
ty::AssocKind::Fn { has_self: false, .. } => "associated function",
|
||||
ty::AssocKind::Type { .. } => "associated type",
|
||||
}
|
||||
self.kind.descr()
|
||||
}
|
||||
|
||||
pub fn namespace(&self) -> Namespace {
|
||||
match self.kind {
|
||||
ty::AssocKind::Type { .. } => Namespace::TypeNS,
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
}
|
||||
self.kind.namespace()
|
||||
}
|
||||
|
||||
pub fn as_def_kind(&self) -> DefKind {
|
||||
match self.kind {
|
||||
AssocKind::Const { .. } => DefKind::AssocConst,
|
||||
AssocKind::Fn { .. } => DefKind::AssocFn,
|
||||
AssocKind::Type { .. } => DefKind::AssocTy,
|
||||
}
|
||||
self.kind.as_def_kind()
|
||||
}
|
||||
pub fn is_type(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Type { .. })
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Const { .. })
|
||||
}
|
||||
|
||||
pub fn is_fn(&self) -> bool {
|
||||
@@ -160,12 +149,12 @@ pub fn is_method(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. })
|
||||
}
|
||||
|
||||
pub fn as_tag(&self) -> AssocTag {
|
||||
match self.kind {
|
||||
AssocKind::Const { .. } => AssocTag::Const,
|
||||
AssocKind::Fn { .. } => AssocTag::Fn,
|
||||
AssocKind::Type { .. } => AssocTag::Type,
|
||||
}
|
||||
pub fn is_type(&self) -> bool {
|
||||
matches!(self.kind, ty::AssocKind::Type { .. })
|
||||
}
|
||||
|
||||
pub fn tag(&self) -> AssocTag {
|
||||
self.kind.tag()
|
||||
}
|
||||
|
||||
pub fn is_impl_trait_in_trait(&self) -> bool {
|
||||
@@ -191,40 +180,61 @@ pub enum AssocKind {
|
||||
|
||||
impl AssocKind {
|
||||
pub fn namespace(&self) -> Namespace {
|
||||
match *self {
|
||||
ty::AssocKind::Type { .. } => Namespace::TypeNS,
|
||||
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
|
||||
match self {
|
||||
Self::Type { .. } => Namespace::TypeNS,
|
||||
Self::Const { .. } | Self::Fn { .. } => Namespace::ValueNS,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tag(&self) -> AssocTag {
|
||||
match self {
|
||||
Self::Const { .. } => AssocTag::Const,
|
||||
Self::Fn { .. } => AssocTag::Fn,
|
||||
Self::Type { .. } => AssocTag::Type,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_def_kind(&self) -> DefKind {
|
||||
match self {
|
||||
AssocKind::Const { .. } => DefKind::AssocConst,
|
||||
AssocKind::Fn { .. } => DefKind::AssocFn,
|
||||
AssocKind::Type { .. } => DefKind::AssocTy,
|
||||
Self::Const { .. } => DefKind::AssocConst,
|
||||
Self::Fn { .. } => DefKind::AssocFn,
|
||||
Self::Type { .. } => DefKind::AssocTy,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Fn { has_self: true, .. } => "method",
|
||||
_ => self.tag().descr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AssocKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
|
||||
AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
|
||||
AssocKind::Const { .. } => write!(f, "associated const"),
|
||||
AssocKind::Type { .. } => write!(f, "associated type"),
|
||||
}
|
||||
f.write_str(self.descr())
|
||||
}
|
||||
}
|
||||
|
||||
// Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
/// Like [`AssocKind`], but just the tag, no fields. Used in various kinds of matching.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum AssocTag {
|
||||
Const,
|
||||
Fn,
|
||||
Type,
|
||||
}
|
||||
|
||||
impl AssocTag {
|
||||
pub fn descr(self) -> &'static str {
|
||||
// This should match `DefKind::descr`.
|
||||
match self {
|
||||
Self::Const => "associated constant",
|
||||
Self::Fn => "associated function",
|
||||
Self::Type => "associated type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
|
||||
///
|
||||
/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
|
||||
@@ -272,7 +282,7 @@ pub fn filter_by_name_unhygienic_and_kind(
|
||||
name: Symbol,
|
||||
assoc_tag: AssocTag,
|
||||
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
|
||||
self.filter_by_name_unhygienic(name).filter(move |item| item.as_tag() == assoc_tag)
|
||||
self.filter_by_name_unhygienic(name).filter(move |item| item.tag() == assoc_tag)
|
||||
}
|
||||
|
||||
/// Returns the associated item with the given identifier and `AssocKind`, if one exists.
|
||||
@@ -285,7 +295,7 @@ pub fn find_by_ident_and_kind(
|
||||
parent_def_id: DefId,
|
||||
) -> Option<&ty::AssocItem> {
|
||||
self.filter_by_name_unhygienic(ident.name)
|
||||
.filter(|item| item.as_tag() == assoc_tag)
|
||||
.filter(|item| item.tag() == assoc_tag)
|
||||
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
|
||||
}
|
||||
|
||||
|
||||
@@ -762,8 +762,7 @@ pub fn new_dynamic(
|
||||
.principal_def_id()
|
||||
.into_iter()
|
||||
.flat_map(|principal_def_id| {
|
||||
// NOTE: This should agree with `needed_associated_types` in
|
||||
// dyn trait lowering, or else we'll have ICEs.
|
||||
// IMPORTANT: This has to agree with HIR ty lowering of dyn trait!
|
||||
elaborate::supertraits(
|
||||
tcx,
|
||||
ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)),
|
||||
@@ -771,7 +770,7 @@ pub fn new_dynamic(
|
||||
.map(|principal| {
|
||||
tcx.associated_items(principal.def_id())
|
||||
.in_definition_order()
|
||||
.filter(|item| item.is_type())
|
||||
.filter(|item| item.is_type() || item.is_const())
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.count()
|
||||
|
||||
@@ -6,7 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
punycode = "0.4.0"
|
||||
rustc-demangle = "0.1.21"
|
||||
rustc-demangle = "0.1.27"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
||||
@@ -648,7 +648,10 @@ fn print_dyn_existential(
|
||||
p.push_ident(name.as_str());
|
||||
match projection.term.kind() {
|
||||
ty::TermKind::Ty(ty) => ty.print(p),
|
||||
ty::TermKind::Const(c) => c.print(p),
|
||||
ty::TermKind::Const(c) => {
|
||||
p.push("K");
|
||||
c.print(p)
|
||||
}
|
||||
}?;
|
||||
}
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_errors::FatalError;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_hir::{self as hir, LangItem, find_attr};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
@@ -24,7 +25,8 @@
|
||||
pub use crate::traits::DynCompatibilityViolation;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{
|
||||
MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util,
|
||||
AssocConstViolation, MethodViolation, Obligation, ObligationCause,
|
||||
normalize_param_env_or_error, util,
|
||||
};
|
||||
|
||||
/// Returns the dyn-compatibility violations that affect HIR ty lowering.
|
||||
@@ -229,7 +231,7 @@ fn predicate_references_self<'tcx>(
|
||||
// types for trait objects.
|
||||
//
|
||||
// Note that we *do* allow projection *outputs* to contain
|
||||
// `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
|
||||
// `Self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
|
||||
// we just require the user to specify *both* outputs
|
||||
// in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
|
||||
//
|
||||
@@ -288,7 +290,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
return false; /* No Sized trait, can't require it! */
|
||||
};
|
||||
|
||||
// Search for a predicate like `Self : Sized` amongst the trait bounds.
|
||||
// Search for a predicate like `Self: Sized` amongst the trait bounds.
|
||||
let predicates = tcx.predicates_of(def_id);
|
||||
let predicates = predicates.instantiate_identity(tcx).predicates;
|
||||
elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
|
||||
@@ -306,24 +308,51 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `Some(_)` if this item makes the containing trait dyn-incompatible.
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
pub fn dyn_compatibility_violations_for_assoc_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
trait_def_id: DefId,
|
||||
item: ty::AssocItem,
|
||||
) -> Vec<DynCompatibilityViolation> {
|
||||
// Any item that has a `Self : Sized` requisite is otherwise
|
||||
// exempt from the regulations.
|
||||
// Any item that has a `Self: Sized` requisite is otherwise exempt from the regulations.
|
||||
if tcx.generics_require_sized_self(item.def_id) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let span = || item.ident(tcx).span;
|
||||
|
||||
match item.kind {
|
||||
// Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all,
|
||||
// and associated const bounds in trait objects aren't a thing yet either.
|
||||
ty::AssocKind::Const { name } => {
|
||||
vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
|
||||
// We will permit type associated consts if they are explicitly mentioned in the
|
||||
// trait object type. We can't check this here, as here we only check if it is
|
||||
// guaranteed to not be possible.
|
||||
|
||||
let mut errors = Vec::new();
|
||||
|
||||
if tcx.features().min_generic_const_args() {
|
||||
if !tcx.generics_of(item.def_id).is_own_empty() {
|
||||
errors.push(AssocConstViolation::Generic);
|
||||
} else if !find_attr!(tcx.get_all_attrs(item.def_id), AttributeKind::TypeConst(_)) {
|
||||
errors.push(AssocConstViolation::NonType);
|
||||
}
|
||||
|
||||
let ty = ty::Binder::dummy(tcx.type_of(item.def_id).instantiate_identity());
|
||||
if contains_illegal_self_type_reference(
|
||||
tcx,
|
||||
trait_def_id,
|
||||
ty,
|
||||
AllowSelfProjections::Yes,
|
||||
) {
|
||||
errors.push(AssocConstViolation::TypeReferencesSelf);
|
||||
}
|
||||
} else {
|
||||
errors.push(AssocConstViolation::FeatureNotEnabled);
|
||||
}
|
||||
|
||||
errors
|
||||
.into_iter()
|
||||
.map(|error| DynCompatibilityViolation::AssocConst(name, error, span()))
|
||||
.collect()
|
||||
}
|
||||
ty::AssocKind::Fn { name, .. } => {
|
||||
virtual_call_violations_for_method(tcx, trait_def_id, item)
|
||||
@@ -332,26 +361,28 @@ pub fn dyn_compatibility_violations_for_assoc_item(
|
||||
let node = tcx.hir_get_if_local(item.def_id);
|
||||
// Get an accurate span depending on the violation.
|
||||
let span = match (&v, node) {
|
||||
(MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
|
||||
(MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
|
||||
(MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
|
||||
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
|
||||
(MethodViolation::ReferencesSelfInput(Some(span)), _) => *span,
|
||||
(MethodViolation::UndispatchableReceiver(Some(span)), _) => *span,
|
||||
(MethodViolation::ReferencesImplTraitInTrait(span), _) => *span,
|
||||
(MethodViolation::ReferencesSelfOutput, Some(node)) => {
|
||||
node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
|
||||
}
|
||||
_ => item.ident(tcx).span,
|
||||
_ => span(),
|
||||
};
|
||||
|
||||
DynCompatibilityViolation::Method(name, v, span)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
|
||||
ty::AssocKind::Type { .. } => {
|
||||
if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
|
||||
vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
|
||||
ty::AssocKind::Type { data } => {
|
||||
if !tcx.generics_of(item.def_id).is_own_empty()
|
||||
&& let ty::AssocTypeData::Normal(name) = data
|
||||
{
|
||||
vec![DynCompatibilityViolation::GenericAssocTy(name, span())]
|
||||
} else {
|
||||
// We will permit associated types if they are explicitly mentioned in the trait object.
|
||||
// We can't check this here, as here we only check if it is guaranteed to not be possible.
|
||||
// We will permit associated types if they are explicitly mentioned in the trait
|
||||
// object type. We can't check this here, as here we only check if it is
|
||||
// guaranteed to not be possible.
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
@@ -366,7 +397,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
method: ty::AssocItem,
|
||||
) -> Vec<MethodViolationCode> {
|
||||
) -> Vec<MethodViolation> {
|
||||
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
|
||||
|
||||
// The method's first parameter must be named `self`
|
||||
@@ -394,7 +425,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||
|
||||
// Not having `self` parameter messes up the later checks,
|
||||
// so we need to return instead of pushing
|
||||
return vec![MethodViolationCode::StaticMethod(sugg)];
|
||||
return vec![MethodViolation::StaticMethod(sugg)];
|
||||
}
|
||||
|
||||
let mut errors = Vec::new();
|
||||
@@ -415,7 +446,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
errors.push(MethodViolationCode::ReferencesSelfInput(span));
|
||||
errors.push(MethodViolation::ReferencesSelfInput(span));
|
||||
}
|
||||
}
|
||||
if contains_illegal_self_type_reference(
|
||||
@@ -424,19 +455,19 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||
sig.output(),
|
||||
AllowSelfProjections::Yes,
|
||||
) {
|
||||
errors.push(MethodViolationCode::ReferencesSelfOutput);
|
||||
errors.push(MethodViolation::ReferencesSelfOutput);
|
||||
}
|
||||
if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
|
||||
errors.push(code);
|
||||
if let Some(error) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
|
||||
errors.push(error);
|
||||
}
|
||||
if sig.skip_binder().c_variadic {
|
||||
errors.push(MethodViolationCode::CVariadic);
|
||||
errors.push(MethodViolation::CVariadic);
|
||||
}
|
||||
|
||||
// We can't monomorphize things like `fn foo<A>(...)`.
|
||||
let own_counts = tcx.generics_of(method.def_id).own_counts();
|
||||
if own_counts.types > 0 || own_counts.consts > 0 {
|
||||
errors.push(MethodViolationCode::Generic);
|
||||
errors.push(MethodViolation::Generic);
|
||||
}
|
||||
|
||||
let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
|
||||
@@ -456,7 +487,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
errors.push(MethodViolationCode::UndispatchableReceiver(span));
|
||||
errors.push(MethodViolation::UndispatchableReceiver(span));
|
||||
} else {
|
||||
// We confirm that the `receiver_is_dispatchable` is accurate later,
|
||||
// see `check_receiver_correct`. It should be kept in sync with this code.
|
||||
@@ -514,7 +545,7 @@ fn virtual_call_violations_for_method<'tcx>(
|
||||
|
||||
contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
|
||||
}) {
|
||||
errors.push(MethodViolationCode::WhereClauseReferencesSelf);
|
||||
errors.push(MethodViolation::WhereClauseReferencesSelf);
|
||||
}
|
||||
|
||||
errors
|
||||
@@ -672,13 +703,16 @@ enum AllowSelfProjections {
|
||||
No,
|
||||
}
|
||||
|
||||
/// This is somewhat subtle. In general, we want to forbid
|
||||
/// references to `Self` in the argument and return types,
|
||||
/// since the value of `Self` is erased. However, there is one
|
||||
/// exception: it is ok to reference `Self` in order to access
|
||||
/// an associated type of the current trait, since we retain
|
||||
/// the value of those associated types in the object type
|
||||
/// itself.
|
||||
/// Check if the given value contains illegal `Self` references.
|
||||
///
|
||||
/// This is somewhat subtle. In general, we want to forbid references to `Self` in the
|
||||
/// argument and return types, since the value of `Self` is erased.
|
||||
///
|
||||
/// However, there is one exception: It is ok to reference `Self` in order to access an
|
||||
/// associated type of the current trait, since we retain the value of those associated
|
||||
/// types in the trait object type itself.
|
||||
///
|
||||
/// The same thing holds for associated consts under feature `min_generic_const_args`.
|
||||
///
|
||||
/// ```rust,ignore (example)
|
||||
/// trait SuperTrait {
|
||||
@@ -733,82 +767,88 @@ struct IllegalSelfTypeVisitor<'tcx> {
|
||||
allow_self_projections: AllowSelfProjections,
|
||||
}
|
||||
|
||||
impl<'tcx> IllegalSelfTypeVisitor<'tcx> {
|
||||
fn is_supertrait_of_current_trait(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
|
||||
// Compute supertraits of current trait lazily.
|
||||
let supertraits = self.supertraits.get_or_insert_with(|| {
|
||||
util::supertraits(
|
||||
self.tcx,
|
||||
ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)),
|
||||
)
|
||||
.map(|trait_ref| {
|
||||
self.tcx.erase_and_anonymize_regions(
|
||||
self.tcx.instantiate_bound_regions_with_erased(trait_ref),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
// Determine whether the given trait ref is in fact a supertrait of the current trait.
|
||||
// In that case, any derived projections are legal, because the term will be specified
|
||||
// in the trait object type.
|
||||
// Note that we can just use direct equality here because all of these types are part of
|
||||
// the formal parameter listing, and hence there should be no inference variables.
|
||||
let trait_ref = trait_ref
|
||||
.fold_with(&mut EraseEscapingBoundRegions { tcx: self.tcx, binder: ty::INNERMOST });
|
||||
supertraits.contains(&trait_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
match t.kind() {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
match ty.kind() {
|
||||
ty::Param(_) => {
|
||||
if t == self.tcx.types.self_param {
|
||||
if ty == self.tcx.types.self_param {
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
ty::Alias(ty::Projection, data) if self.tcx.is_impl_trait_in_trait(data.def_id) => {
|
||||
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => {
|
||||
// We'll deny these later in their own pass
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
ty::Alias(ty::Projection, data) => {
|
||||
ty::Alias(ty::Projection, proj) => {
|
||||
match self.allow_self_projections {
|
||||
AllowSelfProjections::Yes => {
|
||||
// This is a projected type `<Foo as SomeTrait>::X`.
|
||||
|
||||
// Compute supertraits of current trait lazily.
|
||||
if self.supertraits.is_none() {
|
||||
self.supertraits = Some(
|
||||
util::supertraits(
|
||||
self.tcx,
|
||||
ty::Binder::dummy(ty::TraitRef::identity(
|
||||
self.tcx,
|
||||
self.trait_def_id,
|
||||
)),
|
||||
)
|
||||
.map(|trait_ref| {
|
||||
self.tcx.erase_and_anonymize_regions(
|
||||
self.tcx.instantiate_bound_regions_with_erased(trait_ref),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
// Determine whether the trait reference `Foo as
|
||||
// SomeTrait` is in fact a supertrait of the
|
||||
// current trait. In that case, this type is
|
||||
// legal, because the type `X` will be specified
|
||||
// in the object type. Note that we can just use
|
||||
// direct equality here because all of these types
|
||||
// are part of the formal parameter listing, and
|
||||
// hence there should be no inference variables.
|
||||
let is_supertrait_of_current_trait =
|
||||
self.supertraits.as_ref().unwrap().contains(
|
||||
&data.trait_ref(self.tcx).fold_with(
|
||||
&mut EraseEscapingBoundRegions {
|
||||
tcx: self.tcx,
|
||||
binder: ty::INNERMOST,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// only walk contained types if it's not a super trait
|
||||
if is_supertrait_of_current_trait {
|
||||
// Only walk contained types if the parent trait is not a supertrait.
|
||||
if self.is_supertrait_of_current_trait(proj.trait_ref(self.tcx)) {
|
||||
ControlFlow::Continue(())
|
||||
} else {
|
||||
t.super_visit_with(self) // POSSIBLY reporting an error
|
||||
ty.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
AllowSelfProjections::No => t.super_visit_with(self),
|
||||
AllowSelfProjections::No => ty.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
_ => t.super_visit_with(self),
|
||||
_ => ty.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
|
||||
// Constants can only influence dyn-compatibility if they are generic and reference `Self`.
|
||||
// This is only possible for unevaluated constants, so we walk these here.
|
||||
self.tcx.expand_abstract_consts(ct).super_visit_with(self)
|
||||
let ct = self.tcx.expand_abstract_consts(ct);
|
||||
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => {
|
||||
match self.allow_self_projections {
|
||||
AllowSelfProjections::Yes => {
|
||||
let trait_def_id = self.tcx.parent(proj.def);
|
||||
let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args);
|
||||
|
||||
// Only walk contained consts if the parent trait is not a supertrait.
|
||||
if self.is_supertrait_of_current_trait(trait_ref) {
|
||||
ControlFlow::Continue(())
|
||||
} else {
|
||||
ct.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
AllowSelfProjections::No => ct.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
_ => ct.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,12 +887,12 @@ fn contains_illegal_impl_trait_in_trait<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
fn_def_id: DefId,
|
||||
ty: ty::Binder<'tcx, Ty<'tcx>>,
|
||||
) -> Option<MethodViolationCode> {
|
||||
) -> Option<MethodViolation> {
|
||||
let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
|
||||
|
||||
if tcx.asyncness(fn_def_id).is_async() {
|
||||
// Rendering the error as a separate `async-specific` message is better.
|
||||
Some(MethodViolationCode::AsyncFn)
|
||||
Some(MethodViolation::AsyncFn)
|
||||
} else {
|
||||
ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
|
||||
}
|
||||
@@ -864,14 +904,14 @@ struct IllegalRpititVisitor<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
|
||||
type Result = ControlFlow<MethodViolationCode>;
|
||||
type Result = ControlFlow<MethodViolation>;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
if let ty::Alias(ty::Projection, proj) = *ty.kind()
|
||||
&& Some(proj) != self.allowed
|
||||
&& self.tcx.is_impl_trait_in_trait(proj.def_id)
|
||||
{
|
||||
ControlFlow::Break(MethodViolationCode::ReferencesImplTraitInTrait(
|
||||
ControlFlow::Break(MethodViolation::ReferencesImplTraitInTrait(
|
||||
self.tcx.def_span(proj.def_id),
|
||||
))
|
||||
} else {
|
||||
|
||||
@@ -857,7 +857,11 @@ Remaining primitives are encoded as a crate production, e.g. `C4f128`.
|
||||
>
|
||||
> <span id="dyn-trait">dyn-trait</span> → *[path]* {*[dyn-trait-assoc-binding]*}
|
||||
>
|
||||
> <span id="dyn-trait-assoc-binding">dyn-trait-assoc-binding</span> → `p` *[undisambiguated-identifier]* *[type]*
|
||||
> <span id="dyn-trait-assoc-binding">dyn-trait-assoc-binding</span> → `p` *[undisambiguated-identifier]* *[type-or-const]*
|
||||
>
|
||||
> <span id="type-or-const">type-or-const</span> → \
|
||||
> *[type]* \
|
||||
> | `K` *[const]*
|
||||
|
||||
The tag `D` is followed by a *[dyn-bounds]* which encodes the trait bounds,
|
||||
followed by a *[lifetime]* of the trait object lifetime bound.
|
||||
@@ -867,11 +871,12 @@ Remaining primitives are encoded as a crate production, e.g. `C4f128`.
|
||||
|
||||
Each *[dyn-trait]* represents a trait bound, which consists of a *[path]* to the trait followed by zero or more *[dyn-trait-assoc-binding]* which list the associated types.
|
||||
|
||||
Each *[dyn-trait-assoc-binding]* consists of a character `p` followed a *[undisambiguated-identifier]* representing the associated binding name, and finally a *[type]*.
|
||||
Each *[dyn-trait-assoc-binding]* consists of a character `p` followed a *[undisambiguated-identifier]* representing the associated binding name, and finally a *[type-or-const]*.
|
||||
|
||||
[dyn-bounds]: #dyn-bounds
|
||||
[dyn-trait]: #dyn-trait
|
||||
[dyn-trait-assoc-binding]: #dyn-trait-assoc-binding
|
||||
[type-or-const]: #type-or-const
|
||||
|
||||
|
||||
* A *[path]* to a named type.
|
||||
|
||||
@@ -561,7 +561,7 @@ pub(crate) fn build_impl(
|
||||
.find_by_ident_and_kind(
|
||||
tcx,
|
||||
item.ident(tcx),
|
||||
item.as_tag(),
|
||||
item.tag(),
|
||||
associated_trait.def_id,
|
||||
)
|
||||
.unwrap(); // corresponding associated item has to exist
|
||||
|
||||
@@ -1226,7 +1226,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n
|
||||
.associated_items(did)
|
||||
.filter_by_name_unhygienic(method_name)
|
||||
.next()
|
||||
.filter(|item| item.as_tag() == AssocTag::Fn)
|
||||
.filter(|item| item.tag() == AssocTag::Fn)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
//@ known-bug: #136063
|
||||
#![feature(generic_const_exprs)]
|
||||
trait A<const B: u8 = X> {}
|
||||
impl A<1> for bool {}
|
||||
fn bar(arg : &dyn A<x>) { bar(true) }
|
||||
pub fn main() {}
|
||||
@@ -1,11 +0,0 @@
|
||||
//@ known-bug: #137260
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Iter<const N: usize = { 1 + true }> {}
|
||||
|
||||
fn needs_iter<const N: usize, T: Iter<N>>() {}
|
||||
|
||||
fn test() {
|
||||
needs_iter::<1, dyn Iter<()>>();
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
//@ known-bug: #137514
|
||||
//@ needs-rustc-debug-assertions
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
trait Bar<const N: usize> {}
|
||||
|
||||
trait BB = Bar<{ 1i32 + 1 }>;
|
||||
|
||||
fn foo(x: &dyn BB) {}
|
||||
@@ -0,0 +1,34 @@
|
||||
//@ compile-flags: -g
|
||||
//@ disable-gdb-pretty-printers
|
||||
//@ ignore-backends: gcc
|
||||
|
||||
//@ gdb-command:run
|
||||
//@ gdb-command:whatis local
|
||||
//@ gdb-check:type = &dyn associated_const_bindings::Trait<N=101>
|
||||
|
||||
//@ cdb-command: g
|
||||
//@ cdb-command:dv /t /n local
|
||||
//@ cdb-check:struct ref$<dyn$<associated_const_bindings::Trait<assoc$<N,101> > > > local = [...]
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(unused_variables, incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
impl Trait for () {
|
||||
#[type_const]
|
||||
const N: usize = 101;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let local = &() as &dyn Trait<N = 101>;
|
||||
|
||||
zzz(); // #break
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn zzz() {
|
||||
()
|
||||
}
|
||||
@@ -7,8 +7,6 @@ trait Trait {
|
||||
impl dyn Trait {
|
||||
//~^ ERROR the trait `Trait` is not dyn compatible [E0038]
|
||||
const fn n() -> usize { Self::N }
|
||||
//~^ ERROR the trait `Trait` is not dyn compatible [E0038]
|
||||
//~| ERROR the trait `Trait` is not dyn compatible
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/associated-const-in-trait.rs:7:6
|
||||
--> $DIR/associated-const-in-trait.rs:7:10
|
||||
|
|
||||
LL | impl dyn Trait {
|
||||
| ^^^^^^^^^ `Trait` is not dyn compatible
|
||||
| ^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
@@ -11,41 +11,9 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const N: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
| ^ ...because it contains associated const `N`
|
||||
= help: consider moving `N` to another trait
|
||||
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/associated-const-in-trait.rs:9:29
|
||||
|
|
||||
LL | const fn n() -> usize { Self::N }
|
||||
| ^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/associated-const-in-trait.rs:4:11
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const N: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
= help: consider moving `N` to another trait
|
||||
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/associated-const-in-trait.rs:9:29
|
||||
|
|
||||
LL | const fn n() -> usize { Self::N }
|
||||
| ^^^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/associated-const-in-trait.rs:4:11
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const N: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
= help: consider moving `N` to another trait
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error[E0038]: the trait `Bar` is not dyn compatible
|
||||
--> $DIR/issue-48027.rs:6:6
|
||||
--> $DIR/issue-48027.rs:6:10
|
||||
|
|
||||
LL | impl dyn Bar {}
|
||||
| ^^^^^^^ `Bar` is not dyn compatible
|
||||
| ^^^ `Bar` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Bar {
|
||||
| --- this trait is not dyn compatible...
|
||||
LL | const X: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
| ^ ...because it contains associated const `X`
|
||||
= help: consider moving `X` to another trait
|
||||
|
||||
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
|
||||
|
||||
@@ -86,7 +86,7 @@ fn uncallable_rtn(
|
||||
|
||||
type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
//~^ ERROR [E0719]
|
||||
//~| ERROR conflicting associated type bounds
|
||||
//~| ERROR conflicting associated type bindings
|
||||
|
||||
trait Trait2 {
|
||||
#[type_const]
|
||||
@@ -95,7 +95,7 @@ trait Trait2 {
|
||||
|
||||
type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
//~^ ERROR [E0719]
|
||||
//~| ERROR conflicting associated type bounds
|
||||
//~| ERROR conflicting associated constant bindings
|
||||
|
||||
type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
||||
//~^ ERROR [E0719]
|
||||
|
||||
@@ -116,7 +116,7 @@ LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
| |
|
||||
| `Item` bound here first
|
||||
|
||||
error: conflicting associated type bounds for `Item`
|
||||
error: conflicting associated type bindings for `Item`
|
||||
--> $DIR/duplicate-bound-err.rs:87:17
|
||||
|
|
||||
LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
@@ -133,7 +133,7 @@ LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
| |
|
||||
| `ASSOC` bound here first
|
||||
|
||||
error: conflicting associated type bounds for `ASSOC`
|
||||
error: conflicting associated constant bindings for `ASSOC`
|
||||
--> $DIR/duplicate-bound-err.rs:96:18
|
||||
|
|
||||
LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
|
||||
@@ -2,7 +2,7 @@ error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIt
|
||||
--> $DIR/overlaping-bound-suggestion.rs:7:13
|
||||
|
|
||||
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = /* Type */, IntoIter = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type B;
|
||||
| ------ `B` defined here
|
||||
...
|
||||
LL | let b = &42isize as &dyn Foo<A=usize>;
|
||||
| ^^^^^^^^^^^^ help: specify the associated type: `Foo<A=usize, B = Type>`
|
||||
| ^^^^^^^^^^^^ help: specify the associated type: `Foo<A=usize, B = /* Type */>`
|
||||
|
||||
error[E0191]: the value of the associated type `A` in `Foo` must be specified
|
||||
--> $DIR/associated-types-incomplete-object.rs:26:30
|
||||
@@ -14,7 +14,7 @@ LL | type A;
|
||||
| ------ `A` defined here
|
||||
...
|
||||
LL | let c = &42isize as &dyn Foo<B=char>;
|
||||
| ^^^^^^^^^^^ help: specify the associated type: `Foo<B=char, A = Type>`
|
||||
| ^^^^^^^^^^^ help: specify the associated type: `Foo<B=char, A = /* Type */>`
|
||||
|
||||
error[E0191]: the value of the associated types `A` and `B` in `Foo` must be specified
|
||||
--> $DIR/associated-types-incomplete-object.rs:29:30
|
||||
@@ -25,7 +25,7 @@ LL | type B;
|
||||
| ------ `B` defined here
|
||||
...
|
||||
LL | let d = &42isize as &dyn Foo;
|
||||
| ^^^ help: specify the associated types: `Foo<A = Type, B = Type>`
|
||||
| ^^^ help: specify the associated types: `Foo<A = /* Type */, B = /* Type */>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
|
||||
fn main() {
|
||||
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
|
||||
//~^ ERROR conflicting associated type bounds
|
||||
//~^ ERROR conflicting associated type bindings
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
error: conflicting associated type bounds for `Item`
|
||||
error: conflicting associated type bindings for `Item`
|
||||
--> $DIR/associated-types-overridden-binding-2.rs:6:13
|
||||
|
|
||||
LL | trait I32Iterator = Iterator<Item = i32>;
|
||||
|
||||
@@ -8,5 +8,5 @@ trait Bar: Foo<Item = u32> {} //~ ERROR type annotations needed
|
||||
|
||||
fn main() {
|
||||
let _: &dyn I32Iterator<Item = u32>;
|
||||
//~^ ERROR conflicting associated type bounds
|
||||
//~^ ERROR conflicting associated type bindings
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ note: required by a bound in `I32Iterator`
|
||||
LL | trait I32Iterator = Iterator<Item = i32>;
|
||||
| ^^^^^^^^^^ required by this bound in `I32Iterator`
|
||||
|
||||
error: conflicting associated type bounds for `Item`
|
||||
error: conflicting associated type bindings for `Item`
|
||||
--> $DIR/associated-types-overridden-binding.rs:10:13
|
||||
|
|
||||
LL | trait I32Iterator = Iterator<Item = i32>;
|
||||
|
||||
@@ -6,7 +6,7 @@ LL | type Value;
|
||||
LL | type ChildKey;
|
||||
| ------------- `ChildKey` defined here
|
||||
LL | type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy>;
|
||||
| ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy<Value = Type, ChildKey = Type, Children = Type>`
|
||||
| ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy<Value = /* Type */, ChildKey = /* Type */, Children = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
|
||||
|
|
||||
= note: the trait is not dyn compatible because it contains the generic associated type `CallRefFuture`
|
||||
= note: the trait is not dyn compatible because it contains generic associated type `CallRefFuture`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Ensure that we consider traits dyn *in*compatible if the type of any (type) assoc const
|
||||
// mentions `Self` (barring "`Self` projections")
|
||||
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
#![feature(generic_const_items)]
|
||||
#![feature(generic_const_parameter_types)]
|
||||
#![feature(min_generic_const_args)]
|
||||
#![feature(unsized_const_params)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
// NOTE: The `ConstParamTy_` bound is intentionally on the assoc const and not on the trait as
|
||||
// doing the latter would already render the trait dyn incompatible due to it being
|
||||
// bounded by `PartialEq<Self>` and supertrait bounds cannot mention `Self` like this.
|
||||
#[type_const]
|
||||
const K: Self where Self: std::marker::ConstParamTy_;
|
||||
//~^ NOTE it contains associated const `K` whose type references the `Self` type
|
||||
|
||||
// This is not a "`Self` projection" in our sense (which would be allowed)
|
||||
// since the trait is not the principal trait or a supertrait thereof.
|
||||
#[type_const]
|
||||
const Q: <Self as SomeOtherTrait>::Output;
|
||||
//~^ NOTE it contains associated const `Q` whose type references the `Self` type
|
||||
}
|
||||
|
||||
trait SomeOtherTrait {
|
||||
type Output: std::marker::ConstParamTy_;
|
||||
}
|
||||
|
||||
// You could imagine this impl being more interesting and mention `T` somewhere in `Output`...
|
||||
impl<T: ?Sized> SomeOtherTrait for T {
|
||||
type Output = ();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Trait; //~ ERROR the trait `Trait` is not dyn compatible
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:37:16
|
||||
|
|
||||
LL | let _: dyn Trait;
|
||||
| ^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:17:11
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
...
|
||||
LL | const K: Self where Self: std::marker::ConstParamTy_;
|
||||
| ^ ...because it contains associated const `K` whose type references the `Self` type
|
||||
...
|
||||
LL | const Q: <Self as SomeOtherTrait>::Output;
|
||||
| ^ ...because it contains associated const `Q` whose type references the `Self` type
|
||||
= help: consider moving `K` to another trait
|
||||
= help: consider moving `Q` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
@@ -0,0 +1,38 @@
|
||||
// Traits with type associated consts are dyn compatible.
|
||||
// Check that we allow the corresp. trait object types if all assoc consts are specified.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait: SuperTrait<C = 3> {
|
||||
#[type_const]
|
||||
const K: usize;
|
||||
}
|
||||
|
||||
trait SuperTrait {
|
||||
#[type_const]
|
||||
const Q: usize;
|
||||
#[type_const]
|
||||
const C: usize;
|
||||
}
|
||||
|
||||
trait Bound {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
impl Bound for () {
|
||||
#[type_const]
|
||||
const N: usize = 10;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Trait<K = 1, Q = 2>;
|
||||
|
||||
let obj: &dyn Bound<N = 10> = &();
|
||||
_ = identity(obj);
|
||||
|
||||
fn identity(x: &(impl ?Sized + Bound<N = 10>)) -> &(impl ?Sized + Bound<N = 10>) { x }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Ensure that we actually enforce equality constraints found in trait object types.
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
impl Trait for () {
|
||||
#[type_const]
|
||||
const N: usize = 1;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: &dyn Trait<N = 0> = &(); //~ ERROR type mismatch resolving `<() as Trait>::N == 0`
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
error[E0271]: type mismatch resolving `<() as Trait>::N == 0`
|
||||
--> $DIR/dyn-compat-const-mismatch.rs:17:32
|
||||
|
|
||||
LL | let _: &dyn Trait<N = 0> = &();
|
||||
| ^^^ expected `0`, found `1`
|
||||
|
|
||||
= note: expected constant `0`
|
||||
found constant `1`
|
||||
= note: required for the cast from `&()` to `&dyn Trait<N = 0>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Test that we force users to explicitly specify const arguments for const parameters that
|
||||
// have defaults if the default mentions the `Self` type parameter.
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait X<const N: usize = { <Self as Y>::N }> {}
|
||||
|
||||
trait Y {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Y for T {
|
||||
#[type_const]
|
||||
const N: usize = 1;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn X; //~ ERROR the const parameter `N` must be explicitly specified
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
error[E0393]: the const parameter `N` must be explicitly specified
|
||||
--> $DIR/dyn-compat-const-param-default-mentions-self.rs:20:16
|
||||
|
|
||||
LL | trait X<const N: usize = { <Self as Y>::N }> {}
|
||||
| -------------------------------------------- const parameter `N` must be specified for this
|
||||
...
|
||||
LL | let _: dyn X;
|
||||
| ^
|
||||
|
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the trait object type
|
||||
help: explicitly specify the const parameter
|
||||
|
|
||||
LL | let _: dyn X</* N */>;
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0393`.
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Check that we reject const projections behind trait aliases that mention `Self`.
|
||||
// The code below is pretty artifical and contains a type mismatch anyway but we still need to
|
||||
// reject it & lower the `Self` ty param to a `{type error}` to avoid ICEs down the line.
|
||||
//
|
||||
// The author of the trait object type can't fix this unlike the supertrait bound
|
||||
// equivalent where they just need to explicitly specify the assoc const.
|
||||
|
||||
#![feature(min_generic_const_args, trait_alias)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const Y: i32;
|
||||
}
|
||||
|
||||
struct Hold<T: ?Sized>(T);
|
||||
|
||||
trait Bound = Trait<Y = { Hold::<Self> }>;
|
||||
|
||||
fn main() {
|
||||
let _: dyn Bound; //~ ERROR associated constant binding in trait object type mentions `Self`
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
error: associated constant binding in trait object type mentions `Self`
|
||||
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:21:12
|
||||
|
|
||||
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
|
||||
| -------------------- this binding mentions `Self`
|
||||
...
|
||||
LL | let _: dyn Bound;
|
||||
| ^^^^^^^^^ contains a mention of `Self`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// Test that we force users to explicitly specify associated constants (via bindings)
|
||||
// which reference the `Self` type parameter.
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait X: Y<K = { Self::Q }> {
|
||||
#[type_const]
|
||||
const Q: usize;
|
||||
}
|
||||
|
||||
trait Y {
|
||||
#[type_const]
|
||||
const K: usize;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn X<Q = 10>;
|
||||
//~^ ERROR the value of the associated constant `K` in `Y` must be specified
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
error[E0191]: the value of the associated constant `K` in `Y` must be specified
|
||||
--> $DIR/dyn-compat-const-projection-from-supertrait-mentions-self.rs:18:16
|
||||
|
|
||||
LL | const K: usize;
|
||||
| -------------- `K` defined here
|
||||
...
|
||||
LL | let _: dyn X<Q = 10>;
|
||||
| ^^^^^^^^^ help: specify the associated constant: `X<Q = 10, K = /* CONST */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0191`.
|
||||
@@ -0,0 +1,16 @@
|
||||
// Ensure that traits with generic associated consts (GACs) are dyn *in*compatible.
|
||||
// It would be very hard to make dyn Trait with GACs sound just like with GATs.
|
||||
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
#![feature(min_generic_const_args, generic_const_items)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
const POLY<T>: T;
|
||||
//~^ NOTE it contains generic associated const `POLY`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Trait; //~ ERROR the trait `Trait` is not dyn compatible
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-generic-assoc-const.rs:15:16
|
||||
|
|
||||
LL | let _: dyn Trait;
|
||||
| ^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/dyn-compat-generic-assoc-const.rs:10:11
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const POLY<T>: T;
|
||||
| ^^^^ ...because it contains generic associated const `POLY`
|
||||
= help: consider moving `POLY` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
@@ -0,0 +1,20 @@
|
||||
// Ensure that traits with non-type associated consts are dyn *in*compatible.
|
||||
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
const K: usize;
|
||||
//~^ NOTE it contains associated const `K` that's not marked `#[type_const]`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Trait; //~ ERROR the trait `Trait` is not dyn compatible
|
||||
|
||||
// Check that specifying the non-type assoc const doesn't "magically make it work".
|
||||
let _: dyn Trait<K = 0>;
|
||||
//~^ ERROR the trait `Trait` is not dyn compatible
|
||||
//~| ERROR use of trait associated const without `#[type_const]`
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:14:16
|
||||
|
|
||||
LL | let _: dyn Trait;
|
||||
| ^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:9:11
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const K: usize;
|
||||
| ^ ...because it contains associated const `K` that's not marked `#[type_const]`
|
||||
= help: consider moving `K` to another trait
|
||||
|
||||
error: use of trait associated const without `#[type_const]`
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:22
|
||||
|
|
||||
LL | let _: dyn Trait<K = 0>;
|
||||
| ^^^^^
|
||||
|
|
||||
= note: the declaration in the trait must be marked with `#[type_const]`
|
||||
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:16
|
||||
|
|
||||
LL | let _: dyn Trait<K = 0>;
|
||||
| ^^^^^^^^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:9:11
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const K: usize;
|
||||
| ^ ...because it contains associated const `K` that's not marked `#[type_const]`
|
||||
= help: consider moving `K` to another trait
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// Ensure that the where-clause of assoc consts in dyn-compatible traits are allowed to freely
|
||||
// reference the `Self` type parameter (contrary to methods) and that such where clauses are
|
||||
// actually enforced.
|
||||
|
||||
#![feature(min_generic_const_args, generic_const_items)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: i32 where Self: Bound;
|
||||
}
|
||||
|
||||
impl Trait for () {
|
||||
#[type_const]
|
||||
const N: i32 = 0;
|
||||
}
|
||||
|
||||
trait Bound {}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Trait<N = 0>; // OK
|
||||
|
||||
let _: &dyn Trait<N = 0> = &(); //~ ERROR the trait bound `(): Bound` is not satisfied
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
error[E0277]: the trait bound `(): Bound` is not satisfied
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:23:32
|
||||
|
|
||||
LL | let _: &dyn Trait<N = 0> = &();
|
||||
| ^^^ the trait `Bound` is not implemented for `()`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:18:1
|
||||
|
|
||||
LL | trait Bound {}
|
||||
| ^^^^^^^^^^^
|
||||
note: required by a bound in `Trait::N`
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:10:30
|
||||
|
|
||||
LL | const N: i32 where Self: Bound;
|
||||
| ^^^^^ required by this bound in `Trait::N`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// FIXME(mgca): Ideally this would compile -- at least if the user annotated the instantiated type
|
||||
// of the assoc const (but we don't have the syntax for this (yet)). In any case, we
|
||||
// should not leak `trait_object_dummy_self` (defined as `FreshTy(0)` under the hood)
|
||||
// to the rest of the compiler and by extension the user via diagnostics.
|
||||
//@ known-bug: unknown
|
||||
|
||||
#![feature(min_generic_const_args, unsized_const_params, generic_const_parameter_types)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait A {
|
||||
type Ty: std::marker::ConstParamTy_;
|
||||
#[type_const] const CT: Self::Ty;
|
||||
}
|
||||
|
||||
impl A for () {
|
||||
type Ty = i32;
|
||||
#[type_const] const CT: i32 = 0;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// NOTE: As alluded to above, if we can't get the examples below to compile as written,
|
||||
// we might want to allow the user to manually specify the instantiated type somehow.
|
||||
// The hypothetical syntax for that *might* look sth. like
|
||||
// * `dyn A<Ty = i32, CT = const -> i32 { 0 }>`
|
||||
// * `dyn A<Ty = i32, CT: i32 = 0>`
|
||||
|
||||
let _: dyn A<Ty = i32, CT = 0>;
|
||||
|
||||
let _: &dyn A<Ty = i32, CT = 0> = &();
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
error[E0277]: the trait bound `FreshTy(0): A` is not satisfied
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:27:33
|
||||
|
|
||||
LL | let _: dyn A<Ty = i32, CT = 0>;
|
||||
| ^ the trait `A` is not implemented for `FreshTy(0)`
|
||||
|
|
||||
help: the trait `A` is implemented for `()`
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:15:1
|
||||
|
|
||||
LL | impl A for () {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `FreshTy(0): A` is not satisfied
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:29:34
|
||||
|
|
||||
LL | let _: &dyn A<Ty = i32, CT = 0> = &();
|
||||
| ^ the trait `A` is not implemented for `FreshTy(0)`
|
||||
|
|
||||
help: the trait `A` is implemented for `()`
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:15:1
|
||||
|
|
||||
LL | impl A for () {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// While mentioning `Self` in the method signature of dyn compatible traits is generally forbidden
|
||||
// due to type erasure, we can make an exception for const projections from `Self` where the trait
|
||||
// is the principal trait or a supertrait thereof. That's sound because we force users to specify
|
||||
// all associated consts in the trait object type, so the projections are all normalizable.
|
||||
//
|
||||
// Check that we can define & use dyn compatible traits that reference `Self` const projections.
|
||||
|
||||
// This is a run-pass test to ensure that codegen can actually deal with such method instances
|
||||
// (e.g., const projections normalize flawlessly to something concrete, symbols get mangled
|
||||
// properly, the vtable is fine) and simply to ensure that the generated code "received" the
|
||||
// correct values from the type assoc consts).
|
||||
//@ run-pass
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
|
||||
fn process(&self, _: [u8; Self::N]) -> [u8; Self::N];
|
||||
}
|
||||
|
||||
impl Trait for u8 {
|
||||
#[type_const]
|
||||
const N: usize = 2;
|
||||
|
||||
fn process(&self, [x, y]: [u8; Self::N]) -> [u8; Self::N] {
|
||||
[self * x, self + y]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Trait for [u8; N] {
|
||||
#[type_const]
|
||||
const N: usize = N;
|
||||
|
||||
fn process(&self, other: [u8; Self::N]) -> [u8; Self::N] {
|
||||
let mut result = [0; _];
|
||||
for i in 0..Self::N {
|
||||
result[i] = self[i] + other[i];
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ops: [Box<dyn Trait<N = 2>>; _] = [Box::new(3), Box::new([1, 1])];
|
||||
|
||||
let mut data = [16, 32];
|
||||
|
||||
for op in ops {
|
||||
data = op.process(data);
|
||||
}
|
||||
|
||||
assert_eq!(data, [49, 36]);
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// Ensure that we reject the `Self` type parameter in supertrait bounds of dyn-compatible traits
|
||||
// even if they're part of a "`Self` projection" (contrary to method signatures and the type of
|
||||
// assoc consts).
|
||||
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait: SuperTrait<{ Self::N }> {
|
||||
//~^ NOTE it uses `Self` as a type parameter
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
trait SuperTrait<const N: usize> {}
|
||||
|
||||
fn main() {
|
||||
let _: dyn Trait; //~ ERROR the trait `Trait` is not dyn compatible
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-self-const-projections-in-supertrait-bounds.rs:19:16
|
||||
|
|
||||
LL | let _: dyn Trait;
|
||||
| ^^^^^ `Trait` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/dyn-compat-self-const-projections-in-supertrait-bounds.rs:10:14
|
||||
|
|
||||
LL | trait Trait: SuperTrait<{ Self::N }> {
|
||||
| ----- ^^^^^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
|
||||
| |
|
||||
| this trait is not dyn compatible...
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
@@ -0,0 +1,28 @@
|
||||
// Ensure that we can successfully mangle & demangle trait object types w/ assoc const bindings.
|
||||
|
||||
// FIXME(mgca): Legacy mangling still crashes:
|
||||
// "finding type for [impl], encountered [crate root] with no parent"
|
||||
|
||||
//@ build-fail
|
||||
//@ revisions: v0
|
||||
//\@[legacy] compile-flags: -C symbol-mangling-version=legacy -Z unstable-options
|
||||
//@ [v0] compile-flags: -C symbol-mangling-version=v0
|
||||
//\@[legacy] normalize-stderr: "h[[:xdigit:]]{16}" -> "h[HASH]"
|
||||
//@ [v0] normalize-stderr: "sym\[.*?\]" -> "sym[HASH]"
|
||||
|
||||
#![feature(min_generic_const_args, rustc_attrs)]
|
||||
#![expect(incomplete_features)]
|
||||
#![crate_name = "sym"]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
#[rustc_symbol_name]
|
||||
//~^ ERROR symbol-name(_RMCs
|
||||
//~| ERROR demangling(<dyn sym[
|
||||
//~| ERROR demangling-alt(<dyn sym::Trait<N = 0>>)
|
||||
impl dyn Trait<N = 0> {}
|
||||
|
||||
fn main() {}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
error: symbol-name(_RMCsCRATE_HASH_3symDNtB<REF>_5Traitp1NKj0_EL_)
|
||||
--> $DIR/dyn-compat-symbol-mangling.rs:22:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(<dyn sym[HASH]::Trait<N = 0usize>>)
|
||||
--> $DIR/dyn-compat-symbol-mangling.rs:22:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling-alt(<dyn sym::Trait<N = 0>>)
|
||||
--> $DIR/dyn-compat-symbol-mangling.rs:22:1
|
||||
|
|
||||
LL | #[rustc_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Traits with type associated consts are dyn compatible. However, all associated consts must
|
||||
// be specified in the corresp. trait object type (barring exceptions) similiar to associated
|
||||
// types. Check that we reject code that doesn't provide the necessary bindings.
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const K: usize;
|
||||
}
|
||||
|
||||
// fn ctxt / body
|
||||
fn main() {
|
||||
let _: dyn Trait;
|
||||
//~^ ERROR the value of the associated constant `K` in `Trait` must be specified
|
||||
}
|
||||
|
||||
// item ctxt / signature / non-body
|
||||
struct Store(dyn Trait);
|
||||
//~^ ERROR the value of the associated constant `K` in `Trait` must be specified
|
||||
|
||||
// item ctxt & no wfcking (eager ty alias)
|
||||
type DynTrait = dyn Trait;
|
||||
//~^ ERROR the value of the associated constant `K` in `Trait` must be specified
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
error[E0191]: the value of the associated constant `K` in `Trait` must be specified
|
||||
--> $DIR/dyn-compat-unspecified-assoc-consts.rs:20:18
|
||||
|
|
||||
LL | const K: usize;
|
||||
| -------------- `K` defined here
|
||||
...
|
||||
LL | struct Store(dyn Trait);
|
||||
| ^^^^^ help: specify the associated constant: `Trait<K = /* CONST */>`
|
||||
|
||||
error[E0191]: the value of the associated constant `K` in `Trait` must be specified
|
||||
--> $DIR/dyn-compat-unspecified-assoc-consts.rs:24:21
|
||||
|
|
||||
LL | const K: usize;
|
||||
| -------------- `K` defined here
|
||||
...
|
||||
LL | type DynTrait = dyn Trait;
|
||||
| ^^^^^ help: specify the associated constant: `Trait<K = /* CONST */>`
|
||||
|
||||
error[E0191]: the value of the associated constant `K` in `Trait` must be specified
|
||||
--> $DIR/dyn-compat-unspecified-assoc-consts.rs:15:16
|
||||
|
|
||||
LL | const K: usize;
|
||||
| -------------- `K` defined here
|
||||
...
|
||||
LL | let _: dyn Trait;
|
||||
| ^^^^^ help: specify the associated constant: `Trait<K = /* CONST */>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0191`.
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait X {
|
||||
| - this trait is not dyn compatible...
|
||||
LL | type Y<const N: i16>;
|
||||
| ^ ...because it contains the generic associated type `Y`
|
||||
| ^ ...because it contains generic associated type `Y`
|
||||
= help: consider moving `Y` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -16,7 +16,7 @@ impl Bar for Foo<'_> {
|
||||
const STATIC: &str = "";
|
||||
//~^ ERROR `&` without an explicit lifetime name cannot be used here
|
||||
//~| WARN this was previously accepted by the compiler but is being phased out
|
||||
//~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
|
||||
//~| ERROR lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -39,14 +39,14 @@ help: use the `'static` lifetime
|
||||
LL | const STATIC: &'static str = "";
|
||||
| +++++++
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
|
||||
error[E0195]: lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
|
||||
--> $DIR/elided-lifetime.rs:16:17
|
||||
|
|
||||
LL | const STATIC: &str;
|
||||
| - lifetimes in impl do not match this associated const in trait
|
||||
| - lifetimes in impl do not match this associated constant in trait
|
||||
...
|
||||
LL | const STATIC: &str = "";
|
||||
| ^ lifetimes do not match associated const in trait
|
||||
| ^ lifetimes do not match associated constant in trait
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ impl Bar<'_> for A {
|
||||
const STATIC: &str = "";
|
||||
//~^ ERROR `&` without an explicit lifetime name cannot be used here
|
||||
//~| WARN this was previously accepted by the compiler but is being phased out
|
||||
//~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
|
||||
//~| ERROR lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
|
||||
}
|
||||
|
||||
struct B;
|
||||
|
||||
@@ -21,14 +21,14 @@ help: use the `'static` lifetime
|
||||
LL | const STATIC: &'static str = "";
|
||||
| +++++++
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
|
||||
error[E0195]: lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
|
||||
--> $DIR/static-trait-impl.rs:9:17
|
||||
|
|
||||
LL | const STATIC: &'a str;
|
||||
| - lifetimes in impl do not match this associated const in trait
|
||||
| - lifetimes in impl do not match this associated constant in trait
|
||||
...
|
||||
LL | const STATIC: &str = "";
|
||||
| ^ lifetimes do not match associated const in trait
|
||||
| ^ lifetimes do not match associated constant in trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type Bar
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | fn foo(_: &dyn Foo<()>) {}
|
||||
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
|
||||
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = /* Type */>`
|
||||
|
||||
error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
|
||||
--> $DIR/assoc_type_bounds.rs:11:16
|
||||
@@ -14,7 +14,7 @@ LL | type Bar
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | fn bar(_: &dyn Foo<i32>) {}
|
||||
| ^^^^^^^^ help: specify the associated type: `Foo<i32, Bar = Type>`
|
||||
| ^^^^^^^^ help: specify the associated type: `Foo<i32, Bar = /* Type */>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type Bar
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | fn foo(_: &dyn Foo<()>) {}
|
||||
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
|
||||
| ^^^^^^^ help: specify the associated type: `Foo<(), Bar = /* Type */>`
|
||||
|
||||
error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
|
||||
--> $DIR/assoc_type_bounds2.rs:11:16
|
||||
@@ -14,7 +14,7 @@ LL | type Bar
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | fn bar(_: &dyn Foo<i32>) {}
|
||||
| ^^^^^^^^ help: specify the associated type: `Foo<i32, Bar = Type>`
|
||||
| ^^^^^^^^ help: specify the associated type: `Foo<i32, Bar = /* Type */>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type Bop;
|
||||
| -------- `Bop` defined here
|
||||
...
|
||||
LL | fn foo(_: &dyn Foo) {}
|
||||
| ^^^ help: specify the associated type: `Foo<Bop = Type>`
|
||||
| ^^^ help: specify the associated type: `Foo<Bop = /* Type */>`
|
||||
|
||||
error[E0191]: the value of the associated type `Bop` in `Bar` must be specified
|
||||
--> $DIR/assoc_type_bounds_sized_others.rs:22:16
|
||||
@@ -14,7 +14,7 @@ LL | type Bop;
|
||||
| -------- `Bop` defined here
|
||||
...
|
||||
LL | fn bar(_: &dyn Bar) {}
|
||||
| ^^^ help: specify the associated type: `Bar<Bop = Type>`
|
||||
| ^^^ help: specify the associated type: `Bar<Bop = /* Type */>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error[E0038]: the trait `Bar` is not dyn compatible
|
||||
--> $DIR/associated-consts.rs:8:31
|
||||
--> $DIR/associated-consts.rs:8:35
|
||||
|
|
||||
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
| ^^^^^^^ `Bar` is not dyn compatible
|
||||
| ^^^ `Bar` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Bar {
|
||||
| --- this trait is not dyn compatible...
|
||||
LL | const X: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
| ^ ...because it contains associated const `X`
|
||||
= help: consider moving `X` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -7,11 +7,11 @@ LL | trait A<C = <Self as D>::E> {}
|
||||
LL | let B: &dyn A = &();
|
||||
| ^
|
||||
|
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the trait object type
|
||||
help: explicitly specify the type parameter
|
||||
|
|
||||
LL | let B: &dyn A<C> = &();
|
||||
| +++
|
||||
LL | let B: &dyn A</* C */> = &();
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Super {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | type Assoc<'a>;
|
||||
| ^^^^^ ...because it contains the generic associated type `Assoc`
|
||||
| ^^^^^ ...because it contains generic associated type `Assoc`
|
||||
= help: consider moving `Assoc` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Foo {
|
||||
| --- this trait is not dyn compatible...
|
||||
LL | type Bar<T>;
|
||||
| ^^^ ...because it contains the generic associated type `Bar`
|
||||
| ^^^ ...because it contains generic associated type `Bar`
|
||||
= help: consider moving `Bar` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Tr {
|
||||
| -- this trait is not dyn compatible...
|
||||
LL | const N: usize;
|
||||
| ^ ...because it contains this associated `const`
|
||||
| ^ ...because it contains associated const `N`
|
||||
= help: consider moving `N` to another trait
|
||||
= help: only type `u8` implements `Tr`; consider using it directly instead.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type Assoc: Default;
|
||||
| ------------------- `Assoc` defined here
|
||||
...
|
||||
LL | let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
|
||||
| ^^^^^^^^^^^^^ help: specify the associated type: `Dyn<i32, u32, Assoc = Type>`
|
||||
| ^^^^^^^^^^^^^ help: specify the associated type: `Dyn<i32, u32, Assoc = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
--> $DIR/supertrait-mentions-GAT.rs:4:10
|
||||
|
|
||||
LL | type Gat<'a>
|
||||
| ^^^ ...because it contains the generic associated type `Gat`
|
||||
| ^^^ ...because it contains generic associated type `Gat`
|
||||
...
|
||||
LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
|
||||
| ---------- this trait is not dyn compatible...
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#![feature(trait_alias)]
|
||||
trait B = Fn() -> Self;
|
||||
type D = &'static dyn B;
|
||||
//~^ ERROR E0411
|
||||
|
||||
fn a() -> D {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
_ = a();
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
error[E0411]: `Self` is not allowed in type aliases
|
||||
--> $DIR/trait-alias-self-projection.rs:3:19
|
||||
|
|
||||
LL | type D = &'static dyn B;
|
||||
| ^^^^^ `Self` is only available in impls, traits, and concrete type definitions
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0411`.
|
||||
@@ -0,0 +1,18 @@
|
||||
// Check that we reject type projections behind trait aliases that mention `Self`.
|
||||
//
|
||||
// The author of the trait object type can't fix this unlike the supertrait bound
|
||||
// equivalent where they just need to explicitly specify the assoc type.
|
||||
|
||||
// issue: <https://github.com/rust-lang/rust/issues/139082>
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait F = Fn() -> Self;
|
||||
|
||||
trait G = H<T = Self>;
|
||||
trait H { type T: ?Sized; }
|
||||
|
||||
fn main() {
|
||||
let _: dyn F; //~ ERROR associated type binding in trait object type mentions `Self`
|
||||
let _: dyn G; //~ ERROR associated type binding in trait object type mentions `Self`
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
error: associated type binding in trait object type mentions `Self`
|
||||
--> $DIR/type-projection-behind-trait-alias-mentions-self.rs:16:12
|
||||
|
|
||||
LL | trait F = Fn() -> Self;
|
||||
| ---- this binding mentions `Self`
|
||||
...
|
||||
LL | let _: dyn F;
|
||||
| ^^^^^ contains a mention of `Self`
|
||||
|
||||
error: associated type binding in trait object type mentions `Self`
|
||||
--> $DIR/type-projection-behind-trait-alias-mentions-self.rs:17:12
|
||||
|
|
||||
LL | trait G = H<T = Self>;
|
||||
| -------- this binding mentions `Self`
|
||||
...
|
||||
LL | let _: dyn G;
|
||||
| ^^^^^ contains a mention of `Self`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type Bar;
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | type Foo = dyn Trait;
|
||||
| ^^^^^ help: specify the associated type: `Trait<Bar = Type>`
|
||||
| ^^^^^ help: specify the associated type: `Trait<Bar = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ LL | type Bar;
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | type Foo = dyn Trait<F=i32>;
|
||||
| ^^^^^^^^^^^^ help: specify the associated type: `Trait<F=i32, Bar = Type>`
|
||||
| ^^^^^^^^^^^^ help: specify the associated type: `Trait<F=i32, Bar = /* Type */>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ LL |
|
||||
LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {}
|
||||
| ^
|
||||
|
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the trait object type
|
||||
help: explicitly specify the type parameter
|
||||
|
|
||||
LL | fn together_we_will_rule_the_galaxy(son: &dyn A<T>) {}
|
||||
| +++
|
||||
LL | fn together_we_will_rule_the_galaxy(son: &dyn A</* T */>) {}
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be spec
|
||||
--> $DIR/dynless-turbofish-e0191-issue-91997.rs:5:13
|
||||
|
|
||||
LL | let _ = MyIterator::next;
|
||||
| ^^^^^^^^^^ help: specify the associated type: `MyIterator::<Item = Type>`
|
||||
| ^^^^^^^^^^ help: specify the associated type: `MyIterator::<Item = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Foo {
|
||||
| --- this trait is not dyn compatible...
|
||||
LL | type A<'a> where Self: 'a;
|
||||
| ^ ...because it contains the generic associated type `A`
|
||||
| ^ ...because it contains generic associated type `A`
|
||||
= help: consider moving `A` to another trait
|
||||
|
||||
error[E0038]: the trait `Foo` is not dyn compatible
|
||||
@@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait Foo {
|
||||
| --- this trait is not dyn compatible...
|
||||
LL | type A<'a> where Self: 'a;
|
||||
| ^ ...because it contains the generic associated type `A`
|
||||
| ^ ...because it contains generic associated type `A`
|
||||
= help: consider moving `A` to another trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait X {
|
||||
| - this trait is not dyn compatible...
|
||||
LL | type Y<'a>;
|
||||
| ^ ...because it contains the generic associated type `Y`
|
||||
| ^ ...because it contains generic associated type `Y`
|
||||
= help: consider moving `Y` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | pub trait SuperTrait {
|
||||
| ---------- this trait is not dyn compatible...
|
||||
LL | type SubType<'a>: SubTrait where Self: 'a;
|
||||
| ^^^^^^^ ...because it contains the generic associated type `SubType`
|
||||
| ^^^^^^^ ...because it contains generic associated type `SubType`
|
||||
= help: consider moving `SubType` to another trait
|
||||
= help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead.
|
||||
= note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
|
||||
|
||||
@@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait CollectionFamily {
|
||||
| ---------------- this trait is not dyn compatible...
|
||||
LL | type Member<T>;
|
||||
| ^^^^^^ ...because it contains the generic associated type `Member`
|
||||
| ^^^^^^ ...because it contains generic associated type `Member`
|
||||
= help: consider moving `Member` to another trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait MapLike<K, V> {
|
||||
| ------- this trait is not dyn compatible...
|
||||
LL | type VRefCont<'a>: RefCont<'a, V>
|
||||
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
|
||||
| ^^^^^^^^ ...because it contains generic associated type `VRefCont`
|
||||
= help: consider moving `VRefCont` to another trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
LL | trait StreamingIterator {
|
||||
| ----------------- this trait is not dyn compatible...
|
||||
LL | type Item<'a> where Self: 'a;
|
||||
| ^^^^ ...because it contains the generic associated type `Item`
|
||||
| ^^^^ ...because it contains generic associated type `Item`
|
||||
= help: consider moving `Item` to another trait
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -14,7 +14,7 @@ impl Trait for () {
|
||||
//~| ERROR mismatched types
|
||||
const Q = "";
|
||||
//~^ ERROR missing type for `const` item
|
||||
//~| ERROR lifetime parameters or bounds on associated const `Q` do not match the trait declaration
|
||||
//~| ERROR lifetime parameters or bounds on associated constant `Q` do not match the trait declaration
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -15,14 +15,14 @@ error: missing type for `const` item
|
||||
LL | const K<T> = ();
|
||||
| ^ help: provide a type for the associated constant: `()`
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on associated const `Q` do not match the trait declaration
|
||||
error[E0195]: lifetime parameters or bounds on associated constant `Q` do not match the trait declaration
|
||||
--> $DIR/assoc-const-missing-type.rs:15:12
|
||||
|
|
||||
LL | const Q<'a>: &'a str;
|
||||
| ---- lifetimes in impl do not match this associated const in trait
|
||||
| ---- lifetimes in impl do not match this associated constant in trait
|
||||
...
|
||||
LL | const Q = "";
|
||||
| ^ lifetimes do not match associated const in trait
|
||||
| ^ lifetimes do not match associated constant in trait
|
||||
|
||||
error: missing type for `const` item
|
||||
--> $DIR/assoc-const-missing-type.rs:15:12
|
||||
|
||||
@@ -14,15 +14,15 @@ trait Trait<P> {
|
||||
|
||||
impl<P> Trait<P> for () {
|
||||
const A<T>: () = ();
|
||||
//~^ ERROR const `A` has 1 type parameter but its trait declaration has 0 type parameters
|
||||
//~^ ERROR constant `A` has 1 type parameter but its trait declaration has 0 type parameters
|
||||
const B<const K: u64>: u64 = 0;
|
||||
//~^ ERROR const `B` has 1 const parameter but its trait declaration has 2 const parameters
|
||||
//~^ ERROR constant `B` has 1 const parameter but its trait declaration has 2 const parameters
|
||||
const C<'a>: &'a str = "";
|
||||
//~^ ERROR const `C` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
//~^ ERROR constant `C` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
const D<const N: u16>: u16 = N;
|
||||
//~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
|
||||
//~^ ERROR constant `D` has an incompatible generic parameter for trait `Trait`
|
||||
const E: &'static () = &();
|
||||
//~^ ERROR lifetime parameters or bounds on associated const `E` do not match the trait declaration
|
||||
//~^ ERROR lifetime parameters or bounds on associated constant `E` do not match the trait declaration
|
||||
|
||||
const F: usize = 1024
|
||||
where
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
error[E0049]: associated const `A` has 1 type parameter but its trait declaration has 0 type parameters
|
||||
error[E0049]: associated constant `A` has 1 type parameter but its trait declaration has 0 type parameters
|
||||
--> $DIR/compare-impl-item.rs:16:13
|
||||
|
|
||||
LL | const A: ();
|
||||
@@ -7,7 +7,7 @@ LL | const A: ();
|
||||
LL | const A<T>: () = ();
|
||||
| ^ found 1 type parameter
|
||||
|
||||
error[E0049]: associated const `B` has 1 const parameter but its trait declaration has 2 const parameters
|
||||
error[E0049]: associated constant `B` has 1 const parameter but its trait declaration has 2 const parameters
|
||||
--> $DIR/compare-impl-item.rs:18:13
|
||||
|
|
||||
LL | const B<const K: u64, const Q: u64>: u64;
|
||||
@@ -18,7 +18,7 @@ LL | const B<const K: u64, const Q: u64>: u64;
|
||||
LL | const B<const K: u64>: u64 = 0;
|
||||
| ^^^^^^^^^^^^ found 1 const parameter
|
||||
|
||||
error[E0049]: associated const `C` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
error[E0049]: associated constant `C` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
--> $DIR/compare-impl-item.rs:20:13
|
||||
|
|
||||
LL | const C<T>: T;
|
||||
@@ -27,7 +27,7 @@ LL | const C<T>: T;
|
||||
LL | const C<'a>: &'a str = "";
|
||||
| ^^ found 0 type parameters
|
||||
|
||||
error[E0053]: associated const `D` has an incompatible generic parameter for trait `Trait`
|
||||
error[E0053]: associated constant `D` has an incompatible generic parameter for trait `Trait`
|
||||
--> $DIR/compare-impl-item.rs:22:13
|
||||
|
|
||||
LL | trait Trait<P> {
|
||||
@@ -42,14 +42,14 @@ LL | impl<P> Trait<P> for () {
|
||||
LL | const D<const N: u16>: u16 = N;
|
||||
| ^^^^^^^^^^^^ found const parameter of type `u16`
|
||||
|
||||
error[E0195]: lifetime parameters or bounds on associated const `E` do not match the trait declaration
|
||||
error[E0195]: lifetime parameters or bounds on associated constant `E` do not match the trait declaration
|
||||
--> $DIR/compare-impl-item.rs:24:12
|
||||
|
|
||||
LL | const E<'a>: &'a ();
|
||||
| ---- lifetimes in impl do not match this associated const in trait
|
||||
| ---- lifetimes in impl do not match this associated constant in trait
|
||||
...
|
||||
LL | const E: &'static () = &();
|
||||
| ^ lifetimes do not match associated const in trait
|
||||
| ^ lifetimes do not match associated constant in trait
|
||||
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/compare-impl-item.rs:29:12
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type Bar;
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | impl Foo for Box<dyn Foo> {
|
||||
| ^^^ help: specify the associated type: `Foo<Bar = Type>`
|
||||
| ^^^ help: specify the associated type: `Foo<Bar = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LL | type A;
|
||||
| ------ `A` defined here
|
||||
...
|
||||
LL | fn bar(x: &dyn Foo) {}
|
||||
| ^^^ help: specify the associated type: `Foo<A = Type>`
|
||||
| ^^^ help: specify the associated type: `Foo<A = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ LL |
|
||||
LL | fn f(a: &dyn A) {}
|
||||
| ^
|
||||
|
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the trait object type
|
||||
help: explicitly specify the type parameter
|
||||
|
|
||||
LL | fn f(a: &dyn A<T>) {}
|
||||
| +++
|
||||
LL | fn f(a: &dyn A</* T */>) {}
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be s
|
||||
--> $DIR/issue-28344.rs:5:17
|
||||
|
|
||||
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
|
||||
| ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>`
|
||||
| ^^^^^^ help: specify the associated type: `BitXor::<Output = /* Type */>`
|
||||
|
||||
warning: trait objects without an explicit `dyn` are deprecated
|
||||
--> $DIR/issue-28344.rs:10:13
|
||||
@@ -35,7 +35,7 @@ error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be s
|
||||
--> $DIR/issue-28344.rs:10:13
|
||||
|
|
||||
LL | let g = BitXor::bitor;
|
||||
| ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>`
|
||||
| ^^^^^^ help: specify the associated type: `BitXor::<Output = /* Type */>`
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be spec
|
||||
--> $DIR/trait-hidden-method.rs:4:33
|
||||
|
|
||||
LL | Box::new(1..=10) as Box<dyn Iterator>
|
||||
| ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`
|
||||
| ^^^^^^^^ help: specify the associated type: `Iterator<Item = /* Type */>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user