Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0421608

Browse files
committedJan 24, 2024
On E0277 be clearer about implicit Sized bounds on type params and assoc types
``` error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> f100.rs:2:33 | 2 | let _ = std::mem::size_of::<[i32]>(); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` note: required by an implicit `Sized` bound in `std::mem::size_of` --> /home/gh-estebank/rust/library/core/src/mem/mod.rs:312:22 | 312 | pub const fn size_of<T>() -> usize { | ^ required by the implicit `Sized` requirement on this bound in `size_of` ``` Fix #120178.
1 parent 0b77301 commit 0421608

File tree

48 files changed

+231
-222
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+231
-222
lines changed
 

‎compiler/rustc_hir_analysis/src/astconv/bounds.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
2828
let tcx = self.tcx();
2929
let sized_def_id = tcx.lang_items().sized_trait();
3030
let mut seen_negative_sized_bound = false;
31+
let mut seen_positive_sized_bound = false;
3132

3233
// Try to find an unbound in bounds.
3334
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
@@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
4546
seen_negative_sized_bound = true;
4647
}
4748
}
49+
hir::TraitBoundModifier::None => {
50+
if let Some(sized_def_id) = sized_def_id
51+
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
52+
{
53+
seen_positive_sized_bound = true;
54+
}
55+
}
4856
_ => {}
4957
}
5058
}
@@ -82,8 +90,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
8290
);
8391
}
8492

85-
if seen_sized_unbound || seen_negative_sized_bound {
86-
// There was in fact a `?Sized` or `!Sized` bound;
93+
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
94+
// There was in fact a `?Sized`, `!Sized` or `Sized` bound;
8795
// we don't need to do anything.
8896
} else if sized_def_id.is_some() {
8997
// There was no `?Sized` or `!Sized` bound;

‎compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+90-69
Original file line numberDiff line numberDiff line change
@@ -3011,35 +3011,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30113011
);
30123012
}
30133013
}
3014-
let descr = format!("required by a bound in `{item_name}`");
3015-
if span.is_visible(sm) {
3016-
let msg = format!("required by this bound in `{short_item_name}`");
3017-
multispan.push_span_label(span, msg);
3018-
err.span_note(multispan, descr);
3019-
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
3020-
&& let ty::ClauseKind::Trait(trait_pred) = clause
3021-
{
3022-
let def_id = trait_pred.def_id();
3023-
let visible_item = if let Some(local) = def_id.as_local() {
3024-
// Check for local traits being reachable.
3025-
let vis = &self.tcx.resolutions(()).effective_visibilities;
3026-
// Account for non-`pub` traits in the root of the local crate.
3027-
let is_locally_reachable = self.tcx.parent(def_id).is_crate_root();
3028-
vis.is_reachable(local) || is_locally_reachable
3029-
} else {
3030-
// Check for foreign traits being reachable.
3031-
self.tcx.visible_parent_map(()).get(&def_id).is_some()
3032-
};
3033-
if Some(def_id) == self.tcx.lang_items().sized_trait()
3034-
&& let Some(hir::Node::TraitItem(hir::TraitItem {
3035-
ident,
3036-
kind: hir::TraitItemKind::Type(bounds, None),
3037-
..
3038-
})) = tcx.hir().get_if_local(item_def_id)
3039-
// Do not suggest relaxing if there is an explicit `Sized` obligation.
3040-
&& !bounds.iter()
3041-
.filter_map(|bound| bound.trait_ref())
3042-
.any(|tr| tr.trait_def_id() == self.tcx.lang_items().sized_trait())
3014+
let mut a = "a";
3015+
let mut this = "this";
3016+
let mut note = None;
3017+
let mut help = None;
3018+
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
3019+
&& let ty::ClauseKind::Trait(trait_pred) = clause
3020+
{
3021+
let def_id = trait_pred.def_id();
3022+
let visible_item = if let Some(local) = def_id.as_local() {
3023+
// Check for local traits being reachable.
3024+
let vis = &self.tcx.resolutions(()).effective_visibilities;
3025+
// Account for non-`pub` traits in the root of the local crate.
3026+
let is_locally_reachable = self.tcx.parent(def_id).is_crate_root();
3027+
vis.is_reachable(local) || is_locally_reachable
3028+
} else {
3029+
// Check for foreign traits being reachable.
3030+
self.tcx.visible_parent_map(()).get(&def_id).is_some()
3031+
};
3032+
if Some(def_id) == self.tcx.lang_items().sized_trait() {
3033+
// Check if this is an implicit bound, even in foreign crates.
3034+
if tcx
3035+
.generics_of(item_def_id)
3036+
.params
3037+
.iter()
3038+
.any(|param| tcx.def_span(param.def_id) == span)
3039+
{
3040+
a = "an implicit `Sized`";
3041+
this = "the implicit `Sized` requirement on this";
3042+
}
3043+
if let Some(hir::Node::TraitItem(hir::TraitItem {
3044+
ident,
3045+
kind: hir::TraitItemKind::Type(bounds, None),
3046+
..
3047+
})) = tcx.hir().get_if_local(item_def_id)
3048+
// Do not suggest relaxing if there is an explicit `Sized` obligation.
3049+
&& !bounds.iter()
3050+
.filter_map(|bound| bound.trait_ref())
3051+
.any(|tr| tr.trait_def_id() == self.tcx.lang_items().sized_trait())
30433052
{
30443053
let (span, separator) = if let [.., last] = bounds {
30453054
(last.span().shrink_to_hi(), " +")
@@ -3053,52 +3062,64 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
30533062
Applicability::MachineApplicable,
30543063
);
30553064
}
3056-
if let DefKind::Trait = tcx.def_kind(item_def_id)
3057-
&& !visible_item
3058-
{
3059-
err.note(format!(
3060-
"`{short_item_name}` is a \"sealed trait\", because to implement \
3061-
it you also need to implement `{}`, which is not accessible; \
3062-
this is usually done to force you to use one of the provided \
3063-
types that already implement it",
3064-
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
3065-
));
3066-
let impls_of = tcx.trait_impls_of(def_id);
3067-
let impls = impls_of
3068-
.non_blanket_impls()
3069-
.values()
3070-
.flatten()
3071-
.chain(impls_of.blanket_impls().iter())
3065+
}
3066+
if let DefKind::Trait = tcx.def_kind(item_def_id)
3067+
&& !visible_item
3068+
{
3069+
note = Some(format!(
3070+
"`{short_item_name}` is a \"sealed trait\", because to implement it \
3071+
you also need to implement `{}`, which is not accessible; this is \
3072+
usually done to force you to use one of the provided types that \
3073+
already implement it",
3074+
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
3075+
));
3076+
let impls_of = tcx.trait_impls_of(def_id);
3077+
let impls = impls_of
3078+
.non_blanket_impls()
3079+
.values()
3080+
.flatten()
3081+
.chain(impls_of.blanket_impls().iter())
3082+
.collect::<Vec<_>>();
3083+
if !impls.is_empty() {
3084+
let len = impls.len();
3085+
let mut types = impls
3086+
.iter()
3087+
.map(|t| {
3088+
with_no_trimmed_paths!(format!(
3089+
" {}",
3090+
tcx.type_of(*t).instantiate_identity(),
3091+
))
3092+
})
30723093
.collect::<Vec<_>>();
3073-
if !impls.is_empty() {
3074-
let len = impls.len();
3075-
let mut types = impls
3076-
.iter()
3077-
.map(|t| {
3078-
with_no_trimmed_paths!(format!(
3079-
" {}",
3080-
tcx.type_of(*t).instantiate_identity(),
3081-
))
3082-
})
3083-
.collect::<Vec<_>>();
3084-
let post = if types.len() > 9 {
3085-
types.truncate(8);
3086-
format!("\nand {} others", len - 8)
3087-
} else {
3088-
String::new()
3089-
};
3090-
err.help(format!(
3091-
"the following type{} implement{} the trait:\n{}{post}",
3092-
pluralize!(len),
3093-
if len == 1 { "s" } else { "" },
3094-
types.join("\n"),
3095-
));
3096-
}
3094+
let post = if types.len() > 9 {
3095+
types.truncate(8);
3096+
format!("\nand {} others", len - 8)
3097+
} else {
3098+
String::new()
3099+
};
3100+
help = Some(format!(
3101+
"the following type{} implement{} the trait:\n{}{post}",
3102+
pluralize!(len),
3103+
if len == 1 { "s" } else { "" },
3104+
types.join("\n"),
3105+
));
30973106
}
30983107
}
3108+
};
3109+
let descr = format!("required by {a} bound in `{item_name}`");
3110+
if span.is_visible(sm) {
3111+
let msg = format!("required by {this} bound in `{short_item_name}`");
3112+
multispan.push_span_label(span, msg);
3113+
err.span_note(multispan, descr);
30993114
} else {
31003115
err.span_note(tcx.def_span(item_def_id), descr);
31013116
}
3117+
if let Some(note) = note {
3118+
err.note(note);
3119+
}
3120+
if let Some(help) = help {
3121+
err.help(help);
3122+
}
31023123
}
31033124
ObligationCauseCode::Coercion { source, target } => {
31043125
let mut file = None;

0 commit comments

Comments
 (0)
Please sign in to comment.