Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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`.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /