Skip to content

Commit c0d717f

Browse files
w
1 parent de4f805 commit c0d717f

File tree

73 files changed

+1043
-92
lines changed

Some content is hidden

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

73 files changed

+1043
-92
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,12 @@ fn check_trait_item<'tcx>(
391391
// Check that an item definition in a subtrait is shadowing a supertrait item.
392392
lint_item_shadowing_supertrait_item(tcx, def_id);
393393

394+
for blanket_impl_def_id in tcx.all_impls(def_id.to_def_id()) {
395+
if !blanket_impl_def_id.is_local() {
396+
tcx.ensure_ok().lint_object_blanket_impl((blanket_impl_def_id, def_id.to_def_id()));
397+
}
398+
}
399+
394400
let mut res = check_associated_item(tcx, def_id, span, method_sig);
395401

396402
if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {

compiler/rustc_hir_analysis/src/impl_wf_check.rs

Lines changed: 144 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,23 @@
1010
1111
use std::assert_matches::debug_assert_matches;
1212

13-
use min_specialization::check_min_specialization;
13+
use itertools::Itertools;
1414
use rustc_data_structures::fx::FxHashSet;
1515
use rustc_errors::codes::*;
1616
use rustc_hir::def::DefKind;
17-
use rustc_hir::def_id::LocalDefId;
18-
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
19-
use rustc_span::ErrorGuaranteed;
17+
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
18+
use rustc_infer::infer::TyCtxtInferExt;
19+
use rustc_lint_defs::builtin::DYN_OVERLAP;
20+
use rustc_middle::ty::{
21+
self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast,
22+
elaborate,
23+
};
24+
use rustc_span::{DUMMY_SP, ErrorGuaranteed, sym};
25+
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
2026

2127
use crate::constrained_generic_params as cgp;
2228
use crate::errors::UnconstrainedGenericParameter;
29+
use crate::impl_wf_check::min_specialization::check_min_specialization;
2330

2431
mod min_specialization;
2532

@@ -68,6 +75,22 @@ pub(crate) fn check_impl_wf(
6875
if tcx.features().min_specialization() {
6976
res = res.and(check_min_specialization(tcx, impl_def_id));
7077
}
78+
79+
if let Some(trait_def_id) = tcx.trait_id_of_impl(impl_def_id.to_def_id()) {
80+
for &subtrait_def_id in tcx
81+
.crates(())
82+
.into_iter()
83+
.copied()
84+
.chain([LOCAL_CRATE])
85+
.flat_map(|cnum| tcx.traits(cnum))
86+
{
87+
if ty::elaborate::supertrait_def_ids(tcx, subtrait_def_id).contains(&trait_def_id) {
88+
tcx.ensure_ok()
89+
.lint_object_blanket_impl((impl_def_id.to_def_id(), subtrait_def_id));
90+
}
91+
}
92+
}
93+
7194
res
7295
}
7396

@@ -234,3 +257,120 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
234257
}
235258
res
236259
}
260+
261+
pub(crate) fn lint_object_blanket_impl<'tcx>(
262+
tcx: TyCtxt<'tcx>,
263+
(impl_def_id, trait_def_id): (DefId, DefId),
264+
) {
265+
if tcx.is_diagnostic_item(sym::Any, trait_def_id) {
266+
return;
267+
}
268+
269+
if !tcx.is_dyn_compatible(trait_def_id) {
270+
return;
271+
}
272+
273+
let infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(TypingMode::CheckObjectOverlap);
274+
275+
let principal_trait_args = infcx.fresh_args_for_item(DUMMY_SP, trait_def_id);
276+
let principal_trait = ty::TraitRef::new_from_args(tcx, trait_def_id, principal_trait_args);
277+
278+
let mut needed_associated_types = vec![];
279+
let clause: ty::Clause<'tcx> = ty::TraitRef::identity(tcx, trait_def_id).upcast(tcx);
280+
for clause in elaborate::elaborate(tcx, [clause]).filter_only_self() {
281+
let clause = clause.instantiate_supertrait(tcx, ty::Binder::dummy(principal_trait));
282+
283+
let bound_predicate = clause.kind();
284+
match bound_predicate.skip_binder() {
285+
ty::ClauseKind::Trait(pred) => {
286+
// FIXME(negative_bounds): Handle this correctly...
287+
let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
288+
needed_associated_types.extend(
289+
tcx.associated_items(pred.trait_ref.def_id)
290+
.in_definition_order()
291+
// We only care about associated types.
292+
.filter(|item| item.is_type())
293+
// No RPITITs -- they're not dyn-compatible for now.
294+
.filter(|item| !item.is_impl_trait_in_trait())
295+
// If the associated type has a `where Self: Sized` bound,
296+
// we do not need to constrain the associated type.
297+
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
298+
.map(|item| (item.def_id, trait_ref)),
299+
);
300+
}
301+
_ => (),
302+
}
303+
}
304+
305+
let mut data: Vec<_> = [ty::Binder::dummy(ty::ExistentialPredicate::Trait(
306+
ty::ExistentialTraitRef::erase_self_ty(tcx, principal_trait),
307+
))]
308+
.into_iter()
309+
.chain(needed_associated_types.into_iter().map(|(def_id, trait_ref)| {
310+
trait_ref.map_bound(|trait_ref| {
311+
ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
312+
tcx,
313+
ty::ProjectionPredicate {
314+
projection_term: ty::AliasTerm::new_from_args(tcx, def_id, trait_ref.args),
315+
term: infcx.next_ty_var(DUMMY_SP).into(),
316+
},
317+
))
318+
})
319+
}))
320+
.collect();
321+
data.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
322+
323+
let self_ty = Ty::new_dynamic(
324+
tcx,
325+
tcx.mk_poly_existential_predicates(&data),
326+
tcx.lifetimes.re_erased,
327+
ty::Dyn,
328+
);
329+
330+
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
331+
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
332+
333+
let ocx = ObligationCtxt::new(&infcx);
334+
let Ok(()) =
335+
ocx.eq(&ObligationCause::dummy(), ty::ParamEnv::empty(), principal_trait, impl_trait_ref)
336+
else {
337+
return;
338+
};
339+
let Ok(()) =
340+
ocx.eq(&ObligationCause::dummy(), ty::ParamEnv::empty(), self_ty, impl_trait_ref.self_ty())
341+
else {
342+
return;
343+
};
344+
345+
ocx.register_obligations(
346+
tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args).into_iter().map(
347+
|(clause, _)| {
348+
Obligation::new(tcx, ObligationCause::dummy(), ty::ParamEnv::empty(), clause)
349+
},
350+
),
351+
);
352+
353+
if !ocx.select_where_possible().is_empty() {
354+
return;
355+
}
356+
357+
let local_def_id = if let Some(impl_def_id) = impl_def_id.as_local() {
358+
impl_def_id
359+
} else if let Some(trait_def_id) = trait_def_id.as_local() {
360+
trait_def_id
361+
} else {
362+
panic!()
363+
};
364+
let hir_id = tcx.local_def_id_to_hir_id(local_def_id);
365+
366+
let self_ty = infcx.resolve_vars_if_possible(self_ty);
367+
368+
tcx.node_span_lint(DYN_OVERLAP, hir_id, tcx.def_span(local_def_id), |diag| {
369+
diag.primary_message("hi");
370+
diag.span_label(
371+
tcx.def_span(trait_def_id),
372+
format!("built-in `{self_ty}` implementation for this trait"),
373+
);
374+
diag.span_label(tcx.def_span(impl_def_id), "overlaps with this blanket impl");
375+
});
376+
}

compiler/rustc_hir_analysis/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ pub fn provide(providers: &mut Providers) {
171171
inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
172172
enforce_impl_non_lifetime_params_are_constrained:
173173
impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
174+
lint_object_blanket_impl: impl_wf_check::lint_object_blanket_impl,
174175
..*providers
175176
};
176177
}

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ declare_lint_pass! {
3737
DEPRECATED_SAFE_2024,
3838
DEPRECATED_WHERE_CLAUSE_LOCATION,
3939
DUPLICATE_MACRO_ATTRIBUTES,
40+
DYN_OVERLAP,
4041
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4142
ELIDED_LIFETIMES_IN_PATHS,
4243
ELIDED_NAMED_LIFETIMES,
@@ -5067,3 +5068,14 @@ declare_lint! {
50675068
reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
50685069
};
50695070
}
5071+
5072+
declare_lint! {
5073+
/// The `dyn_overlap` lint is one of the lints of all time.
5074+
///
5075+
/// ### Uwu
5076+
///
5077+
/// Owo
5078+
pub DYN_OVERLAP,
5079+
Forbid,
5080+
"owo",
5081+
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ rustc_queries! {
527527
anon
528528
}
529529

530+
query lint_object_blanket_impl(_: (DefId, DefId)) {
531+
desc { "u if wu" }
532+
}
533+
530534
/// Set of param indexes for type params that are in the type's representation
531535
query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet<u32> {
532536
desc { "finding type parameters in the representation" }

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,8 @@ where
948948
GoalSource::TypeRelating
949949
}
950950
// FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive?
951-
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc,
951+
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
952+
| ty::PredicateKind::Ambiguous => GoalSource::Misc,
952953
p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
953954
};
954955
self.add_goal(source, goal);

library/std/src/io/buffered/bufreader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ impl<R: ?Sized + Seek> Seek for BufReader<R> {
579579
}
580580
}
581581

582-
impl<T: ?Sized> SizeHint for BufReader<T> {
582+
impl<T> SizeHint for BufReader<T> {
583583
#[inline]
584584
fn lower_bound(&self) -> usize {
585585
SizeHint::lower_bound(self.get_ref()) + self.buffer().len()

library/std/src/io/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3151,7 +3151,7 @@ trait SizeHint {
31513151
}
31523152
}
31533153

3154-
impl<T: ?Sized> SizeHint for T {
3154+
impl<T> SizeHint for T {
31553155
#[inline]
31563156
default fn lower_bound(&self) -> usize {
31573157
0

tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,15 @@ LL | fn take(
2121
= note: `Project` would have to be implemented for the type `for<'a> fn(&'a str) -> &'a str`
2222
= note: ...but `Project` is actually implemented for the type `fn(&'0 str) -> &'0 str`, for some specific lifetime `'0`
2323

24-
error: aborting due to 3 previous errors
24+
error: hi
25+
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:23:1
26+
|
27+
LL | trait Discard { type Out; }
28+
| ------------- built-in `dyn Discard<Out = _>` implementation for this trait
29+
LL | impl<T: ?Sized> Discard for T { type Out = (); }
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overlaps with this blanket impl
31+
|
32+
= note: `#[forbid(dyn_overlap)]` on by default
33+
34+
error: aborting due to 4 previous errors
2535

tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.stderr

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
error: hi
2+
--> $DIR/cant-see-copy-bound-from-child-rigid-2.rs:4:1
3+
|
4+
LL | trait Id {
5+
| -------- built-in `dyn Id<This = _>` implementation for this trait
6+
...
7+
LL | impl<T: ?Sized> Id for T {
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^ overlaps with this blanket impl
9+
|
10+
= note: `#[forbid(dyn_overlap)]` on by default
11+
112
error[E0382]: use of moved value: `x`
213
--> $DIR/cant-see-copy-bound-from-child-rigid-2.rs:14:9
314
|
@@ -8,6 +19,6 @@ LL | (x, x)
819
| |
920
| value moved here
1021

11-
error: aborting due to 1 previous error
22+
error: aborting due to 2 previous errors
1223

1324
For more information about this error, try `rustc --explain E0382`.

tests/ui/associated-types/associated-types-coherence-failure.stderr

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
error: hi
2+
--> $DIR/associated-types-coherence-failure.rs:15:1
3+
|
4+
LL | pub trait IntoCow<'a, B: ?Sized> {
5+
| -------------------------------- built-in `dyn IntoCow<'_, _>` implementation for this trait
6+
...
7+
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overlaps with this blanket impl
9+
|
10+
= note: `#[forbid(dyn_overlap)]` on by default
11+
112
error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
213
--> $DIR/associated-types-coherence-failure.rs:21:1
314
|
@@ -16,6 +27,6 @@ LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwn
1627
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
1728
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
1829

19-
error: aborting due to 2 previous errors
30+
error: aborting due to 3 previous errors
2031

2132
For more information about this error, try `rustc --explain E0119`.

tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
2323
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
2424
= note: `#[warn(anonymous_parameters)]` on by default
2525

26+
error[E0220]: associated type `Assoc` not found for `Self`
27+
--> $DIR/ice-mutability-error-slicing-121807.rs:7:36
28+
|
29+
LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
30+
| ^^^^^ associated type `Assoc` not found
31+
2632
error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait
2733
--> $DIR/ice-mutability-error-slicing-121807.rs:17:5
2834
|
@@ -41,12 +47,6 @@ LL | extern "C" fn read_word(&mut self) -> u8;
4147
LL | impl MemoryUnit for ROM {
4248
| ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation
4349

44-
error[E0220]: associated type `Assoc` not found for `Self`
45-
--> $DIR/ice-mutability-error-slicing-121807.rs:7:36
46-
|
47-
LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
48-
| ^^^^^ associated type `Assoc` not found
49-
5050
error: aborting due to 4 previous errors; 1 warning emitted
5151

5252
Some errors have detailed explanations: E0046, E0185, E0220, E0261.

tests/ui/borrowck/trait-impl-argument-difference-ice.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
88
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
99
= note: `#[warn(anonymous_parameters)]` on by default
1010

11+
error[E0220]: associated type `Assoc` not found for `Self`
12+
--> $DIR/trait-impl-argument-difference-ice.rs:4:36
13+
|
14+
LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
15+
| ^^^^^ associated type `Assoc` not found
16+
1117
error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait
1218
--> $DIR/trait-impl-argument-difference-ice.rs:14:5
1319
|
@@ -26,12 +32,6 @@ LL | extern "C" fn read_word(&mut self) -> u8;
2632
LL | impl MemoryUnit for ROM {
2733
| ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation
2834

29-
error[E0220]: associated type `Assoc` not found for `Self`
30-
--> $DIR/trait-impl-argument-difference-ice.rs:4:36
31-
|
32-
LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
33-
| ^^^^^ associated type `Assoc` not found
34-
3535
error[E0596]: cannot borrow `*self` as mutable, as it is behind a `&` reference
3636
--> $DIR/trait-impl-argument-difference-ice.rs:16:19
3737
|

tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
error: hi
2+
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:14:1
3+
|
4+
LL | trait Id {
5+
| -------- built-in `dyn Id<Id = _>` implementation for this trait
6+
...
7+
LL | impl<T: ?Sized> Id for T {
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^ overlaps with this blanket impl
9+
|
10+
= note: `#[forbid(dyn_overlap)]` on by default
11+
112
error: lifetime may not live long enough
213
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:27
314
|
@@ -11,5 +22,5 @@ LL | let _send = unsend as *const S<dyn Cat<'static>>;
1122
= note: the struct `S<T>` is invariant over the parameter `T`
1223
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
1324

14-
error: aborting due to 1 previous error
25+
error: aborting due to 2 previous errors
1526

0 commit comments

Comments
 (0)