mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 23:34:48 +00:00
Auto merge of #100195 - matthiaskrgr:rollup-ovzyyb0, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #100094 (Detect type mismatch due to loop that might never iterate) - #100132 (Use (actually) dummy place for let-else divergence) - #100167 (Recover `require`, `include` instead of `use` in item) - #100193 (Remove more Clean trait implementations) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5c54be35c6
@ -2334,7 +2334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// This place is not really used because this destination place
|
// This place is not really used because this destination place
|
||||||
// should never be used to take values at the end of the failure
|
// should never be used to take values at the end of the failure
|
||||||
// block.
|
// block.
|
||||||
let dummy_place = Place { local: RETURN_PLACE, projection: ty::List::empty() };
|
let dummy_place = self.temp(self.tcx.types.never, else_block.span);
|
||||||
let failure_block;
|
let failure_block;
|
||||||
unpack!(
|
unpack!(
|
||||||
failure_block = self.ast_block(
|
failure_block = self.ast_block(
|
||||||
|
@ -271,7 +271,10 @@ impl<'a> Parser<'a> {
|
|||||||
// MACRO_RULES ITEM
|
// MACRO_RULES ITEM
|
||||||
self.parse_item_macro_rules(vis, has_bang)?
|
self.parse_item_macro_rules(vis, has_bang)?
|
||||||
} else if self.isnt_macro_invocation()
|
} else if self.isnt_macro_invocation()
|
||||||
&& (self.token.is_ident_named(sym::import) || self.token.is_ident_named(sym::using))
|
&& (self.token.is_ident_named(sym::import)
|
||||||
|
|| self.token.is_ident_named(sym::using)
|
||||||
|
|| self.token.is_ident_named(sym::include)
|
||||||
|
|| self.token.is_ident_named(sym::require))
|
||||||
{
|
{
|
||||||
return self.recover_import_as_use();
|
return self.recover_import_as_use();
|
||||||
} else if self.isnt_macro_invocation() && vis.kind.is_pub() {
|
} else if self.isnt_macro_invocation() && vis.kind.is_pub() {
|
||||||
|
@ -1170,6 +1170,7 @@ symbols! {
|
|||||||
repr_packed,
|
repr_packed,
|
||||||
repr_simd,
|
repr_simd,
|
||||||
repr_transparent,
|
repr_transparent,
|
||||||
|
require,
|
||||||
residual,
|
residual,
|
||||||
result,
|
result,
|
||||||
rhs,
|
rhs,
|
||||||
|
@ -38,10 +38,12 @@
|
|||||||
use crate::astconv::AstConv;
|
use crate::astconv::AstConv;
|
||||||
use crate::check::FnCtxt;
|
use crate::check::FnCtxt;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
|
use rustc_hir::Expr;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_infer::infer::{Coercion, InferOk, InferResult};
|
use rustc_infer::infer::{Coercion, InferOk, InferResult};
|
||||||
use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
|
use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
|
||||||
@ -87,6 +89,19 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
|
|||||||
|
|
||||||
type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
|
type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
|
||||||
|
|
||||||
|
struct CollectRetsVisitor<'tcx> {
|
||||||
|
ret_exprs: Vec<&'tcx hir::Expr<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Visitor<'tcx> for CollectRetsVisitor<'tcx> {
|
||||||
|
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||||
|
if let hir::ExprKind::Ret(_) = expr.kind {
|
||||||
|
self.ret_exprs.push(expr);
|
||||||
|
}
|
||||||
|
intravisit::walk_expr(self, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Coercing a mutable reference to an immutable works, while
|
/// Coercing a mutable reference to an immutable works, while
|
||||||
/// coercing `&T` to `&mut T` should be forbidden.
|
/// coercing `&T` to `&mut T` should be forbidden.
|
||||||
fn coerce_mutbls<'tcx>(
|
fn coerce_mutbls<'tcx>(
|
||||||
@ -1481,6 +1496,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||||||
|
|
||||||
let mut err;
|
let mut err;
|
||||||
let mut unsized_return = false;
|
let mut unsized_return = false;
|
||||||
|
let mut visitor = CollectRetsVisitor { ret_exprs: vec![] };
|
||||||
match *cause.code() {
|
match *cause.code() {
|
||||||
ObligationCauseCode::ReturnNoExpression => {
|
ObligationCauseCode::ReturnNoExpression => {
|
||||||
err = struct_span_err!(
|
err = struct_span_err!(
|
||||||
@ -1506,6 +1522,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||||||
if !fcx.tcx.features().unsized_locals {
|
if !fcx.tcx.features().unsized_locals {
|
||||||
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
|
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
|
||||||
}
|
}
|
||||||
|
if let Some(expression) = expression
|
||||||
|
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind {
|
||||||
|
intravisit::walk_block(& mut visitor, loop_blk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ObligationCauseCode::ReturnValue(id) => {
|
ObligationCauseCode::ReturnValue(id) => {
|
||||||
err = self.report_return_mismatched_types(
|
err = self.report_return_mismatched_types(
|
||||||
@ -1551,12 +1571,39 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
|
||||||
|
self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
|
||||||
|
}
|
||||||
err.emit_unless(unsized_return);
|
err.emit_unless(unsized_return);
|
||||||
|
|
||||||
self.final_ty = Some(fcx.tcx.ty_error());
|
self.final_ty = Some(fcx.tcx.ty_error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn note_unreachable_loop_return<'a>(
|
||||||
|
&self,
|
||||||
|
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
|
||||||
|
expr: &hir::Expr<'tcx>,
|
||||||
|
ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>,
|
||||||
|
) {
|
||||||
|
let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { return;};
|
||||||
|
let mut span: MultiSpan = vec![loop_span].into();
|
||||||
|
span.push_span_label(loop_span, "this might have zero elements to iterate on".to_string());
|
||||||
|
for ret_expr in ret_exprs {
|
||||||
|
span.push_span_label(
|
||||||
|
ret_expr.span,
|
||||||
|
"if the loop doesn't execute, this value would never get returned".to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
err.span_note(
|
||||||
|
span,
|
||||||
|
"the function expects a value to always be returned, but loops might run zero times",
|
||||||
|
);
|
||||||
|
err.help(
|
||||||
|
"return a value for the case when the loop has zero elements to iterate on, or \
|
||||||
|
consider changing the return type to account for that possibility",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn report_return_mismatched_types<'a>(
|
fn report_return_mismatched_types<'a>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -126,40 +126,40 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Clean<'tcx, Option<GenericBound>> for hir::GenericBound<'tcx> {
|
fn clean_generic_bound<'tcx>(
|
||||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<GenericBound> {
|
bound: &hir::GenericBound<'tcx>,
|
||||||
Some(match *self {
|
cx: &mut DocContext<'tcx>,
|
||||||
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
|
) -> Option<GenericBound> {
|
||||||
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
|
Some(match *bound {
|
||||||
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
|
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
|
||||||
|
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
|
||||||
|
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
|
let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
|
||||||
|
|
||||||
let generic_args = generic_args.clean(cx);
|
let generic_args = generic_args.clean(cx);
|
||||||
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
|
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
|
||||||
else {
|
else {
|
||||||
bug!("clean: parenthesized `GenericBound::LangItemTrait`");
|
bug!("clean: parenthesized `GenericBound::LangItemTrait`");
|
||||||
};
|
};
|
||||||
|
|
||||||
let trait_ = clean_trait_ref_with_bindings(cx, trait_ref, &bindings);
|
let trait_ = clean_trait_ref_with_bindings(cx, trait_ref, &bindings);
|
||||||
GenericBound::TraitBound(
|
GenericBound::TraitBound(
|
||||||
PolyTrait { trait_, generic_params: vec![] },
|
PolyTrait { trait_, generic_params: vec![] },
|
||||||
hir::TraitBoundModifier::None,
|
hir::TraitBoundModifier::None,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
hir::GenericBound::Trait(ref t, modifier) => {
|
||||||
|
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
|
||||||
|
if modifier == hir::TraitBoundModifier::MaybeConst
|
||||||
|
&& cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
|
||||||
|
{
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
hir::GenericBound::Trait(ref t, modifier) => {
|
|
||||||
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
|
|
||||||
if modifier == hir::TraitBoundModifier::MaybeConst
|
|
||||||
&& cx.tcx.lang_items().destruct_trait()
|
|
||||||
== Some(t.trait_ref.trait_def_id().unwrap())
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier)
|
GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
|
pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
|
||||||
@ -207,12 +207,6 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> {
|
|
||||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericBound {
|
|
||||||
clean_poly_trait_ref_with_bindings(cx, *self, &[])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
|
fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
|
||||||
let def = cx.tcx.named_region(lifetime.hir_id);
|
let def = cx.tcx.named_region(lifetime.hir_id);
|
||||||
if let Some(
|
if let Some(
|
||||||
@ -294,14 +288,14 @@ impl<'tcx> Clean<'tcx, Option<WherePredicate>> for hir::WherePredicate<'tcx> {
|
|||||||
.collect();
|
.collect();
|
||||||
WherePredicate::BoundPredicate {
|
WherePredicate::BoundPredicate {
|
||||||
ty: clean_ty(wbp.bounded_ty, cx),
|
ty: clean_ty(wbp.bounded_ty, cx),
|
||||||
bounds: wbp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
|
bounds: wbp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
bound_params,
|
bound_params,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
|
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
|
||||||
lifetime: clean_lifetime(wrp.lifetime, cx),
|
lifetime: clean_lifetime(wrp.lifetime, cx),
|
||||||
bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
|
bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
},
|
},
|
||||||
|
|
||||||
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
|
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
|
||||||
@ -349,7 +343,7 @@ fn clean_poly_trait_predicate<'tcx>(
|
|||||||
let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
|
let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
|
||||||
Some(WherePredicate::BoundPredicate {
|
Some(WherePredicate::BoundPredicate {
|
||||||
ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
|
ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
|
||||||
bounds: vec![poly_trait_ref.clean(cx)],
|
bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, &[])],
|
||||||
bound_params: Vec::new(),
|
bound_params: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -531,7 +525,7 @@ fn clean_generic_param<'tcx>(
|
|||||||
.bounds_for_param(did)
|
.bounds_for_param(did)
|
||||||
.filter(|bp| bp.origin != PredicateOrigin::WhereClause)
|
.filter(|bp| bp.origin != PredicateOrigin::WhereClause)
|
||||||
.flat_map(|bp| bp.bounds)
|
.flat_map(|bp| bp.bounds)
|
||||||
.filter_map(|x| x.clean(cx))
|
.filter_map(|x| clean_generic_bound(x, cx))
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
@ -1041,7 +1035,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
|
|||||||
}
|
}
|
||||||
hir::TraitItemKind::Type(bounds, Some(default)) => {
|
hir::TraitItemKind::Type(bounds, Some(default)) => {
|
||||||
let generics = enter_impl_trait(cx, |cx| trait_item.generics.clean(cx));
|
let generics = enter_impl_trait(cx, |cx| trait_item.generics.clean(cx));
|
||||||
let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
|
let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
|
||||||
let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
|
let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
|
||||||
AssocTypeItem(
|
AssocTypeItem(
|
||||||
Box::new(Typedef {
|
Box::new(Typedef {
|
||||||
@ -1054,7 +1048,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
|
|||||||
}
|
}
|
||||||
hir::TraitItemKind::Type(bounds, None) => {
|
hir::TraitItemKind::Type(bounds, None) => {
|
||||||
let generics = enter_impl_trait(cx, |cx| trait_item.generics.clean(cx));
|
let generics = enter_impl_trait(cx, |cx| trait_item.generics.clean(cx));
|
||||||
let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
|
let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
|
||||||
TyAssocTypeItem(Box::new(generics), bounds)
|
TyAssocTypeItem(Box::new(generics), bounds)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1507,7 +1501,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||||||
TyKind::OpaqueDef(item_id, _) => {
|
TyKind::OpaqueDef(item_id, _) => {
|
||||||
let item = cx.tcx.hir().item(item_id);
|
let item = cx.tcx.hir().item(item_id);
|
||||||
if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
|
if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
|
||||||
ImplTrait(ty.bounds.iter().filter_map(|x| x.clean(cx)).collect())
|
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -1911,7 +1905,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||||||
kind: ConstantKind::Local { body: body_id, def_id },
|
kind: ConstantKind::Local { body: body_id, def_id },
|
||||||
}),
|
}),
|
||||||
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
|
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
|
||||||
bounds: ty.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
|
bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
generics: ty.generics.clean(cx),
|
generics: ty.generics.clean(cx),
|
||||||
}),
|
}),
|
||||||
ItemKind::TyAlias(hir_ty, generics) => {
|
ItemKind::TyAlias(hir_ty, generics) => {
|
||||||
@ -1929,7 +1923,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||||||
}),
|
}),
|
||||||
ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias {
|
ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias {
|
||||||
generics: generics.clean(cx),
|
generics: generics.clean(cx),
|
||||||
bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
|
bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
}),
|
}),
|
||||||
ItemKind::Union(ref variant_data, generics) => UnionItem(Union {
|
ItemKind::Union(ref variant_data, generics) => UnionItem(Union {
|
||||||
generics: generics.clean(cx),
|
generics: generics.clean(cx),
|
||||||
@ -1961,7 +1955,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||||||
def_id,
|
def_id,
|
||||||
items,
|
items,
|
||||||
generics: generics.clean(cx),
|
generics: generics.clean(cx),
|
||||||
bounds: bounds.iter().filter_map(|x| x.clean(cx)).collect(),
|
bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ItemKind::ExternCrate(orig_name) => {
|
ItemKind::ExternCrate(orig_name) => {
|
||||||
@ -2241,7 +2235,7 @@ fn clean_type_binding<'tcx>(
|
|||||||
TypeBindingKind::Equality { term: clean_hir_term(term, cx) }
|
TypeBindingKind::Equality { term: clean_hir_term(term, cx) }
|
||||||
}
|
}
|
||||||
hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint {
|
hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint {
|
||||||
bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(),
|
bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,18 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
//~^ ERROR expected item, found `require`
|
||||||
|
|
||||||
|
use std::time::Instant;
|
||||||
|
//~^ ERROR expected item, found `include`
|
||||||
|
|
||||||
pub use std::io;
|
pub use std::io;
|
||||||
//~^ ERROR expected item, found `using`
|
//~^ ERROR expected item, found `using`
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Rc::new(1);
|
let x = Rc::new(1);
|
||||||
let _ = write!(io::stdout(), "{:?}", x);
|
let _ = write!(io::stdout(), "{:?}", x);
|
||||||
|
let _ = Duration::new(5, 0);
|
||||||
|
let _ = Instant::now();
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,18 @@ import std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
require std::time::Duration;
|
||||||
|
//~^ ERROR expected item, found `require`
|
||||||
|
|
||||||
|
include std::time::Instant;
|
||||||
|
//~^ ERROR expected item, found `include`
|
||||||
|
|
||||||
pub using std::io;
|
pub using std::io;
|
||||||
//~^ ERROR expected item, found `using`
|
//~^ ERROR expected item, found `using`
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Rc::new(1);
|
let x = Rc::new(1);
|
||||||
let _ = write!(io::stdout(), "{:?}", x);
|
let _ = write!(io::stdout(), "{:?}", x);
|
||||||
|
let _ = Duration::new(5, 0);
|
||||||
|
let _ = Instant::now();
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,23 @@ error: expected item, found `import`
|
|||||||
LL | import std::{
|
LL | import std::{
|
||||||
| ^^^^^^ help: items are imported using the `use` keyword
|
| ^^^^^^ help: items are imported using the `use` keyword
|
||||||
|
|
||||||
|
error: expected item, found `require`
|
||||||
|
--> $DIR/use_instead_of_import.rs:9:1
|
||||||
|
|
|
||||||
|
LL | require std::time::Duration;
|
||||||
|
| ^^^^^^^ help: items are imported using the `use` keyword
|
||||||
|
|
||||||
|
error: expected item, found `include`
|
||||||
|
--> $DIR/use_instead_of_import.rs:12:1
|
||||||
|
|
|
||||||
|
LL | include std::time::Instant;
|
||||||
|
| ^^^^^^^ help: items are imported using the `use` keyword
|
||||||
|
|
||||||
error: expected item, found `using`
|
error: expected item, found `using`
|
||||||
--> $DIR/use_instead_of_import.rs:9:5
|
--> $DIR/use_instead_of_import.rs:15:5
|
||||||
|
|
|
|
||||||
LL | pub using std::io;
|
LL | pub using std::io;
|
||||||
| ^^^^^ help: items are imported using the `use` keyword
|
| ^^^^^ help: items are imported using the `use` keyword
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -31,6 +31,14 @@ LL | | }
|
|||||||
|
|
|
|
||||||
= note: expected type `!`
|
= note: expected type `!`
|
||||||
found unit type `()`
|
found unit type `()`
|
||||||
|
note: the function expects a value to always be returned, but loops might run zero times
|
||||||
|
--> $DIR/break-while-condition.rs:24:13
|
||||||
|
|
|
||||||
|
LL | while false {
|
||||||
|
| ^^^^^^^^^^^ this might have zero elements to iterate on
|
||||||
|
LL | return
|
||||||
|
| ------ if the loop doesn't execute, this value would never get returned
|
||||||
|
= help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
15
src/test/ui/let-else/issue-100103.rs
Normal file
15
src/test/ui/let-else/issue-100103.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// edition:2021
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(try_blocks)]
|
||||||
|
#![feature(let_else)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: Result<i32, i32> = try {
|
||||||
|
let Some(x) = Some(0) else {
|
||||||
|
Err(1)?
|
||||||
|
};
|
||||||
|
|
||||||
|
x
|
||||||
|
};
|
||||||
|
}
|
9
src/test/ui/typeck/issue-98982.rs
Normal file
9
src/test/ui/typeck/issue-98982.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
fn foo() -> i32 {
|
||||||
|
for i in 0..0 {
|
||||||
|
//~^ ERROR: mismatched types [E0308]
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
//~| help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
24
src/test/ui/typeck/issue-98982.stderr
Normal file
24
src/test/ui/typeck/issue-98982.stderr
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-98982.rs:2:5
|
||||||
|
|
|
||||||
|
LL | fn foo() -> i32 {
|
||||||
|
| --- expected `i32` because of return type
|
||||||
|
LL | / for i in 0..0 {
|
||||||
|
LL | |
|
||||||
|
LL | | return i;
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected `i32`, found `()`
|
||||||
|
|
|
||||||
|
note: the function expects a value to always be returned, but loops might run zero times
|
||||||
|
--> $DIR/issue-98982.rs:2:5
|
||||||
|
|
|
||||||
|
LL | for i in 0..0 {
|
||||||
|
| ^^^^^^^^^^^^^ this might have zero elements to iterate on
|
||||||
|
LL |
|
||||||
|
LL | return i;
|
||||||
|
| -------- if the loop doesn't execute, this value would never get returned
|
||||||
|
= help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user