Skip to content

Commit

Permalink
Rollup merge of rust-lang#120323 - estebank:issue-120178, r=fmease
Browse files Browse the repository at this point in the history
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 rust-lang#120178.
  • Loading branch information
Nadrieril authored Jan 31, 2024
2 parents 3adfa80 + 43fdb12 commit 384a303
Show file tree
Hide file tree
Showing 51 changed files with 238 additions and 229 deletions.
14 changes: 11 additions & 3 deletions compiler/rustc_hir_analysis/src/astconv/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
let tcx = self.tcx();
let sized_def_id = tcx.lang_items().sized_trait();
let mut seen_negative_sized_bound = false;
let mut seen_positive_sized_bound = false;

// Try to find an unbound in bounds.
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
Expand All @@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
seen_negative_sized_bound = true;
}
}
hir::TraitBoundModifier::None => {
if let Some(sized_def_id) = sized_def_id
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
{
seen_positive_sized_bound = true;
}
}
_ => {}
}
}
Expand Down Expand Up @@ -82,11 +90,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
);
}

if seen_sized_unbound || seen_negative_sized_bound {
// There was in fact a `?Sized` or `!Sized` bound;
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
// we don't need to do anything.
} else if sized_def_id.is_some() {
// There was no `?Sized` or `!Sized` bound;
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
// add `Sized` if it's available.
bounds.push_sized(tcx, self_ty, span);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3011,35 +3011,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}
}
let descr = format!("required by a bound in `{item_name}`");
if span.is_visible(sm) {
let msg = format!("required by this bound in `{short_item_name}`");
multispan.push_span_label(span, msg);
err.span_note(multispan, descr);
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
&& let ty::ClauseKind::Trait(trait_pred) = clause
{
let def_id = trait_pred.def_id();
let visible_item = if let Some(local) = def_id.as_local() {
// Check for local traits being reachable.
let vis = &tcx.resolutions(()).effective_visibilities;
// Account for non-`pub` traits in the root of the local crate.
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
vis.is_reachable(local) || is_locally_reachable
} else {
// Check for foreign traits being reachable.
tcx.visible_parent_map(()).get(&def_id).is_some()
};
if Some(def_id) == tcx.lang_items().sized_trait()
&& let Some(hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Type(bounds, None),
..
})) = tcx.hir().get_if_local(item_def_id)
// Do not suggest relaxing if there is an explicit `Sized` obligation.
&& !bounds.iter()
.filter_map(|bound| bound.trait_ref())
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
let mut a = "a";
let mut this = "this bound";
let mut note = None;
let mut help = None;
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
&& let ty::ClauseKind::Trait(trait_pred) = clause
{
let def_id = trait_pred.def_id();
let visible_item = if let Some(local) = def_id.as_local() {
// Check for local traits being reachable.
let vis = &tcx.resolutions(()).effective_visibilities;
// Account for non-`pub` traits in the root of the local crate.
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
vis.is_reachable(local) || is_locally_reachable
} else {
// Check for foreign traits being reachable.
tcx.visible_parent_map(()).get(&def_id).is_some()
};
if Some(def_id) == tcx.lang_items().sized_trait() {
// Check if this is an implicit bound, even in foreign crates.
if tcx
.generics_of(item_def_id)
.params
.iter()
.any(|param| tcx.def_span(param.def_id) == span)
{
a = "an implicit `Sized`";
this = "the implicit `Sized` requirement on this type parameter";
}
if let Some(hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Type(bounds, None),
..
})) = tcx.hir().get_if_local(item_def_id)
// Do not suggest relaxing if there is an explicit `Sized` obligation.
&& !bounds.iter()
.filter_map(|bound| bound.trait_ref())
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
{
let (span, separator) = if let [.., last] = bounds {
(last.span().shrink_to_hi(), " +")
Expand All @@ -3053,52 +3062,64 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
Applicability::MachineApplicable,
);
}
if let DefKind::Trait = tcx.def_kind(item_def_id)
&& !visible_item
{
err.note(format!(
"`{short_item_name}` is a \"sealed trait\", because to implement \
it you also need to implement `{}`, which is not accessible; \
this is usually done to force you to use one of the provided \
types that already implement it",
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
));
let impls_of = tcx.trait_impls_of(def_id);
let impls = impls_of
.non_blanket_impls()
.values()
.flatten()
.chain(impls_of.blanket_impls().iter())
}
if let DefKind::Trait = tcx.def_kind(item_def_id)
&& !visible_item
{
note = Some(format!(
"`{short_item_name}` is a \"sealed trait\", because to implement it \
you also need to implement `{}`, which is not accessible; this is \
usually done to force you to use one of the provided types that \
already implement it",
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
));
let impls_of = tcx.trait_impls_of(def_id);
let impls = impls_of
.non_blanket_impls()
.values()
.flatten()
.chain(impls_of.blanket_impls().iter())
.collect::<Vec<_>>();
if !impls.is_empty() {
let len = impls.len();
let mut types = impls
.iter()
.map(|t| {
with_no_trimmed_paths!(format!(
" {}",
tcx.type_of(*t).instantiate_identity(),
))
})
.collect::<Vec<_>>();
if !impls.is_empty() {
let len = impls.len();
let mut types = impls
.iter()
.map(|t| {
with_no_trimmed_paths!(format!(
" {}",
tcx.type_of(*t).instantiate_identity(),
))
})
.collect::<Vec<_>>();
let post = if types.len() > 9 {
types.truncate(8);
format!("\nand {} others", len - 8)
} else {
String::new()
};
err.help(format!(
"the following type{} implement{} the trait:\n{}{post}",
pluralize!(len),
if len == 1 { "s" } else { "" },
types.join("\n"),
));
}
let post = if types.len() > 9 {
types.truncate(8);
format!("\nand {} others", len - 8)
} else {
String::new()
};
help = Some(format!(
"the following type{} implement{} the trait:\n{}{post}",
pluralize!(len),
if len == 1 { "s" } else { "" },
types.join("\n"),
));
}
}
};
let descr = format!("required by {a} bound in `{item_name}`");
if span.is_visible(sm) {
let msg = format!("required by {this} in `{short_item_name}`");
multispan.push_span_label(span, msg);
err.span_note(multispan, descr);
} else {
err.span_note(tcx.def_span(item_def_id), descr);
}
if let Some(note) = note {
err.note(note);
}
if let Some(help) = help {
err.help(help);
}
}
ObligationCauseCode::Coercion { source, target } => {
let mut file = None;
Expand Down
4 changes: 2 additions & 2 deletions tests/incremental/hashes/trait_defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,10 +559,10 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
#[rustc_clean(cfg="cfail5")]
#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
#[rustc_clean(cfg="cfail6")]
trait TraitAddBuiltinBoundToMethodTypeParameter {
#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")]
#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")]
#[rustc_clean(cfg="cfail6")]
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/associated-types/defaults-wf.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | type Ty = Vec<[u8]>;
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Vec`
note: required by an implicit `Sized` bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL

error: aborting due to 1 previous error
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/issue-20005.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
LL | ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required by a bound in `From`
note: required by an implicit `Sized` bound in `From`
--> $DIR/issue-20005.rs:1:12
|
LL | trait From<Src> {
| ^^^ required by this bound in `From`
| ^^^ required by the implicit `Sized` requirement on this type parameter in `From`
help: consider further restricting `Self`
|
LL | ) -> <Dst as From<Self>>::Result where Dst: From<Self>, Self: Sized {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required by a bound in `Add`
note: required by an implicit `Sized` bound in `Add`
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: consider further restricting `Self`
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/closures/issue-111932.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ LL | println!("{:?}", foo);
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Foo`
note: required by a bound in `core::fmt::rt::Argument::<'a>::new_debug`
note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'a>::new_debug`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/coroutine/sized-yield.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ LL | Pin::new(&mut gen).resume(());
| ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `CoroutineState`
note: required by an implicit `Sized` bound in `CoroutineState`
--> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL

error: aborting due to 2 previous errors
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/dst/dst-sized-trait-param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ LL | impl Foo<[isize]> for usize { }
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[isize]`
note: required by a bound in `Foo`
note: required by an implicit `Sized` bound in `Foo`
--> $DIR/dst-sized-trait-param.rs:5:11
|
LL | trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
| ^ required by this bound in `Foo`
| ^ required by the implicit `Sized` requirement on this type parameter in `Foo`
help: consider relaxing the implicit `Sized` restriction
|
LL | trait Foo<T: ?Sized> : Sized { fn take(self, x: &T) { } } // Note: T is sized
Expand Down
16 changes: 8 additions & 8 deletions tests/ui/extern/extern-types-unsized.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ LL | assert_sized::<A>();
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `A`
note: required by a bound in `assert_sized`
note: required by an implicit `Sized` bound in `assert_sized`
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
| ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
Expand All @@ -27,11 +27,11 @@ note: required because it appears within the type `Foo`
|
LL | struct Foo {
| ^^^
note: required by a bound in `assert_sized`
note: required by an implicit `Sized` bound in `assert_sized`
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
| ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
Expand All @@ -49,11 +49,11 @@ note: required because it appears within the type `Bar<A>`
|
LL | struct Bar<T: ?Sized> {
| ^^^
note: required by a bound in `assert_sized`
note: required by an implicit `Sized` bound in `assert_sized`
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
| ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
Expand All @@ -71,11 +71,11 @@ note: required because it appears within the type `Bar<A>`
|
LL | struct Bar<T: ?Sized> {
| ^^^
note: required by a bound in `assert_sized`
note: required by an implicit `Sized` bound in `assert_sized`
--> $DIR/extern-types-unsized.rs:19:17
|
LL | fn assert_sized<T>() {}
| ^ required by this bound in `assert_sized`
| ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn assert_sized<T: ?Sized>() {}
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/generic-associated-types/issue-88287.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ LL | type SearchFutureTy<'f, A, B: 'f>
LL | async move { todo!() }
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required by a bound in `<T as SearchableResourceExt<Criteria>>`
note: required by an implicit `Sized` bound in `<T as SearchableResourceExt<Criteria>>`
--> $DIR/issue-88287.rs:24:6
|
LL | impl<T, Criteria> SearchableResourceExt<Criteria> for T
| ^ required by this bound in `<T as SearchableResourceExt<Criteria>>`
| ^ required by the implicit `Sized` requirement on this type parameter in `<T as SearchableResourceExt<Criteria>>`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - A: SearchableResource<B> + ?Sized + 'f,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ LL | impl Tsized for () {}
|
= help: the trait `Sized` is not implemented for `[()]`
note: required by a bound in `Tsized`
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:17
|
LL | trait Tsized<P: Sized = [Self]> {}
| ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized`
| ^^^^^ required by this bound in `Tsized`

error: aborting due to 1 previous error

Expand Down
Loading

0 comments on commit 384a303

Please sign in to comment.