Auto merge of #117415 - matthiaskrgr:rollup-jr2p1t2, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #116862 (Detect when trait is implemented for type and suggest importing it) - #117389 (Some diagnostics improvements of `gen` blocks) - #117396 (Don't treat closures/coroutine types as part of the public API) - #117398 (Correctly handle nested or-patterns in exhaustiveness) - #117403 (Poison check_well_formed if method receivers are invalid to prevent typeck from running on it) - #117411 (Improve some diagnostics around `?Trait` bounds) - #117414 (Don't normalize to an un-revealed opaque when we hit the recursion limit) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
31bc7e2c47
31 changed files with 288 additions and 151 deletions
|
@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};
|
|||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::astconv::{
|
||||
AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
|
||||
|
@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
let tcx = self.tcx();
|
||||
|
||||
// Try to find an unbound in bounds.
|
||||
let mut unbound = None;
|
||||
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
|
||||
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
||||
for ab in ast_bounds {
|
||||
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
|
||||
if unbound.is_none() {
|
||||
unbound = Some(&ptr.trait_ref);
|
||||
} else {
|
||||
tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span });
|
||||
}
|
||||
unbounds.push(ptr)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
}
|
||||
}
|
||||
|
||||
let sized_def_id = tcx.lang_items().sized_trait();
|
||||
match (&sized_def_id, unbound) {
|
||||
(Some(sized_def_id), Some(tpb))
|
||||
if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
|
||||
{
|
||||
// There was in fact a `?Sized` bound, return without doing anything
|
||||
return;
|
||||
}
|
||||
(_, Some(_)) => {
|
||||
// There was a `?Trait` bound, but it was not `?Sized`; warn.
|
||||
tcx.sess.span_warn(
|
||||
span,
|
||||
"default bound relaxed for a type parameter, but \
|
||||
this does nothing because the given bound is not \
|
||||
a default; only `?Sized` is supported",
|
||||
);
|
||||
// Otherwise, add implicitly sized if `Sized` is available.
|
||||
}
|
||||
_ => {
|
||||
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
|
||||
}
|
||||
if unbounds.len() > 1 {
|
||||
tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds {
|
||||
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||
});
|
||||
}
|
||||
|
||||
let sized_def_id = tcx.lang_items().sized_trait();
|
||||
|
||||
let mut seen_sized_unbound = false;
|
||||
for unbound in unbounds {
|
||||
if let Some(sized_def_id) = sized_def_id {
|
||||
if unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) {
|
||||
seen_sized_unbound = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// There was a `?Trait` bound, but it was not `?Sized`; warn.
|
||||
tcx.sess.span_warn(
|
||||
unbound.span,
|
||||
"relaxing a default bound only does something for `?Sized`; \
|
||||
all other traits are not bound by default",
|
||||
);
|
||||
}
|
||||
|
||||
// If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available.
|
||||
if sized_def_id.is_none() {
|
||||
// No lang item for `Sized`, so we can't add it as a bound.
|
||||
return;
|
||||
}
|
||||
bounds.push_sized(tcx, self_ty, span);
|
||||
if seen_sized_unbound {
|
||||
// There was in fact a `?Sized` bound, return without doing anything
|
||||
} else {
|
||||
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
|
||||
bounds.push_sized(tcx, self_ty, span);
|
||||
}
|
||||
}
|
||||
|
||||
/// This helper takes a *converted* parameter type (`param_ty`)
|
||||
|
|
|
@ -94,7 +94,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||
f: F,
|
||||
) -> Result<(), ErrorGuaranteed>
|
||||
where
|
||||
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
|
||||
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
|
||||
{
|
||||
let param_env = tcx.param_env(body_def_id);
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
|
@ -105,7 +105,7 @@ where
|
|||
if !tcx.features().trivial_bounds {
|
||||
wfcx.check_false_global_bounds()
|
||||
}
|
||||
f(&mut wfcx);
|
||||
f(&mut wfcx)?;
|
||||
|
||||
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
|
||||
|
||||
|
@ -875,6 +875,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||
ty,
|
||||
trait_def_id,
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
} else {
|
||||
let mut diag = match ty.kind() {
|
||||
|
@ -961,6 +962,7 @@ fn check_associated_item(
|
|||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
Ok(())
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
||||
|
@ -972,7 +974,7 @@ fn check_associated_item(
|
|||
hir_sig.decl,
|
||||
item.def_id.expect_local(),
|
||||
);
|
||||
check_method_receiver(wfcx, hir_sig, item, self_ty);
|
||||
check_method_receiver(wfcx, hir_sig, item, self_ty)
|
||||
}
|
||||
ty::AssocKind::Type => {
|
||||
if let ty::AssocItemContainer::TraitContainer = item.container {
|
||||
|
@ -983,6 +985,7 @@ fn check_associated_item(
|
|||
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1097,6 +1100,7 @@ fn check_type_defn<'tcx>(
|
|||
}
|
||||
|
||||
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1125,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
|
|||
}
|
||||
|
||||
let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
|
||||
check_where_clauses(wfcx, item.span, def_id)
|
||||
check_where_clauses(wfcx, item.span, def_id);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
// Only check traits, don't check trait aliases
|
||||
|
@ -1164,6 +1169,7 @@ fn check_item_fn(
|
|||
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
|
||||
let sig = tcx.fn_sig(def_id).instantiate_identity();
|
||||
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1218,6 +1224,7 @@ fn check_item_type(
|
|||
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1276,6 +1283,7 @@ fn check_impl<'tcx>(
|
|||
}
|
||||
|
||||
check_where_clauses(wfcx, item.span, item.owner_id.def_id);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1548,11 +1556,11 @@ fn check_method_receiver<'tcx>(
|
|||
fn_sig: &hir::FnSig<'_>,
|
||||
method: ty::AssocItem,
|
||||
self_ty: Ty<'tcx>,
|
||||
) {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = wfcx.tcx();
|
||||
|
||||
if !method.fn_has_self_parameter {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let span = fn_sig.decl.inputs[0].span;
|
||||
|
@ -1571,11 +1579,11 @@ fn check_method_receiver<'tcx>(
|
|||
if tcx.features().arbitrary_self_types {
|
||||
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
||||
// Report error; `arbitrary_self_types` was enabled.
|
||||
e0307(tcx, span, receiver_ty);
|
||||
return Err(e0307(tcx, span, receiver_ty));
|
||||
}
|
||||
} else {
|
||||
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) {
|
||||
if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
||||
return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
||||
// Report error; would have worked with `arbitrary_self_types`.
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
|
@ -1587,16 +1595,17 @@ fn check_method_receiver<'tcx>(
|
|||
),
|
||||
)
|
||||
.help(HELP_FOR_SELF_TYPE)
|
||||
.emit();
|
||||
.emit()
|
||||
} else {
|
||||
// Report error; would not have worked with `arbitrary_self_types`.
|
||||
e0307(tcx, span, receiver_ty);
|
||||
}
|
||||
e0307(tcx, span, receiver_ty)
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
|
||||
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed {
|
||||
struct_span_err!(
|
||||
tcx.sess.diagnostic(),
|
||||
span,
|
||||
|
@ -1605,7 +1614,7 @@ fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
|
|||
)
|
||||
.note("type of `self` must be `Self` or a type that dereferences to it")
|
||||
.help(HELP_FOR_SELF_TYPE)
|
||||
.emit();
|
||||
.emit()
|
||||
}
|
||||
|
||||
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
|
||||
|
|
|
@ -96,7 +96,7 @@ pub struct CopyImplOnTypeWithDtor {
|
|||
#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
|
||||
pub struct MultipleRelaxedDefaultBounds {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue