mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +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::symbol::Ident;
|
||||||
use rustc_span::{ErrorGuaranteed, Span};
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::astconv::{
|
use crate::astconv::{
|
||||||
AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
|
AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
|
||||||
@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
// Try to find an unbound in bounds.
|
// 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>]| {
|
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
|
||||||
for ab in ast_bounds {
|
for ab in ast_bounds {
|
||||||
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
|
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
|
||||||
if unbound.is_none() {
|
unbounds.push(ptr)
|
||||||
unbound = Some(&ptr.trait_ref);
|
|
||||||
} else {
|
|
||||||
tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sized_def_id = tcx.lang_items().sized_trait();
|
if unbounds.len() > 1 {
|
||||||
match (&sized_def_id, unbound) {
|
tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds {
|
||||||
(Some(sized_def_id), Some(tpb))
|
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||||
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.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
if sized_def_id.is_none() {
|
||||||
// No lang item for `Sized`, so we can't add it as a bound.
|
// No lang item for `Sized`, so we can't add it as a bound.
|
||||||
return;
|
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`)
|
/// This helper takes a *converted* parameter type (`param_ty`)
|
||||||
|
@ -94,7 +94,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||||||
f: F,
|
f: F,
|
||||||
) -> Result<(), ErrorGuaranteed>
|
) -> Result<(), ErrorGuaranteed>
|
||||||
where
|
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 param_env = tcx.param_env(body_def_id);
|
||||||
let infcx = &tcx.infer_ctxt().build();
|
let infcx = &tcx.infer_ctxt().build();
|
||||||
@ -105,7 +105,7 @@ where
|
|||||||
if !tcx.features().trivial_bounds {
|
if !tcx.features().trivial_bounds {
|
||||||
wfcx.check_false_global_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)?;
|
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,
|
ty,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let mut diag = match ty.kind() {
|
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 = tcx.type_of(item.def_id).instantiate_identity();
|
||||||
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
ty::AssocKind::Fn => {
|
ty::AssocKind::Fn => {
|
||||||
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
||||||
@ -972,7 +974,7 @@ fn check_associated_item(
|
|||||||
hir_sig.decl,
|
hir_sig.decl,
|
||||||
item.def_id.expect_local(),
|
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 => {
|
ty::AssocKind::Type => {
|
||||||
if let ty::AssocItemContainer::TraitContainer = item.container {
|
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);
|
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
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);
|
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| {
|
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
|
// 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| {
|
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
|
||||||
let sig = tcx.fn_sig(def_id).instantiate_identity();
|
let sig = tcx.fn_sig(def_id).instantiate_identity();
|
||||||
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
|
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)),
|
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);
|
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<'_>,
|
fn_sig: &hir::FnSig<'_>,
|
||||||
method: ty::AssocItem,
|
method: ty::AssocItem,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
) {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let tcx = wfcx.tcx();
|
let tcx = wfcx.tcx();
|
||||||
|
|
||||||
if !method.fn_has_self_parameter {
|
if !method.fn_has_self_parameter {
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let span = fn_sig.decl.inputs[0].span;
|
let span = fn_sig.decl.inputs[0].span;
|
||||||
@ -1571,11 +1579,11 @@ fn check_method_receiver<'tcx>(
|
|||||||
if tcx.features().arbitrary_self_types {
|
if tcx.features().arbitrary_self_types {
|
||||||
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
|
||||||
// Report error; `arbitrary_self_types` was enabled.
|
// Report error; `arbitrary_self_types` was enabled.
|
||||||
e0307(tcx, span, receiver_ty);
|
return Err(e0307(tcx, span, receiver_ty));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) {
|
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`.
|
// Report error; would have worked with `arbitrary_self_types`.
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess.parse_sess,
|
&tcx.sess.parse_sess,
|
||||||
@ -1587,16 +1595,17 @@ fn check_method_receiver<'tcx>(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.help(HELP_FOR_SELF_TYPE)
|
.help(HELP_FOR_SELF_TYPE)
|
||||||
.emit();
|
.emit()
|
||||||
} else {
|
} else {
|
||||||
// Report error; would not have worked with `arbitrary_self_types`.
|
// 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!(
|
struct_span_err!(
|
||||||
tcx.sess.diagnostic(),
|
tcx.sess.diagnostic(),
|
||||||
span,
|
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")
|
.note("type of `self` must be `Self` or a type that dereferences to it")
|
||||||
.help(HELP_FOR_SELF_TYPE)
|
.help(HELP_FOR_SELF_TYPE)
|
||||||
.emit();
|
.emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
|
/// 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")]
|
#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
|
||||||
pub struct MultipleRelaxedDefaultBounds {
|
pub struct MultipleRelaxedDefaultBounds {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub spans: Vec<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -35,6 +35,7 @@ use rustc_span::def_id::DefIdSet;
|
|||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
|
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::OnUnimplementedNote;
|
||||||
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
|
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt 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)
|
.span_if_local(def_id)
|
||||||
.unwrap_or_else(|| self.tcx.def_span(def_id));
|
.unwrap_or_else(|| self.tcx.def_span(def_id));
|
||||||
err.span_label(sp, format!("private {kind} defined here"));
|
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();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2464,6 +2465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
valid_out_of_scope_traits: Vec<DefId>,
|
valid_out_of_scope_traits: Vec<DefId>,
|
||||||
|
explain: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if !valid_out_of_scope_traits.is_empty() {
|
if !valid_out_of_scope_traits.is_empty() {
|
||||||
let mut candidates = valid_out_of_scope_traits;
|
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))
|
.find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
|
||||||
.copied();
|
.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!(
|
let msg = format!(
|
||||||
"the following {traits_are} implemented but not in scope; \
|
"the following {traits_are} implemented but not in scope; \
|
||||||
perhaps add a `use` for {one_of_them}:",
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2970,22 +2974,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
(candidates, Vec::new())
|
(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[..] {
|
match &potential_candidates[..] {
|
||||||
[] => {}
|
[] => {}
|
||||||
[trait_info] if trait_info.def_id.is_local() => {
|
[trait_info] if trait_info.def_id.is_local() => {
|
||||||
err.subdiagnostic(CandidateTraitNote {
|
if impls_trait(trait_info.def_id) {
|
||||||
span: self.tcx.def_span(trait_info.def_id),
|
self.suggest_valid_traits(err, vec![trait_info.def_id], false);
|
||||||
trait_name: self.tcx.def_path_str(trait_info.def_id),
|
} else {
|
||||||
item_name,
|
err.subdiagnostic(CandidateTraitNote {
|
||||||
action_or_ty: if trait_missing_method {
|
span: self.tcx.def_span(trait_info.def_id),
|
||||||
"NONE".to_string()
|
trait_name: self.tcx.def_path_str(trait_info.def_id),
|
||||||
} else {
|
item_name,
|
||||||
param_type.map_or_else(
|
action_or_ty: if trait_missing_method {
|
||||||
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
|
"NONE".to_string()
|
||||||
ToString::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 => {
|
trait_infos => {
|
||||||
let mut msg = message(param_type.map_or_else(
|
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"),
|
|param| format!("restrict type parameter `{param}` with"),
|
||||||
));
|
));
|
||||||
for (i, trait_info) in trait_infos.iter().enumerate() {
|
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!(
|
msg.push_str(&format!(
|
||||||
"\ncandidate #{}: `{}`",
|
"\ncandidate #{}: `{}`",
|
||||||
i + 1,
|
i + 1,
|
||||||
|
@ -12,6 +12,8 @@ middle_assert_coroutine_resume_after_return = coroutine resumed after completion
|
|||||||
middle_assert_divide_by_zero =
|
middle_assert_divide_by_zero =
|
||||||
attempt to divide `{$val}` 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 =
|
middle_assert_misaligned_ptr_deref =
|
||||||
misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
|
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
|
middle_assert_coroutine_resume_after_return
|
||||||
}
|
}
|
||||||
ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic,
|
ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic,
|
||||||
// FIXME(gen_blocks): custom error message for `gen` blocks
|
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_gen_resume_after_panic,
|
||||||
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_async_resume_after_panic,
|
|
||||||
ResumedAfterPanic(CoroutineKind::Coroutine) => {
|
ResumedAfterPanic(CoroutineKind::Coroutine) => {
|
||||||
middle_assert_coroutine_resume_after_panic
|
middle_assert_coroutine_resume_after_panic
|
||||||
}
|
}
|
||||||
|
@ -931,7 +931,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
|
|||||||
let specialized = pat.specialize(pcx, &ctor);
|
let specialized = pat.specialize(pcx, &ctor);
|
||||||
for (subpat, column) in specialized.iter().zip(&mut specialized_columns) {
|
for (subpat, column) in specialized.iter().zip(&mut specialized_columns) {
|
||||||
if subpat.is_or_pat() {
|
if subpat.is_or_pat() {
|
||||||
column.patterns.extend(subpat.iter_fields())
|
column.patterns.extend(subpat.flatten_or_pat())
|
||||||
} else {
|
} else {
|
||||||
column.patterns.push(subpat)
|
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;`
|
parse_function_body_equals_expr = function body cannot be `= expression;`
|
||||||
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
|
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
|
||||||
|
|
||||||
parse_gen_block = `gen` blocks are not yet implemented
|
parse_gen_fn = `gen` functions are not yet implemented
|
||||||
.help = only the keyword is reserved for now
|
.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
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_gen_block)]
|
#[diag(parse_gen_fn)]
|
||||||
#[help]
|
#[help]
|
||||||
pub(crate) struct GenBlock {
|
pub(crate) struct GenFn {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
@ -2372,7 +2372,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Gen::Yes { span, .. } = genness {
|
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) {
|
if !self.eat_keyword_case(kw::Fn, case) {
|
||||||
|
@ -230,17 +230,14 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
|
|||||||
Reveal::All => {
|
Reveal::All => {
|
||||||
let args = data.args.try_fold_with(self)?;
|
let args = data.args.try_fold_with(self)?;
|
||||||
let recursion_limit = self.interner().recursion_limit();
|
let recursion_limit = self.interner().recursion_limit();
|
||||||
|
|
||||||
if !recursion_limit.value_within_limit(self.anon_depth) {
|
if !recursion_limit.value_within_limit(self.anon_depth) {
|
||||||
// A closure or coroutine may have itself as in its upvars.
|
let guar = self
|
||||||
// This should be checked handled by the recursion check for opaque
|
.infcx
|
||||||
// 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
|
|
||||||
.err_ctxt()
|
.err_ctxt()
|
||||||
.build_overflow_error(&ty, self.cause.span, true)
|
.build_overflow_error(&ty, self.cause.span, true)
|
||||||
.delay_as_bug();
|
.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);
|
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> {
|
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<!> {
|
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
|
||||||
self.visit_spanned(span, value);
|
self.visit_spanned(span, value);
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use rustc_hir::{def::DefKind, def_id::LocalDefId};
|
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_span::Span;
|
||||||
use rustc_type_ir::visit::TypeVisitable;
|
use rustc_type_ir::visit::TypeVisitable;
|
||||||
|
|
||||||
@ -25,24 +25,9 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
|||||||
let kind = tcx.def_kind(item);
|
let kind = tcx.def_kind(item);
|
||||||
trace!(?kind);
|
trace!(?kind);
|
||||||
match kind {
|
match kind {
|
||||||
DefKind::Coroutine => {
|
// Walk over the signature of the function
|
||||||
match tcx.type_of(item).instantiate_identity().kind() {
|
DefKind::AssocFn | DefKind::Fn => {
|
||||||
ty::Coroutine(_, args, _) => visitor.visit(tcx.def_span(item), args.as_coroutine().sig())?,
|
let ty_sig = tcx.fn_sig(item).instantiate_identity();
|
||||||
_ => 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(),
|
|
||||||
};
|
|
||||||
let hir_sig = tcx.hir().get_by_def_id(item).fn_decl().unwrap();
|
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.
|
// Walk over the inputs and outputs manually in order to get good spans for them.
|
||||||
visitor.visit(hir_sig.output.span(), ty_sig.output());
|
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,
|
Some(ty) => ty.span,
|
||||||
_ => tcx.def_span(item),
|
_ => 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) {
|
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||||
visitor.visit(span, pred)?;
|
visitor.visit(span, pred)?;
|
||||||
}
|
}
|
||||||
@ -74,13 +59,15 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
|||||||
// Look at field types
|
// Look at field types
|
||||||
DefKind::Struct | DefKind::Union | DefKind::Enum => {
|
DefKind::Struct | DefKind::Union | DefKind::Enum => {
|
||||||
let span = tcx.def_ident_span(item).unwrap();
|
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) {
|
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||||
visitor.visit(span, pred)?;
|
visitor.visit(span, pred)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Does not have a syntactical signature
|
// These are not part of a public API, they can only appear as hidden types, and there
|
||||||
DefKind::InlineConst => {}
|
// 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 } => {
|
DefKind::Impl { of_trait } => {
|
||||||
if of_trait {
|
if of_trait {
|
||||||
let span = tcx.hir().get_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span;
|
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),
|
_ => 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)?;
|
|
||||||
}}
|
|
||||||
DefKind::Trait => {
|
|
||||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||||
visitor.visit(span, pred)?;
|
visitor.visit(span, pred)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefKind::TraitAlias => {
|
DefKind::TraitAlias | DefKind::Trait => {
|
||||||
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
|
||||||
visitor.visit(span, pred)?;
|
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
|
--> $DIR/gen_fn.rs:4:1
|
||||||
|
|
|
|
||||||
LL | gen fn foo() {}
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
gen fn foo() {}
|
gen fn foo() {}
|
||||||
//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen`
|
//[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() {}
|
fn main() {}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
struct Foo<T: ?Hash> { }
|
struct Foo<T: ?Hash> {}
|
||||||
//~^ ERROR expected trait, found derive macro `Hash`
|
//~^ ERROR expected trait, found derive macro `Hash`
|
||||||
//~^^ ERROR parameter `T` is never used
|
//~^^ 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`
|
error[E0404]: expected trait, found derive macro `Hash`
|
||||||
--> $DIR/issue-37534.rs:1:16
|
--> $DIR/issue-37534.rs:1:16
|
||||||
|
|
|
|
||||||
LL | struct Foo<T: ?Hash> { }
|
LL | struct Foo<T: ?Hash> {}
|
||||||
| ^^^^ not a trait
|
| ^^^^ not a trait
|
||||||
|
|
|
|
||||||
help: consider importing this trait instead
|
help: consider importing this trait instead
|
||||||
@ -9,16 +9,16 @@ help: consider importing this trait instead
|
|||||||
LL + use std::hash::Hash;
|
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
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/issue-37534.rs:1:12
|
--> $DIR/issue-37534.rs:1:15
|
||||||
|
|
|
|
||||||
LL | struct Foo<T: ?Hash> { }
|
LL | struct Foo<T: ?Hash> {}
|
||||||
| ^
|
| ^^^^^
|
||||||
|
|
||||||
error[E0392]: parameter `T` is never used
|
error[E0392]: parameter `T` is never used
|
||||||
--> $DIR/issue-37534.rs:1:12
|
--> $DIR/issue-37534.rs:1:12
|
||||||
|
|
|
|
||||||
LL | struct Foo<T: ?Hash> { }
|
LL | struct Foo<T: ?Hash> {}
|
||||||
| ^ unused parameter
|
| ^ unused parameter
|
||||||
|
|
|
|
||||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
= 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
|
// Check that these function definitions only emit warnings, not errors
|
||||||
fn arg<T: ?Send>(_: T) {}
|
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) {}
|
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() }
|
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!
|
// Check that there's no `?Sized` relaxation!
|
||||||
fn main() {
|
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
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/issue-87199.rs:8:8
|
--> $DIR/issue-87199.rs:8:11
|
||||||
|
|
|
|
||||||
LL | fn arg<T: ?Send>(_: T) {}
|
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
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/issue-87199.rs:10:12
|
--> $DIR/issue-87199.rs:10:15
|
||||||
|
|
|
|
||||||
LL | fn ref_arg<T: ?Send>(_: &T) {}
|
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
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/issue-87199.rs:12:13
|
--> $DIR/issue-87199.rs:12:40
|
||||||
|
|
|
|
||||||
LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
|
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
|
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
|
||||||
--> $DIR/issue-87199.rs:18:15
|
--> $DIR/issue-87199.rs:18:15
|
||||||
|
@ -35,4 +35,10 @@ fn main() {
|
|||||||
((0, 0) | (1, 0),) => {}
|
((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
|
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>();
|
LL | foo.get::<&Foo>();
|
||||||
| ^^^ expected `&Foo`, found `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;
|
use std::ops::Deref;
|
||||||
|
|
||||||
struct Foo(u32);
|
struct Foo(u32);
|
||||||
impl Foo {
|
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
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,5 +14,5 @@ impl Foo {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut foo = Foo(1);
|
let mut foo = Foo(1);
|
||||||
foo.get::<&Foo>();
|
foo.get::<&Foo>();
|
||||||
//~^ ERROR mismatched types
|
//[feature]~^ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,10 @@ LL | S.a();
|
|||||||
| ^ method not found in `S`
|
| ^ method not found in `S`
|
||||||
|
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= 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
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
--> $DIR/item-privacy.rs:6:5
|
|
|
||||||
|
LL + use method::A;
|
||||||
|
|
|
|
||||||
LL | trait A {
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error[E0599]: no method named `b` found for struct `S` in the current scope
|
error[E0599]: no method named `b` found for struct `S` in the current scope
|
||||||
--> $DIR/item-privacy.rs:68:7
|
--> $DIR/item-privacy.rs:68:7
|
||||||
@ -51,11 +50,10 @@ LL | S::a(&S);
|
|||||||
| ^ function or associated item not found in `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
|
= 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
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
--> $DIR/item-privacy.rs:6:5
|
|
|
||||||
|
LL + use method::A;
|
||||||
|
|
|
|
||||||
LL | trait A {
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
|
error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
|
||||||
--> $DIR/item-privacy.rs:80:8
|
--> $DIR/item-privacy.rs:80:8
|
||||||
@ -91,11 +89,10 @@ LL | S::A;
|
|||||||
| ^ associated item not found in `S`
|
| ^ associated item not found in `S`
|
||||||
|
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= 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
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
--> $DIR/item-privacy.rs:24:5
|
|
|
||||||
|
LL + use assoc_const::A;
|
||||||
|
|
|
|
||||||
LL | trait A {
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error[E0599]: no associated item named `B` found for struct `S` in the current scope
|
error[E0599]: no associated item named `B` found for struct `S` in the current scope
|
||||||
--> $DIR/item-privacy.rs:98:8
|
--> $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>;
|
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
|
//~^ 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;
|
struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||||
//~^ ERROR type parameter has more than one relaxed default bound
|
//~^ 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> {
|
impl<T> S1<T> {
|
||||||
fn f() where T: ?Sized {}
|
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 {}
|
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
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $DIR/maybe-bounds-where.rs:12:11
|
--> $DIR/maybe-bounds-where.rs:12:34
|
||||||
|
|
|
|
||||||
LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
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
|
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;
|
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
|
warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
|
||||||
--> $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;
|
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||||
| ^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors; 2 warnings emitted
|
error: aborting due to 6 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user