mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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
@ -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)]
|
||||
|
@ -35,6 +35,7 @@ use rustc_span::def_id::DefIdSet;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
|
||||
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
@ -192,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.span_if_local(def_id)
|
||||
.unwrap_or_else(|| self.tcx.def_span(def_id));
|
||||
err.span_label(sp, format!("private {kind} defined here"));
|
||||
self.suggest_valid_traits(&mut err, out_of_scope_traits);
|
||||
self.suggest_valid_traits(&mut err, out_of_scope_traits, true);
|
||||
err.emit();
|
||||
}
|
||||
|
||||
@ -2464,6 +2465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
valid_out_of_scope_traits: Vec<DefId>,
|
||||
explain: bool,
|
||||
) -> bool {
|
||||
if !valid_out_of_scope_traits.is_empty() {
|
||||
let mut candidates = valid_out_of_scope_traits;
|
||||
@ -2476,7 +2478,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
|
||||
.copied();
|
||||
|
||||
err.help("items from traits can only be used if the trait is in scope");
|
||||
if explain {
|
||||
err.help("items from traits can only be used if the trait is in scope");
|
||||
}
|
||||
let msg = format!(
|
||||
"the following {traits_are} implemented but not in scope; \
|
||||
perhaps add a `use` for {one_of_them}:",
|
||||
@ -2693,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
|
||||
if self.suggest_valid_traits(err, valid_out_of_scope_traits, true) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2970,22 +2974,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(candidates, Vec::new())
|
||||
};
|
||||
|
||||
let impls_trait = |def_id: DefId| {
|
||||
let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| {
|
||||
if param.index == 0 {
|
||||
rcvr_ty.into()
|
||||
} else {
|
||||
self.infcx.var_for_def(span, param)
|
||||
}
|
||||
});
|
||||
self.infcx
|
||||
.type_implements_trait(def_id, args, self.param_env)
|
||||
.must_apply_modulo_regions()
|
||||
&& param_type.is_none()
|
||||
};
|
||||
match &potential_candidates[..] {
|
||||
[] => {}
|
||||
[trait_info] if trait_info.def_id.is_local() => {
|
||||
err.subdiagnostic(CandidateTraitNote {
|
||||
span: self.tcx.def_span(trait_info.def_id),
|
||||
trait_name: self.tcx.def_path_str(trait_info.def_id),
|
||||
item_name,
|
||||
action_or_ty: if trait_missing_method {
|
||||
"NONE".to_string()
|
||||
} else {
|
||||
param_type.map_or_else(
|
||||
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
|
||||
ToString::to_string,
|
||||
)
|
||||
},
|
||||
});
|
||||
if impls_trait(trait_info.def_id) {
|
||||
self.suggest_valid_traits(err, vec![trait_info.def_id], false);
|
||||
} else {
|
||||
err.subdiagnostic(CandidateTraitNote {
|
||||
span: self.tcx.def_span(trait_info.def_id),
|
||||
trait_name: self.tcx.def_path_str(trait_info.def_id),
|
||||
item_name,
|
||||
action_or_ty: if trait_missing_method {
|
||||
"NONE".to_string()
|
||||
} else {
|
||||
param_type.map_or_else(
|
||||
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
|
||||
ToString::to_string,
|
||||
)
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
trait_infos => {
|
||||
let mut msg = message(param_type.map_or_else(
|
||||
@ -2993,6 +3014,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|param| format!("restrict type parameter `{param}` with"),
|
||||
));
|
||||
for (i, trait_info) in trait_infos.iter().enumerate() {
|
||||
if impls_trait(trait_info.def_id) {
|
||||
self.suggest_valid_traits(err, vec![trait_info.def_id], false);
|
||||
}
|
||||
msg.push_str(&format!(
|
||||
"\ncandidate #{}: `{}`",
|
||||
i + 1,
|
||||
|
@ -12,6 +12,8 @@ middle_assert_coroutine_resume_after_return = coroutine resumed after completion
|
||||
middle_assert_divide_by_zero =
|
||||
attempt to divide `{$val}` by zero
|
||||
|
||||
middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked
|
||||
|
||||
middle_assert_misaligned_ptr_deref =
|
||||
misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
|
||||
|
||||
|
@ -250,8 +250,7 @@ impl<O> AssertKind<O> {
|
||||
middle_assert_coroutine_resume_after_return
|
||||
}
|
||||
ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic,
|
||||
// FIXME(gen_blocks): custom error message for `gen` blocks
|
||||
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_async_resume_after_panic,
|
||||
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_gen_resume_after_panic,
|
||||
ResumedAfterPanic(CoroutineKind::Coroutine) => {
|
||||
middle_assert_coroutine_resume_after_panic
|
||||
}
|
||||
|
@ -931,7 +931,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
|
||||
let specialized = pat.specialize(pcx, &ctor);
|
||||
for (subpat, column) in specialized.iter().zip(&mut specialized_columns) {
|
||||
if subpat.is_or_pat() {
|
||||
column.patterns.extend(subpat.iter_fields())
|
||||
column.patterns.extend(subpat.flatten_or_pat())
|
||||
} else {
|
||||
column.patterns.push(subpat)
|
||||
}
|
||||
|
@ -278,8 +278,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
|
||||
parse_function_body_equals_expr = function body cannot be `= expression;`
|
||||
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
|
||||
|
||||
parse_gen_block = `gen` blocks are not yet implemented
|
||||
.help = only the keyword is reserved for now
|
||||
parse_gen_fn = `gen` functions are not yet implemented
|
||||
.help = for now you can use `gen {"{}"}` blocks and return `impl Iterator` instead
|
||||
|
||||
parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax
|
||||
|
||||
|
@ -521,9 +521,9 @@ pub(crate) struct CatchAfterTry {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_gen_block)]
|
||||
#[diag(parse_gen_fn)]
|
||||
#[help]
|
||||
pub(crate) struct GenBlock {
|
||||
pub(crate) struct GenFn {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -2372,7 +2372,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
if let Gen::Yes { span, .. } = genness {
|
||||
self.sess.emit_err(errors::GenBlock { span });
|
||||
self.sess.emit_err(errors::GenFn { span });
|
||||
}
|
||||
|
||||
if !self.eat_keyword_case(kw::Fn, case) {
|
||||
|
@ -230,17 +230,14 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
|
||||
Reveal::All => {
|
||||
let args = data.args.try_fold_with(self)?;
|
||||
let recursion_limit = self.interner().recursion_limit();
|
||||
|
||||
if !recursion_limit.value_within_limit(self.anon_depth) {
|
||||
// A closure or coroutine may have itself as in its upvars.
|
||||
// This should be checked handled by the recursion check for opaque
|
||||
// types, but we may end up here before that check can happen.
|
||||
// In that case, we delay a bug to mark the trip, and continue without
|
||||
// revealing the opaque.
|
||||
self.infcx
|
||||
let guar = self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.build_overflow_error(&ty, self.cause.span, true)
|
||||
.delay_as_bug();
|
||||
return ty.try_super_fold_with(self);
|
||||
return Ok(Ty::new_error(self.interner(), guar));
|
||||
}
|
||||
|
||||
let generic_ty = self.interner().type_of(data.def_id);
|
||||
|
@ -121,6 +121,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
|
||||
#[instrument(skip(self), ret, level = "trace")]
|
||||
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
|
||||
self.visit_spanned(span, value);
|
||||
ControlFlow::Continue(())
|
||||
|
@ -4,7 +4,7 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_hir::{def::DefKind, def_id::LocalDefId};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::Span;
|
||||
use rustc_type_ir::visit::TypeVisitable;
|
||||
|
||||
@ -25,24 +25,9 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
||||
let kind = tcx.def_kind(item);
|
||||
trace!(?kind);
|
||||
match kind {
|
||||
DefKind::Coroutine => {
|
||||
match tcx.type_of(item).instantiate_identity().kind() {
|
||||
ty::Coroutine(_, args, _) => visitor.visit(tcx.def_span(item), args.as_coroutine().sig())?,
|
||||
_ => bug!(),
|
||||
}
|
||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||
visitor.visit(span, pred)?;
|
||||
}
|
||||
}
|
||||
// Walk over the signature of the function-like
|
||||
DefKind::Closure | DefKind::AssocFn | DefKind::Fn => {
|
||||
let ty_sig = match kind {
|
||||
DefKind::Closure => match tcx.type_of(item).instantiate_identity().kind() {
|
||||
ty::Closure(_, args) => args.as_closure().sig(),
|
||||
_ => bug!(),
|
||||
},
|
||||
_ => tcx.fn_sig(item).instantiate_identity(),
|
||||
};
|
||||
// Walk over the signature of the function
|
||||
DefKind::AssocFn | DefKind::Fn => {
|
||||
let ty_sig = tcx.fn_sig(item).instantiate_identity();
|
||||
let hir_sig = tcx.hir().get_by_def_id(item).fn_decl().unwrap();
|
||||
// Walk over the inputs and outputs manually in order to get good spans for them.
|
||||
visitor.visit(hir_sig.output.span(), ty_sig.output());
|
||||
@ -61,7 +46,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
||||
Some(ty) => ty.span,
|
||||
_ => tcx.def_span(item),
|
||||
};
|
||||
visitor.visit(span, tcx.type_of(item).instantiate_identity());
|
||||
visitor.visit(span, tcx.type_of(item).instantiate_identity());
|
||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||
visitor.visit(span, pred)?;
|
||||
}
|
||||
@ -74,13 +59,15 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
||||
// Look at field types
|
||||
DefKind::Struct | DefKind::Union | DefKind::Enum => {
|
||||
let span = tcx.def_ident_span(item).unwrap();
|
||||
visitor.visit(span, tcx.type_of(item).instantiate_identity());
|
||||
visitor.visit(span, tcx.type_of(item).instantiate_identity());
|
||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||
visitor.visit(span, pred)?;
|
||||
}
|
||||
}
|
||||
// Does not have a syntactical signature
|
||||
DefKind::InlineConst => {}
|
||||
// These are not part of a public API, they can only appear as hidden types, and there
|
||||
// the interesting parts are solely in the signature of the containing item's opaque type
|
||||
// or dyn type.
|
||||
DefKind::InlineConst | DefKind::Closure | DefKind::Coroutine => {}
|
||||
DefKind::Impl { of_trait } => {
|
||||
if of_trait {
|
||||
let span = tcx.hir().get_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span;
|
||||
@ -92,15 +79,11 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
||||
_ => tcx.def_span(item),
|
||||
};
|
||||
visitor.visit(span, tcx.type_of(item).instantiate_identity());
|
||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||
visitor.visit(span, pred)?;
|
||||
}}
|
||||
DefKind::Trait => {
|
||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||
visitor.visit(span, pred)?;
|
||||
}
|
||||
}
|
||||
DefKind::TraitAlias => {
|
||||
DefKind::TraitAlias | DefKind::Trait => {
|
||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||
visitor.visit(span, pred)?;
|
||||
}
|
||||
|
26
tests/ui/coroutine/gen_block_panic.rs
Normal file
26
tests/ui/coroutine/gen_block_panic.rs
Normal file
@ -0,0 +1,26 @@
|
||||
//compile-flags: --edition 2024 -Zunstable-options
|
||||
// run-pass
|
||||
// needs-unwind
|
||||
#![feature(gen_blocks)]
|
||||
|
||||
fn main() {
|
||||
let mut iter = gen {
|
||||
yield 42;
|
||||
panic!("foo");
|
||||
yield 69; //~ WARN: unreachable statement
|
||||
};
|
||||
assert_eq!(iter.next(), Some(42));
|
||||
let mut tmp = std::panic::AssertUnwindSafe(&mut iter);
|
||||
match std::panic::catch_unwind(move || tmp.next()) {
|
||||
Ok(_) => unreachable!(),
|
||||
Err(err) => assert_eq!(*err.downcast::<&'static str>().unwrap(), "foo"),
|
||||
}
|
||||
|
||||
match std::panic::catch_unwind(move || iter.next()) {
|
||||
Ok(_) => unreachable!(),
|
||||
Err(err) => assert_eq!(
|
||||
*err.downcast::<&'static str>().unwrap(),
|
||||
"`gen fn` should just keep returning `None` after panicking",
|
||||
),
|
||||
}
|
||||
}
|
12
tests/ui/coroutine/gen_block_panic.stderr
Normal file
12
tests/ui/coroutine/gen_block_panic.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
warning: unreachable statement
|
||||
--> $DIR/gen_block_panic.rs:10:9
|
||||
|
|
||||
LL | panic!("foo");
|
||||
| ------------- any code following this expression is unreachable
|
||||
LL | yield 69;
|
||||
| ^^^^^^^^^ unreachable statement
|
||||
|
|
||||
= note: `#[warn(unreachable_code)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: `gen` blocks are not yet implemented
|
||||
error: `gen` functions are not yet implemented
|
||||
--> $DIR/gen_fn.rs:4:1
|
||||
|
|
||||
LL | gen fn foo() {}
|
||||
| ^^^
|
||||
|
|
||||
= help: only the keyword is reserved for now
|
||||
= help: for now you can use `gen {}` blocks and return `impl Iterator` instead
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,6 +3,6 @@
|
||||
|
||||
gen fn foo() {}
|
||||
//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen`
|
||||
//[e2024]~^^ ERROR: `gen` blocks are not yet implemented
|
||||
//[e2024]~^^ ERROR: `gen` functions are not yet implemented
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
struct Foo<T: ?Hash> { }
|
||||
struct Foo<T: ?Hash> {}
|
||||
//~^ ERROR expected trait, found derive macro `Hash`
|
||||
//~^^ ERROR parameter `T` is never used
|
||||
//~^^^ WARN default bound relaxed for a type parameter, but this does nothing
|
||||
//~^^^ WARN relaxing a default bound only does something for `?Sized`
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
error[E0404]: expected trait, found derive macro `Hash`
|
||||
--> $DIR/issue-37534.rs:1:16
|
||||
|
|
||||
LL | struct Foo<T: ?Hash> { }
|
||||
LL | struct Foo<T: ?Hash> {}
|
||||
| ^^^^ not a trait
|
||||
|
|
||||
help: consider importing this trait instead
|
||||
@ -9,16 +9,16 @@ help: consider importing this trait instead
|
||||
LL + use std::hash::Hash;
|
||||
|
|
||||
|
||||
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
|
||||
--> $DIR/issue-37534.rs:1:12
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/issue-37534.rs:1:15
|
||||
|
|
||||
LL | struct Foo<T: ?Hash> { }
|
||||
| ^
|
||||
LL | struct Foo<T: ?Hash> {}
|
||||
| ^^^^^
|
||||
|
||||
error[E0392]: parameter `T` is never used
|
||||
--> $DIR/issue-37534.rs:1:12
|
||||
|
|
||||
LL | struct Foo<T: ?Hash> { }
|
||||
LL | struct Foo<T: ?Hash> {}
|
||||
| ^ unused parameter
|
||||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
// Check that these function definitions only emit warnings, not errors
|
||||
fn arg<T: ?Send>(_: T) {}
|
||||
//~^ warning: default bound relaxed for a type parameter, but this does nothing
|
||||
//~^ warning: relaxing a default bound only does something for `?Sized`
|
||||
fn ref_arg<T: ?Send>(_: &T) {}
|
||||
//~^ warning: default bound relaxed for a type parameter, but this does nothing
|
||||
//~^ warning: relaxing a default bound only does something for `?Sized`
|
||||
fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
|
||||
//~^ warning: default bound relaxed for a type parameter, but this does nothing
|
||||
//~^ warning: relaxing a default bound only does something for `?Sized`
|
||||
|
||||
// Check that there's no `?Sized` relaxation!
|
||||
fn main() {
|
||||
|
@ -1,20 +1,20 @@
|
||||
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
|
||||
--> $DIR/issue-87199.rs:8:8
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/issue-87199.rs:8:11
|
||||
|
|
||||
LL | fn arg<T: ?Send>(_: T) {}
|
||||
| ^
|
||||
| ^^^^^
|
||||
|
||||
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
|
||||
--> $DIR/issue-87199.rs:10:12
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/issue-87199.rs:10:15
|
||||
|
|
||||
LL | fn ref_arg<T: ?Send>(_: &T) {}
|
||||
| ^
|
||||
| ^^^^^
|
||||
|
||||
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
|
||||
--> $DIR/issue-87199.rs:12:13
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/issue-87199.rs:12:40
|
||||
|
|
||||
LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
|
||||
--> $DIR/issue-87199.rs:18:15
|
||||
|
@ -35,4 +35,10 @@ fn main() {
|
||||
((0, 0) | (1, 0),) => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// This one caused ICE https://github.com/rust-lang/rust/issues/117378
|
||||
match (0u8, 0) {
|
||||
(x @ 0 | x @ (1 | 2), _) => {}
|
||||
(3.., _) => {}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:8:43
|
||||
|
|
||||
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
| ^
|
||||
|
|
||||
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
|
||||
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:14:5
|
||||
--> $DIR/arbitrary-self-from-method-substs.rs:16:5
|
||||
|
|
||||
LL | foo.get::<&Foo>();
|
||||
| ^^^ expected `&Foo`, found `Foo`
|
@ -1,10 +1,12 @@
|
||||
#![feature(arbitrary_self_types)]
|
||||
// revisions: default feature
|
||||
#![cfg_attr(feature, feature(arbitrary_self_types))]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
struct Foo(u32);
|
||||
impl Foo {
|
||||
fn get<R: Deref<Target=Self>>(self: R) -> u32 {
|
||||
fn get<R: Deref<Target = Self>>(self: R) -> u32 {
|
||||
//[default]~^ ERROR: `R` cannot be used as the type of `self`
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@ -12,5 +14,5 @@ impl Foo {
|
||||
fn main() {
|
||||
let mut foo = Foo(1);
|
||||
foo.get::<&Foo>();
|
||||
//~^ ERROR mismatched types
|
||||
//[feature]~^ ERROR mismatched types
|
||||
}
|
||||
|
@ -8,11 +8,10 @@ LL | S.a();
|
||||
| ^ method not found in `S`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `method::A` defines an item `a`, perhaps you need to implement it
|
||||
--> $DIR/item-privacy.rs:6:5
|
||||
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||
|
|
||||
LL + use method::A;
|
||||
|
|
||||
LL | trait A {
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0599]: no method named `b` found for struct `S` in the current scope
|
||||
--> $DIR/item-privacy.rs:68:7
|
||||
@ -51,11 +50,10 @@ LL | S::a(&S);
|
||||
| ^ function or associated item not found in `S`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `method::A` defines an item `a`, perhaps you need to implement it
|
||||
--> $DIR/item-privacy.rs:6:5
|
||||
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||
|
|
||||
LL + use method::A;
|
||||
|
|
||||
LL | trait A {
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
|
||||
--> $DIR/item-privacy.rs:80:8
|
||||
@ -91,11 +89,10 @@ LL | S::A;
|
||||
| ^ associated item not found in `S`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `assoc_const::A` defines an item `A`, perhaps you need to implement it
|
||||
--> $DIR/item-privacy.rs:24:5
|
||||
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||
|
|
||||
LL + use assoc_const::A;
|
||||
|
|
||||
LL | trait A {
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0599]: no associated item named `B` found for struct `S` in the current scope
|
||||
--> $DIR/item-privacy.rs:98:8
|
||||
|
@ -0,0 +1,8 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type T = impl Copy;
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
|
||||
static STATIC: T = None::<&'static T>;
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,9 @@
|
||||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/infinite-cycle-involving-weak.rs:3:10
|
||||
|
|
||||
LL | type T = impl Copy;
|
||||
| ^^^^^^^^^ cannot resolve opaque type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
@ -0,0 +1,44 @@
|
||||
//! This test checks that we do not walk types in async blocks for
|
||||
//! determining the opaque types that appear in a signature. async blocks,
|
||||
//! all other coroutines and closures are always private and not part of
|
||||
//! a signature. They become part of a signature via `dyn Trait` or `impl Trait`,
|
||||
//! which is something that we process abstractly without looking at its hidden
|
||||
//! types.
|
||||
// edition: 2021
|
||||
// check-pass
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
pub struct MemtableLocalStateStore {
|
||||
mem_table: MemTable,
|
||||
}
|
||||
|
||||
impl LocalStateStore for MemtableLocalStateStore {
|
||||
type IterStream<'a> = impl Sized + 'a where Self: 'a;
|
||||
|
||||
fn iter(&self) -> impl Future<Output = Self::IterStream<'_>> + '_ {
|
||||
async move { merge_stream(self.mem_table.iter()) }
|
||||
}
|
||||
}
|
||||
|
||||
trait LocalStateStore {
|
||||
type IterStream<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn iter(&self) -> impl Future<Output = Self::IterStream<'_>> + '_;
|
||||
}
|
||||
|
||||
struct MemTable;
|
||||
|
||||
impl MemTable {
|
||||
fn iter<'a>(&'a self) -> impl Iterator<Item = &'a ()> {
|
||||
std::iter::empty()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn merge_stream<'a>(mem_table_iter: impl Iterator<Item = &'a ()>) {}
|
||||
|
||||
fn main() {}
|
@ -11,11 +11,11 @@ trait Trait<'a> {}
|
||||
|
||||
struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
||||
//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||
//~| WARN default bound relaxed for a type parameter
|
||||
//~| WARN relaxing a default bound only does something for `?Sized`
|
||||
|
||||
struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||
//~^ ERROR type parameter has more than one relaxed default bound
|
||||
//~| WARN default bound relaxed for a type parameter
|
||||
//~| WARN relaxing a default bound only does something for `?Sized`
|
||||
|
||||
impl<T> S1<T> {
|
||||
fn f() where T: ?Sized {}
|
||||
|
@ -28,23 +28,23 @@ error: `?Trait` bounds are only permitted at the point where a type parameter is
|
||||
LL | fn f() where T: ?Sized {}
|
||||
| ^^^^^^
|
||||
|
||||
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
|
||||
--> $DIR/maybe-bounds-where.rs:12:11
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/maybe-bounds-where.rs:12:34
|
||||
|
|
||||
LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
||||
| ^
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0203]: type parameter has more than one relaxed default bound, only one is supported
|
||||
--> $DIR/maybe-bounds-where.rs:16:11
|
||||
--> $DIR/maybe-bounds-where.rs:16:33
|
||||
|
|
||||
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^^^ ^^^^^^
|
||||
|
||||
warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
|
||||
--> $DIR/maybe-bounds-where.rs:16:11
|
||||
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||
--> $DIR/maybe-bounds-where.rs:16:33
|
||||
|
|
||||
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors; 2 warnings emitted
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user