Skip to content

Commit 31bc7e2

Browse files
committed
Auto merge of rust-lang#117415 - matthiaskrgr:rollup-jr2p1t2, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#116862 (Detect when trait is implemented for type and suggest importing it) - rust-lang#117389 (Some diagnostics improvements of `gen` blocks) - rust-lang#117396 (Don't treat closures/coroutine types as part of the public API) - rust-lang#117398 (Correctly handle nested or-patterns in exhaustiveness) - rust-lang#117403 (Poison check_well_formed if method receivers are invalid to prevent typeck from running on it) - rust-lang#117411 (Improve some diagnostics around `?Trait` bounds) - rust-lang#117414 (Don't normalize to an un-revealed opaque when we hit the recursion limit) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 236ac91 + c5aec96 commit 31bc7e2

31 files changed

+286
-149
lines changed

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+31-26
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};
88
use rustc_span::symbol::Ident;
99
use rustc_span::{ErrorGuaranteed, Span};
1010
use rustc_trait_selection::traits;
11+
use smallvec::SmallVec;
1112

1213
use crate::astconv::{
1314
AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
@@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
2829
let tcx = self.tcx();
2930

3031
// Try to find an unbound in bounds.
31-
let mut unbound = None;
32+
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
3233
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
3334
for ab in ast_bounds {
3435
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
35-
if unbound.is_none() {
36-
unbound = Some(&ptr.trait_ref);
37-
} else {
38-
tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span });
39-
}
36+
unbounds.push(ptr)
4037
}
4138
}
4239
};
@@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
5148
}
5249
}
5350

51+
if unbounds.len() > 1 {
52+
tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds {
53+
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
54+
});
55+
}
56+
5457
let sized_def_id = tcx.lang_items().sized_trait();
55-
match (&sized_def_id, unbound) {
56-
(Some(sized_def_id), Some(tpb))
57-
if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
58-
{
59-
// There was in fact a `?Sized` bound, return without doing anything
60-
return;
61-
}
62-
(_, Some(_)) => {
63-
// There was a `?Trait` bound, but it was not `?Sized`; warn.
64-
tcx.sess.span_warn(
65-
span,
66-
"default bound relaxed for a type parameter, but \
67-
this does nothing because the given bound is not \
68-
a default; only `?Sized` is supported",
69-
);
70-
// Otherwise, add implicitly sized if `Sized` is available.
71-
}
72-
_ => {
73-
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
58+
59+
let mut seen_sized_unbound = false;
60+
for unbound in unbounds {
61+
if let Some(sized_def_id) = sized_def_id {
62+
if unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) {
63+
seen_sized_unbound = true;
64+
continue;
65+
}
7466
}
67+
// There was a `?Trait` bound, but it was not `?Sized`; warn.
68+
tcx.sess.span_warn(
69+
unbound.span,
70+
"relaxing a default bound only does something for `?Sized`; \
71+
all other traits are not bound by default",
72+
);
7573
}
74+
75+
// If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available.
7676
if sized_def_id.is_none() {
7777
// No lang item for `Sized`, so we can't add it as a bound.
7878
return;
7979
}
80-
bounds.push_sized(tcx, self_ty, span);
80+
if seen_sized_unbound {
81+
// There was in fact a `?Sized` bound, return without doing anything
82+
} else {
83+
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
84+
bounds.push_sized(tcx, self_ty, span);
85+
}
8186
}
8287

8388
/// This helper takes a *converted* parameter type (`param_ty`)

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
9494
f: F,
9595
) -> Result<(), ErrorGuaranteed>
9696
where
97-
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
97+
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
9898
{
9999
let param_env = tcx.param_env(body_def_id);
100100
let infcx = &tcx.infer_ctxt().build();
@@ -105,7 +105,7 @@ where
105105
if !tcx.features().trivial_bounds {
106106
wfcx.check_false_global_bounds()
107107
}
108-
f(&mut wfcx);
108+
f(&mut wfcx)?;
109109

110110
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
111111

@@ -875,6 +875,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
875875
ty,
876876
trait_def_id,
877877
);
878+
Ok(())
878879
})
879880
} else {
880881
let mut diag = match ty.kind() {
@@ -961,6 +962,7 @@ fn check_associated_item(
961962
let ty = tcx.type_of(item.def_id).instantiate_identity();
962963
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
963964
wfcx.register_wf_obligation(span, loc, ty.into());
965+
Ok(())
964966
}
965967
ty::AssocKind::Fn => {
966968
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
@@ -972,7 +974,7 @@ fn check_associated_item(
972974
hir_sig.decl,
973975
item.def_id.expect_local(),
974976
);
975-
check_method_receiver(wfcx, hir_sig, item, self_ty);
977+
check_method_receiver(wfcx, hir_sig, item, self_ty)
976978
}
977979
ty::AssocKind::Type => {
978980
if let ty::AssocItemContainer::TraitContainer = item.container {
@@ -983,6 +985,7 @@ fn check_associated_item(
983985
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
984986
wfcx.register_wf_obligation(span, loc, ty.into());
985987
}
988+
Ok(())
986989
}
987990
}
988991
})
@@ -1097,6 +1100,7 @@ fn check_type_defn<'tcx>(
10971100
}
10981101

10991102
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
1103+
Ok(())
11001104
})
11011105
}
11021106

@@ -1121,7 +1125,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
11211125
}
11221126

11231127
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
1124-
check_where_clauses(wfcx, item.span, def_id)
1128+
check_where_clauses(wfcx, item.span, def_id);
1129+
Ok(())
11251130
});
11261131

11271132
// Only check traits, don't check trait aliases
@@ -1164,6 +1169,7 @@ fn check_item_fn(
11641169
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
11651170
let sig = tcx.fn_sig(def_id).instantiate_identity();
11661171
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
1172+
Ok(())
11671173
})
11681174
}
11691175

@@ -1218,6 +1224,7 @@ fn check_item_type(
12181224
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
12191225
);
12201226
}
1227+
Ok(())
12211228
})
12221229
}
12231230

@@ -1276,6 +1283,7 @@ fn check_impl<'tcx>(
12761283
}
12771284

12781285
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
1286+
Ok(())
12791287
})
12801288
}
12811289

@@ -1548,11 +1556,11 @@ fn check_method_receiver<'tcx>(
15481556
fn_sig: &hir::FnSig<'_>,
15491557
method: ty::AssocItem,
15501558
self_ty: Ty<'tcx>,
1551-
) {
1559+
) -> Result<(), ErrorGuaranteed> {
15521560
let tcx = wfcx.tcx();
15531561

15541562
if !method.fn_has_self_parameter {
1555-
return;
1563+
return Ok(());
15561564
}
15571565

15581566
let span = fn_sig.decl.inputs[0].span;
@@ -1571,11 +1579,11 @@ fn check_method_receiver<'tcx>(
15711579
if tcx.features().arbitrary_self_types {
15721580
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
15731581
// Report error; `arbitrary_self_types` was enabled.
1574-
e0307(tcx, span, receiver_ty);
1582+
return Err(e0307(tcx, span, receiver_ty));
15751583
}
15761584
} else {
15771585
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) {
1578-
if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
1586+
return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
15791587
// Report error; would have worked with `arbitrary_self_types`.
15801588
feature_err(
15811589
&tcx.sess.parse_sess,
@@ -1587,16 +1595,17 @@ fn check_method_receiver<'tcx>(
15871595
),
15881596
)
15891597
.help(HELP_FOR_SELF_TYPE)
1590-
.emit();
1598+
.emit()
15911599
} else {
15921600
// Report error; would not have worked with `arbitrary_self_types`.
1593-
e0307(tcx, span, receiver_ty);
1594-
}
1601+
e0307(tcx, span, receiver_ty)
1602+
});
15951603
}
15961604
}
1605+
Ok(())
15971606
}
15981607

1599-
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
1608+
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed {
16001609
struct_span_err!(
16011610
tcx.sess.diagnostic(),
16021611
span,
@@ -1605,7 +1614,7 @@ fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
16051614
)
16061615
.note("type of `self` must be `Self` or a type that dereferences to it")
16071616
.help(HELP_FOR_SELF_TYPE)
1608-
.emit();
1617+
.emit()
16091618
}
16101619

16111620
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If

compiler/rustc_hir_analysis/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub struct CopyImplOnTypeWithDtor {
9696
#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
9797
pub struct MultipleRelaxedDefaultBounds {
9898
#[primary_span]
99-
pub span: Span,
99+
pub spans: Vec<Span>,
100100
}
101101

102102
#[derive(Diagnostic)]

compiler/rustc_hir_typeck/src/method/suggest.rs

+40-16
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_span::def_id::DefIdSet;
3535
use rustc_span::symbol::{kw, sym, Ident};
3636
use rustc_span::Symbol;
3737
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
38+
use rustc_trait_selection::infer::InferCtxtExt;
3839
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
3940
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
4041
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -192,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
192193
.span_if_local(def_id)
193194
.unwrap_or_else(|| self.tcx.def_span(def_id));
194195
err.span_label(sp, format!("private {kind} defined here"));
195-
self.suggest_valid_traits(&mut err, out_of_scope_traits);
196+
self.suggest_valid_traits(&mut err, out_of_scope_traits, true);
196197
err.emit();
197198
}
198199

@@ -2464,6 +2465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24642465
&self,
24652466
err: &mut Diagnostic,
24662467
valid_out_of_scope_traits: Vec<DefId>,
2468+
explain: bool,
24672469
) -> bool {
24682470
if !valid_out_of_scope_traits.is_empty() {
24692471
let mut candidates = valid_out_of_scope_traits;
@@ -2476,7 +2478,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24762478
.find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
24772479
.copied();
24782480

2479-
err.help("items from traits can only be used if the trait is in scope");
2481+
if explain {
2482+
err.help("items from traits can only be used if the trait is in scope");
2483+
}
24802484
let msg = format!(
24812485
"the following {traits_are} implemented but not in scope; \
24822486
perhaps add a `use` for {one_of_them}:",
@@ -2693,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26932697
}
26942698
}
26952699
}
2696-
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
2700+
if self.suggest_valid_traits(err, valid_out_of_scope_traits, true) {
26972701
return;
26982702
}
26992703

@@ -2970,29 +2974,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
29702974
(candidates, Vec::new())
29712975
};
29722976

2977+
let impls_trait = |def_id: DefId| {
2978+
let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| {
2979+
if param.index == 0 {
2980+
rcvr_ty.into()
2981+
} else {
2982+
self.infcx.var_for_def(span, param)
2983+
}
2984+
});
2985+
self.infcx
2986+
.type_implements_trait(def_id, args, self.param_env)
2987+
.must_apply_modulo_regions()
2988+
&& param_type.is_none()
2989+
};
29732990
match &potential_candidates[..] {
29742991
[] => {}
29752992
[trait_info] if trait_info.def_id.is_local() => {
2976-
err.subdiagnostic(CandidateTraitNote {
2977-
span: self.tcx.def_span(trait_info.def_id),
2978-
trait_name: self.tcx.def_path_str(trait_info.def_id),
2979-
item_name,
2980-
action_or_ty: if trait_missing_method {
2981-
"NONE".to_string()
2982-
} else {
2983-
param_type.map_or_else(
2984-
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
2985-
ToString::to_string,
2986-
)
2987-
},
2988-
});
2993+
if impls_trait(trait_info.def_id) {
2994+
self.suggest_valid_traits(err, vec![trait_info.def_id], false);
2995+
} else {
2996+
err.subdiagnostic(CandidateTraitNote {
2997+
span: self.tcx.def_span(trait_info.def_id),
2998+
trait_name: self.tcx.def_path_str(trait_info.def_id),
2999+
item_name,
3000+
action_or_ty: if trait_missing_method {
3001+
"NONE".to_string()
3002+
} else {
3003+
param_type.map_or_else(
3004+
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
3005+
ToString::to_string,
3006+
)
3007+
},
3008+
});
3009+
}
29893010
}
29903011
trait_infos => {
29913012
let mut msg = message(param_type.map_or_else(
29923013
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
29933014
|param| format!("restrict type parameter `{param}` with"),
29943015
));
29953016
for (i, trait_info) in trait_infos.iter().enumerate() {
3017+
if impls_trait(trait_info.def_id) {
3018+
self.suggest_valid_traits(err, vec![trait_info.def_id], false);
3019+
}
29963020
msg.push_str(&format!(
29973021
"\ncandidate #{}: `{}`",
29983022
i + 1,

compiler/rustc_middle/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ middle_assert_coroutine_resume_after_return = coroutine resumed after completion
1212
middle_assert_divide_by_zero =
1313
attempt to divide `{$val}` by zero
1414
15+
middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked
16+
1517
middle_assert_misaligned_ptr_deref =
1618
misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
1719

compiler/rustc_middle/src/mir/terminator.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,7 @@ impl<O> AssertKind<O> {
250250
middle_assert_coroutine_resume_after_return
251251
}
252252
ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic,
253-
// FIXME(gen_blocks): custom error message for `gen` blocks
254-
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_async_resume_after_panic,
253+
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_gen_resume_after_panic,
255254
ResumedAfterPanic(CoroutineKind::Coroutine) => {
256255
middle_assert_coroutine_resume_after_panic
257256
}

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
931931
let specialized = pat.specialize(pcx, &ctor);
932932
for (subpat, column) in specialized.iter().zip(&mut specialized_columns) {
933933
if subpat.is_or_pat() {
934-
column.patterns.extend(subpat.iter_fields())
934+
column.patterns.extend(subpat.flatten_or_pat())
935935
} else {
936936
column.patterns.push(subpat)
937937
}

compiler/rustc_parse/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
278278
parse_function_body_equals_expr = function body cannot be `= expression;`
279279
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
280280
281-
parse_gen_block = `gen` blocks are not yet implemented
282-
.help = only the keyword is reserved for now
281+
parse_gen_fn = `gen` functions are not yet implemented
282+
.help = for now you can use `gen {"{}"}` blocks and return `impl Iterator` instead
283283
284284
parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax
285285

0 commit comments

Comments
 (0)