Auto merge of #108620 - Dylan-DPC:rollup-o5c4evy, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #108143 (rustdoc: search by macro when query ends with `!`) - #108394 (Make `x doc --open` work on every book) - #108427 (Recover from for-else and while-else) - #108462 (Fix `VecDeque::append` capacity overflow for ZSTs) - #108568 (Make associated_item_def_ids for traits use an unstable option to also return associated types for RPITITs) - #108604 (Add regression test for #107280) - #108605 (Add regression test for #105821) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f77bfb7336
@ -1101,9 +1101,18 @@ fn should_encode_const(def_kind: DefKind) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Return `false` to avoid encoding impl trait in trait, while we don't use the query.
|
||||
fn should_encode_fn_impl_trait_in_trait<'tcx>(_tcx: TyCtxt<'tcx>, _def_id: DefId) -> bool {
|
||||
false
|
||||
// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
|
||||
// option.
|
||||
fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
|
||||
if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
|
||||
&& let Some(assoc_item) = tcx.opt_associated_item(def_id)
|
||||
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
|
||||
&& assoc_item.kind == ty::AssocKind::Fn
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
@ -177,6 +177,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
}
|
||||
};
|
||||
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
|
||||
providers.opt_rpitit_info = |_, _| None;
|
||||
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
|
||||
providers.expn_that_defined = |tcx, id| {
|
||||
let id = id.expect_local();
|
||||
|
@ -90,6 +90,7 @@ rustc_queries! {
|
||||
/// Definitions that were generated with no HIR, would be feeded to return `None`.
|
||||
query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
|
||||
desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Gives access to the HIR node's parent for the HIR owner `key`.
|
||||
@ -166,6 +167,7 @@ rustc_queries! {
|
||||
}
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
|
||||
@ -222,6 +224,7 @@ rustc_queries! {
|
||||
arena_cache
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
|
||||
@ -264,6 +267,7 @@ rustc_queries! {
|
||||
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Elaborated version of the predicates from `explicit_item_bounds`.
|
||||
@ -588,6 +592,7 @@ rustc_queries! {
|
||||
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Returns the inferred outlives predicates (e.g., for `struct
|
||||
@ -596,6 +601,7 @@ rustc_queries! {
|
||||
desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Maps from the `DefId` of a trait to the list of
|
||||
@ -728,6 +734,7 @@ rustc_queries! {
|
||||
desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Collects the associated items defined on a trait or impl.
|
||||
@ -1142,6 +1149,15 @@ rustc_queries! {
|
||||
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
/// The `opt_rpitit_info` query returns the pair of the def id of the function where the RPIT
|
||||
/// is defined and the opaque def id if any.
|
||||
query opt_rpitit_info(def_id: DefId) -> Option<ty::ImplTraitInTraitData> {
|
||||
desc { |tcx| "opt_rpitit_info `{}`", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Gets the span for the definition.
|
||||
@ -1157,6 +1173,7 @@ rustc_queries! {
|
||||
desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
query lookup_stability(def_id: DefId) -> Option<attr::Stability> {
|
||||
@ -1498,6 +1515,7 @@ rustc_queries! {
|
||||
desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
query check_well_formed(key: hir::OwnerId) -> () {
|
||||
@ -1695,6 +1713,7 @@ rustc_queries! {
|
||||
query visibility(def_id: DefId) -> ty::Visibility<DefId> {
|
||||
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
|
||||
separate_provide_extern
|
||||
feedable
|
||||
}
|
||||
|
||||
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
|
||||
|
@ -2071,6 +2071,12 @@ pub enum ImplOverlapKind {
|
||||
Issue33140,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum ImplTraitInTraitData {
|
||||
Trait { fn_def_id: DefId, opaque_def_id: DefId },
|
||||
Impl { fn_def_id: DefId },
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
|
||||
self.typeck(self.hir().body_owner_def_id(body))
|
||||
|
@ -151,6 +151,10 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop
|
||||
parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
|
||||
.suggestion = try adding an expression to the `for` loop
|
||||
|
||||
parse_loop_else = `{$loop_kind}...else` loops are not supported
|
||||
.note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
.loop_keyword = `else` is attached to this loop
|
||||
|
||||
parse_missing_comma_after_match_arm = expected `,` following `match` arm
|
||||
.suggestion = missing a comma here to end this `match` arm
|
||||
|
||||
|
@ -451,6 +451,17 @@ pub(crate) struct MissingExpressionInForLoop {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_loop_else)]
|
||||
#[note]
|
||||
pub(crate) struct LoopElseNotSupported {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub loop_kind: &'static str,
|
||||
#[label(parse_loop_keyword)]
|
||||
pub loop_kw: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_missing_comma_after_match_arm)]
|
||||
pub(crate) struct MissingCommaAfterMatchArm {
|
||||
|
@ -2503,9 +2503,27 @@ impl<'a> Parser<'a> {
|
||||
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
|
||||
|
||||
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
|
||||
|
||||
self.recover_loop_else("for", lo)?;
|
||||
|
||||
Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
|
||||
}
|
||||
|
||||
/// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
|
||||
fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
|
||||
if self.token.is_keyword(kw::Else) && self.may_recover() {
|
||||
let else_span = self.token.span;
|
||||
self.bump();
|
||||
let else_clause = self.parse_expr_else()?;
|
||||
self.sess.emit_err(errors::LoopElseNotSupported {
|
||||
span: else_span.to(else_clause.span),
|
||||
loop_kind,
|
||||
loop_kw,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_missing_in_for_loop(&mut self) {
|
||||
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
|
||||
// Possibly using JS syntax (#75311).
|
||||
@ -2530,6 +2548,9 @@ impl<'a> Parser<'a> {
|
||||
err.span_label(cond.span, "this `while` condition successfully parsed");
|
||||
err
|
||||
})?;
|
||||
|
||||
self.recover_loop_else("while", lo)?;
|
||||
|
||||
Ok(self.mk_expr_with_attrs(
|
||||
lo.to(self.prev_token.span),
|
||||
ExprKind::While(cond, body, opt_label),
|
||||
@ -2541,6 +2562,7 @@ impl<'a> Parser<'a> {
|
||||
fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let loop_span = self.prev_token.span;
|
||||
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
self.recover_loop_else("loop", lo)?;
|
||||
Ok(self.mk_expr_with_attrs(
|
||||
lo.to(self.prev_token.span),
|
||||
ExprKind::Loop(body, opt_label, loop_span),
|
||||
|
@ -1503,6 +1503,9 @@ options! {
|
||||
"what location details should be tracked when using caller_location, either \
|
||||
`none`, or a comma separated list of location details, for which \
|
||||
valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
|
||||
lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
|
||||
"modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
|
||||
generic associated types"),
|
||||
ls: bool = (false, parse_bool, [UNTRACKED],
|
||||
"list the symbols defined by a library crate (default: no)"),
|
||||
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -4,7 +4,8 @@ use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
||||
use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, InternalSubsts, TyCtxt};
|
||||
use rustc_span::symbol::kw;
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers {
|
||||
@ -21,9 +22,37 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||
fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
|
||||
let item = tcx.hir().expect_item(def_id.expect_local());
|
||||
match item.kind {
|
||||
hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
|
||||
trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
|
||||
),
|
||||
hir::ItemKind::Trait(.., ref trait_item_refs) => {
|
||||
if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
|
||||
// We collect RPITITs for each trait method's return type and create a
|
||||
// corresponding associated item using associated_items_for_impl_trait_in_trait
|
||||
// query.
|
||||
tcx.arena.alloc_from_iter(
|
||||
trait_item_refs
|
||||
.iter()
|
||||
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
|
||||
.chain(
|
||||
trait_item_refs
|
||||
.iter()
|
||||
.filter(|trait_item_ref| {
|
||||
matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
|
||||
})
|
||||
.flat_map(|trait_item_ref| {
|
||||
let trait_fn_def_id =
|
||||
trait_item_ref.id.owner_id.def_id.to_def_id();
|
||||
tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id)
|
||||
})
|
||||
.map(|def_id| *def_id),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
tcx.arena.alloc_from_iter(
|
||||
trait_item_refs
|
||||
.iter()
|
||||
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
|
||||
)
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
|
||||
impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
|
||||
),
|
||||
@ -193,10 +222,65 @@ fn associated_item_for_impl_trait_in_trait(
|
||||
let span = tcx.def_span(opaque_ty_def_id);
|
||||
let trait_assoc_ty =
|
||||
tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
|
||||
trait_assoc_ty.def_id()
|
||||
|
||||
let local_def_id = trait_assoc_ty.def_id();
|
||||
let def_id = local_def_id.to_def_id();
|
||||
|
||||
trait_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
|
||||
|
||||
// There's no HIR associated with this new synthesized `def_id`, so feed
|
||||
// `opt_local_def_id_to_hir_id` with `None`.
|
||||
trait_assoc_ty.opt_local_def_id_to_hir_id(None);
|
||||
|
||||
// Copy span of the opaque.
|
||||
trait_assoc_ty.def_ident_span(Some(span));
|
||||
|
||||
// Add the def_id of the function and opaque that generated this synthesized associated type.
|
||||
trait_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Trait {
|
||||
fn_def_id,
|
||||
opaque_def_id: opaque_ty_def_id.to_def_id(),
|
||||
}));
|
||||
|
||||
trait_assoc_ty.associated_item(ty::AssocItem {
|
||||
name: kw::Empty,
|
||||
kind: ty::AssocKind::Type,
|
||||
def_id,
|
||||
trait_item_def_id: None,
|
||||
container: ty::TraitContainer,
|
||||
fn_has_self_parameter: false,
|
||||
});
|
||||
|
||||
// Copy visility of the containing function.
|
||||
trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
|
||||
|
||||
// Copy impl_defaultness of the containing function.
|
||||
trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
|
||||
|
||||
// Copy type_of of the opaque.
|
||||
trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
|
||||
opaque_ty_def_id.to_def_id(),
|
||||
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
|
||||
)));
|
||||
|
||||
// Copy generics_of of the opaque.
|
||||
trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
|
||||
|
||||
// There are no predicates for the synthesized associated type.
|
||||
trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
|
||||
parent: Some(trait_def_id),
|
||||
predicates: &[],
|
||||
});
|
||||
|
||||
// There are no inferred outlives for the synthesized associated type.
|
||||
trait_assoc_ty.inferred_outlives_of(&[]);
|
||||
|
||||
// FIXME implement this.
|
||||
trait_assoc_ty.explicit_item_bounds(&[]);
|
||||
|
||||
local_def_id
|
||||
}
|
||||
|
||||
/// Given an `trait_assoc_def_id` that corresponds to a previously synthethized impl trait in trait
|
||||
/// Given an `trait_assoc_def_id` that corresponds to a previously synthesized impl trait in trait
|
||||
/// into an associated type and an `impl_def_id` corresponding to an impl block, create and return
|
||||
/// the corresponding associated item inside the impl block.
|
||||
fn impl_associated_item_for_impl_trait_in_trait(
|
||||
|
@ -1924,7 +1924,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
#[stable(feature = "append", since = "1.4.0")]
|
||||
pub fn append(&mut self, other: &mut Self) {
|
||||
if T::IS_ZST {
|
||||
self.len += other.len;
|
||||
self.len = self.len.checked_add(other.len).expect("capacity overflow");
|
||||
other.len = 0;
|
||||
other.head = 0;
|
||||
return;
|
||||
|
@ -1045,6 +1045,20 @@ fn test_append_double_drop() {
|
||||
assert_eq!(count_b, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_append_zst_capacity_overflow() {
|
||||
let mut v = Vec::with_capacity(usize::MAX);
|
||||
// note: using resize instead of set_len here would
|
||||
// be *extremely* slow in unoptimized builds.
|
||||
// SAFETY: `v` has capacity `usize::MAX`, and no initialization
|
||||
// is needed for empty tuples.
|
||||
unsafe { v.set_len(usize::MAX) };
|
||||
let mut v = VecDeque::from(v);
|
||||
let mut w = vec![()].into();
|
||||
v.append(&mut w);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retain() {
|
||||
let mut buf = VecDeque::new();
|
||||
|
@ -62,6 +62,7 @@ macro_rules! book {
|
||||
target: self.target,
|
||||
name: INTERNER.intern_str($book_name),
|
||||
src: INTERNER.intern_path(builder.src.join($path)),
|
||||
parent: Some(self),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -119,18 +120,20 @@ impl Step for UnstableBook {
|
||||
target: self.target,
|
||||
name: INTERNER.intern_str("unstable-book"),
|
||||
src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
|
||||
parent: Some(self),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
struct RustbookSrc {
|
||||
struct RustbookSrc<P: Step> {
|
||||
target: TargetSelection,
|
||||
name: Interned<String>,
|
||||
src: Interned<PathBuf>,
|
||||
parent: Option<P>,
|
||||
}
|
||||
|
||||
impl Step for RustbookSrc {
|
||||
impl<P: Step> Step for RustbookSrc<P> {
|
||||
type Output = ();
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
@ -152,13 +155,18 @@ impl Step for RustbookSrc {
|
||||
let index = out.join("index.html");
|
||||
let rustbook = builder.tool_exe(Tool::Rustbook);
|
||||
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
|
||||
if builder.config.dry_run() || up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
|
||||
return;
|
||||
}
|
||||
builder.info(&format!("Rustbook ({}) - {}", target, name));
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
|
||||
builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
|
||||
if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index))
|
||||
{
|
||||
builder.info(&format!("Rustbook ({}) - {}", target, name));
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
|
||||
builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
|
||||
}
|
||||
|
||||
if self.parent.is_some() {
|
||||
builder.maybe_open_in_browser::<P>(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,6 +213,7 @@ impl Step for TheBook {
|
||||
target,
|
||||
name: INTERNER.intern_str("book"),
|
||||
src: INTERNER.intern_path(builder.src.join(&relative_path)),
|
||||
parent: Some(self),
|
||||
});
|
||||
|
||||
// building older edition redirects
|
||||
@ -213,6 +222,9 @@ impl Step for TheBook {
|
||||
target,
|
||||
name: INTERNER.intern_string(format!("book/{}", edition)),
|
||||
src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)),
|
||||
// There should only be one book that is marked as the parent for each target, so
|
||||
// treat the other editions as not having a parent.
|
||||
parent: Option::<Self>::None,
|
||||
});
|
||||
}
|
||||
|
||||
@ -228,10 +240,6 @@ impl Step for TheBook {
|
||||
|
||||
invoke_rustdoc(builder, compiler, &shared_assets, target, path);
|
||||
}
|
||||
|
||||
let out = builder.doc_out(target);
|
||||
let index = out.join("book").join("index.html");
|
||||
builder.maybe_open_in_browser::<Self>(index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1032,10 +1040,7 @@ impl Step for RustcBook {
|
||||
target: self.target,
|
||||
name: INTERNER.intern_str("rustc"),
|
||||
src: INTERNER.intern_path(out_base),
|
||||
parent: Some(self),
|
||||
});
|
||||
|
||||
let out = builder.doc_out(self.target);
|
||||
let index = out.join("rustc").join("index.html");
|
||||
builder.maybe_open_in_browser::<Self>(index);
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,9 @@ When typing in the search bar, you can prefix your search term with a type
|
||||
followed by a colon (such as `mod:`) to restrict the results to just that
|
||||
kind of item. (The available items are listed in the help popup.)
|
||||
|
||||
Searching for `println!` will search for a macro named `println`, just like
|
||||
searching for `macro:println` does.
|
||||
|
||||
### Changing displayed theme
|
||||
|
||||
You can change the displayed theme by opening the settings menu (the gear
|
||||
|
@ -300,20 +300,21 @@ function initSearch(rawSearchIndex) {
|
||||
* @return {integer}
|
||||
*/
|
||||
function getIdentEndPosition(parserState) {
|
||||
const start = parserState.pos;
|
||||
let end = parserState.pos;
|
||||
let foundExclamation = false;
|
||||
let foundExclamation = -1;
|
||||
while (parserState.pos < parserState.length) {
|
||||
const c = parserState.userQuery[parserState.pos];
|
||||
if (!isIdentCharacter(c)) {
|
||||
if (c === "!") {
|
||||
if (foundExclamation) {
|
||||
if (foundExclamation !== -1) {
|
||||
throw new Error("Cannot have more than one `!` in an ident");
|
||||
} else if (parserState.pos + 1 < parserState.length &&
|
||||
isIdentCharacter(parserState.userQuery[parserState.pos + 1])
|
||||
) {
|
||||
throw new Error("`!` can only be at the end of an ident");
|
||||
}
|
||||
foundExclamation = true;
|
||||
foundExclamation = parserState.pos;
|
||||
} else if (isErrorCharacter(c)) {
|
||||
throw new Error(`Unexpected \`${c}\``);
|
||||
} else if (
|
||||
@ -326,9 +327,18 @@ function initSearch(rawSearchIndex) {
|
||||
if (!isPathStart(parserState)) {
|
||||
break;
|
||||
}
|
||||
if (foundExclamation !== -1) {
|
||||
if (start <= (end - 2)) {
|
||||
throw new Error("Cannot have associated items in macros");
|
||||
} else {
|
||||
// if start == end - 1, we got the never type
|
||||
// while the never type has no associated macros, we still
|
||||
// can parse a path like that
|
||||
foundExclamation = -1;
|
||||
}
|
||||
}
|
||||
// Skip current ":".
|
||||
parserState.pos += 1;
|
||||
foundExclamation = false;
|
||||
} else {
|
||||
throw new Error(`Unexpected \`${c}\``);
|
||||
}
|
||||
@ -336,6 +346,16 @@ function initSearch(rawSearchIndex) {
|
||||
parserState.pos += 1;
|
||||
end = parserState.pos;
|
||||
}
|
||||
// if start == end - 1, we got the never type
|
||||
if (foundExclamation !== -1 && start <= (end - 2)) {
|
||||
if (parserState.typeFilter === null) {
|
||||
parserState.typeFilter = "macro";
|
||||
} else if (parserState.typeFilter !== "macro") {
|
||||
throw new Error("Invalid search type: macro `!` and " +
|
||||
`\`${parserState.typeFilter}\` both specified`);
|
||||
}
|
||||
end = foundExclamation;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
@ -589,8 +609,8 @@ function initSearch(rawSearchIndex) {
|
||||
*
|
||||
* The supported syntax by this parser is as follow:
|
||||
*
|
||||
* ident = *(ALPHA / DIGIT / "_") [!]
|
||||
* path = ident *(DOUBLE-COLON ident)
|
||||
* ident = *(ALPHA / DIGIT / "_")
|
||||
* path = ident *(DOUBLE-COLON ident) [!]
|
||||
* arg = path [generics]
|
||||
* arg-without-generic = path
|
||||
* type-sep = COMMA/WS *(COMMA/WS)
|
||||
|
@ -37,6 +37,8 @@ const QUERY = [
|
||||
"mod : :",
|
||||
"a!a",
|
||||
"a!!",
|
||||
"mod:a!",
|
||||
"a!::a",
|
||||
];
|
||||
|
||||
const PARSED = [
|
||||
@ -382,4 +384,22 @@ const PARSED = [
|
||||
userQuery: "a!!",
|
||||
error: 'Cannot have more than one `!` in an ident',
|
||||
},
|
||||
{
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
original: "mod:a!",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "mod:a!",
|
||||
error: 'Invalid search type: macro `!` and `mod` both specified',
|
||||
},
|
||||
{
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
original: "a!::a",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "a!::a",
|
||||
error: 'Cannot have associated items in macros',
|
||||
},
|
||||
];
|
||||
|
@ -1,4 +1,4 @@
|
||||
const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
|
||||
const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo', 'macro!', 'macro:mac!', 'a::mac!'];
|
||||
|
||||
const PARSED = [
|
||||
{
|
||||
@ -40,4 +40,49 @@ const PARSED = [
|
||||
userQuery: "macro<f>:foo",
|
||||
error: "Unexpected `:`",
|
||||
},
|
||||
{
|
||||
elems: [{
|
||||
name: "macro",
|
||||
fullPath: ["macro"],
|
||||
pathWithoutLast: [],
|
||||
pathLast: "macro",
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
original: "macro!",
|
||||
returned: [],
|
||||
typeFilter: 14,
|
||||
userQuery: "macro!",
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
elems: [{
|
||||
name: "mac",
|
||||
fullPath: ["mac"],
|
||||
pathWithoutLast: [],
|
||||
pathLast: "mac",
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
original: "macro:mac!",
|
||||
returned: [],
|
||||
typeFilter: 14,
|
||||
userQuery: "macro:mac!",
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
elems: [{
|
||||
name: "a::mac",
|
||||
fullPath: ["a", "mac"],
|
||||
pathWithoutLast: ["a"],
|
||||
pathLast: "mac",
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
original: "a::mac!",
|
||||
returned: [],
|
||||
typeFilter: 14,
|
||||
userQuery: "a::mac!",
|
||||
error: null,
|
||||
},
|
||||
];
|
||||
|
@ -3,6 +3,7 @@ const QUERY = [
|
||||
"!",
|
||||
"a!",
|
||||
"a!::b",
|
||||
"!::b",
|
||||
"a!::b!",
|
||||
];
|
||||
|
||||
@ -47,47 +48,50 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
elems: [{
|
||||
name: "a!",
|
||||
fullPath: ["a!"],
|
||||
name: "a",
|
||||
fullPath: ["a"],
|
||||
pathWithoutLast: [],
|
||||
pathLast: "a!",
|
||||
pathLast: "a",
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
original: "a!",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
typeFilter: 14,
|
||||
userQuery: "a!",
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
elems: [{
|
||||
name: "a!::b",
|
||||
fullPath: ["a!", "b"],
|
||||
pathWithoutLast: ["a!"],
|
||||
pathLast: "b",
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
original: "a!::b",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "a!::b",
|
||||
error: null,
|
||||
error: "Cannot have associated items in macros",
|
||||
},
|
||||
{
|
||||
elems: [{
|
||||
name: "a!::b!",
|
||||
fullPath: ["a!", "b!"],
|
||||
pathWithoutLast: ["a!"],
|
||||
pathLast: "b!",
|
||||
name: "!::b",
|
||||
fullPath: ["!", "b"],
|
||||
pathWithoutLast: ["!"],
|
||||
pathLast: "b",
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
original: "!::b",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "!::b",
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
original: "a!::b!",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "a!::b!",
|
||||
error: null,
|
||||
error: "Cannot have associated items in macros",
|
||||
},
|
||||
];
|
||||
|
10
tests/rustdoc-js/macro-search.js
Normal file
10
tests/rustdoc-js/macro-search.js
Normal file
@ -0,0 +1,10 @@
|
||||
// exact-check
|
||||
|
||||
const QUERY = 'abracadabra!';
|
||||
|
||||
const EXPECTED = {
|
||||
'others': [
|
||||
{ 'path': 'macro_search', 'name': 'abracadabra' },
|
||||
{ 'path': 'macro_search', 'name': 'abracadabra_b' },
|
||||
],
|
||||
};
|
10
tests/rustdoc-js/macro-search.rs
Normal file
10
tests/rustdoc-js/macro-search.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#[macro_export]
|
||||
macro_rules! abracadabra {
|
||||
() => {}
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! abracadabra_b {
|
||||
() => {}
|
||||
}
|
||||
pub fn abracadabra() {}
|
||||
pub fn abracadabra_c() {}
|
@ -87,6 +87,7 @@
|
||||
-Z llvm-plugins=val -- a list LLVM plugins to enable (space separated)
|
||||
-Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
|
||||
-Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
|
||||
-Z lower-impl-trait-in-trait-to-assoc-ty=val -- modify the lowering strategy for `impl Trait` in traits so that they are lowered to generic associated types
|
||||
-Z ls=val -- list the symbols defined by a library crate (default: no)
|
||||
-Z macro-backtrace=val -- show macro backtraces (default: no)
|
||||
-Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
|
||||
|
15
tests/ui/async-await/issues/issue-107280.rs
Normal file
15
tests/ui/async-await/issues/issue-107280.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// edition:2021
|
||||
|
||||
async fn foo() {
|
||||
inner::<false>().await
|
||||
//~^ ERROR: function takes 2 generic arguments but 1 generic argument was supplied
|
||||
//~| ERROR: type inside `async fn` body must be known in this context
|
||||
//~| ERROR: type inside `async fn` body must be known in this context
|
||||
//~| ERROR: type inside `async fn` body must be known in this context
|
||||
//~| ERROR: type inside `async fn` body must be known in this context
|
||||
//~| ERROR: type inside `async fn` body must be known in this context
|
||||
}
|
||||
|
||||
async fn inner<T, const PING: bool>() {}
|
||||
|
||||
fn main() {}
|
82
tests/ui/async-await/issues/issue-107280.stderr
Normal file
82
tests/ui/async-await/issues/issue-107280.stderr
Normal file
@ -0,0 +1,82 @@
|
||||
error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/issue-107280.rs:4:5
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^ ----- supplied 1 generic argument
|
||||
| |
|
||||
| expected 2 generic arguments
|
||||
|
|
||||
note: function defined here, with 2 generic parameters: `T`, `PING`
|
||||
--> $DIR/issue-107280.rs:13:10
|
||||
|
|
||||
LL | async fn inner<T, const PING: bool>() {}
|
||||
| ^^^^^ - ----------------
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | inner::<false, PING>().await
|
||||
| ++++++
|
||||
|
||||
error[E0698]: type inside `async fn` body must be known in this context
|
||||
--> $DIR/issue-107280.rs:4:5
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/issue-107280.rs:4:21
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async fn` body must be known in this context
|
||||
--> $DIR/issue-107280.rs:4:5
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/issue-107280.rs:4:21
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async fn` body must be known in this context
|
||||
--> $DIR/issue-107280.rs:4:5
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/issue-107280.rs:4:21
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async fn` body must be known in this context
|
||||
--> $DIR/issue-107280.rs:4:5
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/issue-107280.rs:4:21
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^
|
||||
|
||||
error[E0698]: type inside `async fn` body must be known in this context
|
||||
--> $DIR/issue-107280.rs:4:5
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
|
||||
|
|
||||
note: the type is part of the `async fn` body because of this `await`
|
||||
--> $DIR/issue-107280.rs:4:21
|
||||
|
|
||||
LL | inner::<false>().await
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0698.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
23
tests/ui/const-generics/issues/issue-105821.rs
Normal file
23
tests/ui/const-generics/issues/issue-105821.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// check-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(adt_const_params, const_ptr_read, generic_const_exprs)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
const fn catone<const M: usize>(_a: &[u8; M]) -> [u8; M + 1]
|
||||
where
|
||||
[(); M + 1]:,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
struct Catter<const A: &'static [u8]>;
|
||||
impl<const A: &'static [u8]> Catter<A>
|
||||
where
|
||||
[(); A.len() + 1]:,
|
||||
{
|
||||
const ZEROS: &'static [u8; A.len()] = &[0_u8; A.len()];
|
||||
const R: &'static [u8] = &catone(Self::ZEROS);
|
||||
}
|
||||
|
||||
fn main() {}
|
8
tests/ui/for/for-else-err.rs
Normal file
8
tests/ui/for/for-else-err.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
for _ in 0..1 {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
} else {
|
||||
//~^ ERROR `for...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
}
|
||||
}
|
17
tests/ui/for/for-else-err.stderr
Normal file
17
tests/ui/for/for-else-err.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: `for...else` loops are not supported
|
||||
--> $DIR/for-else-err.rs:4:7
|
||||
|
|
||||
LL | for _ in 0..1 {
|
||||
| --- `else` is attached to this loop
|
||||
LL |
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
8
tests/ui/for/for-else-let-else-err.rs
Normal file
8
tests/ui/for/for-else-let-else-err.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let _ = for _ in 0..1 {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
} else {
|
||||
//~^ ERROR `for...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
};
|
||||
}
|
17
tests/ui/for/for-else-let-else-err.stderr
Normal file
17
tests/ui/for/for-else-let-else-err.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: `for...else` loops are not supported
|
||||
--> $DIR/for-else-let-else-err.rs:4:7
|
||||
|
|
||||
LL | let _ = for _ in 0..1 {
|
||||
| --- `else` is attached to this loop
|
||||
LL |
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -7,10 +7,6 @@ fn main() {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
};
|
||||
let Some(1) = (loop { break Some(1) }) else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
};
|
||||
let 2 = 1 + (match 1 { n => n }) else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
|
@ -7,10 +7,6 @@ fn main() {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
};
|
||||
let Some(1) = loop { break Some(1) } else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
};
|
||||
let 2 = 1 + match 1 { n => n } else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
|
@ -10,18 +10,7 @@ LL | let Some(1) = ({ Some(1) }) else {
|
||||
| + +
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/let-else-brace-before-else.rs:10:40
|
||||
|
|
||||
LL | let Some(1) = loop { break Some(1) } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL | let Some(1) = (loop { break Some(1) }) else {
|
||||
| + +
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/let-else-brace-before-else.rs:14:34
|
||||
--> $DIR/let-else-brace-before-else.rs:10:34
|
||||
|
|
||||
LL | let 2 = 1 + match 1 { n => n } else {
|
||||
| ^
|
||||
@ -32,7 +21,7 @@ LL | let 2 = 1 + (match 1 { n => n }) else {
|
||||
| + +
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/let-else-brace-before-else.rs:18:40
|
||||
--> $DIR/let-else-brace-before-else.rs:14:40
|
||||
|
|
||||
LL | let Some(1) = unsafe { unsafe_fn() } else {
|
||||
| ^
|
||||
@ -42,5 +31,5 @@ help: wrap the expression in parentheses
|
||||
LL | let Some(1) = (unsafe { unsafe_fn() }) else {
|
||||
| + +
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
10
tests/ui/loops/loop-else-break-with-value.rs
Normal file
10
tests/ui/loops/loop-else-break-with-value.rs
Normal file
@ -0,0 +1,10 @@
|
||||
fn main() {
|
||||
let Some(1) = loop {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
break Some(1)
|
||||
} else {
|
||||
//~^ ERROR `loop...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
return;
|
||||
};
|
||||
}
|
18
tests/ui/loops/loop-else-break-with-value.stderr
Normal file
18
tests/ui/loops/loop-else-break-with-value.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error: `loop...else` loops are not supported
|
||||
--> $DIR/loop-else-break-with-value.rs:5:7
|
||||
|
|
||||
LL | let Some(1) = loop {
|
||||
| ---- `else` is attached to this loop
|
||||
...
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | return;
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
8
tests/ui/loops/loop-else-err.rs
Normal file
8
tests/ui/loops/loop-else-err.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
loop {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
} else {
|
||||
//~^ ERROR `loop...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
}
|
||||
}
|
17
tests/ui/loops/loop-else-err.stderr
Normal file
17
tests/ui/loops/loop-else-err.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: `loop...else` loops are not supported
|
||||
--> $DIR/loop-else-err.rs:4:7
|
||||
|
|
||||
LL | loop {
|
||||
| ---- `else` is attached to this loop
|
||||
LL |
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
8
tests/ui/loops/loop-else-let-else-err.rs
Normal file
8
tests/ui/loops/loop-else-let-else-err.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let _ = loop {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
} else {
|
||||
//~^ ERROR `loop...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
};
|
||||
}
|
17
tests/ui/loops/loop-else-let-else-err.stderr
Normal file
17
tests/ui/loops/loop-else-let-else-err.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: `loop...else` loops are not supported
|
||||
--> $DIR/loop-else-let-else-err.rs:4:7
|
||||
|
|
||||
LL | let _ = loop {
|
||||
| ---- `else` is attached to this loop
|
||||
LL |
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
8
tests/ui/while/while-else-err.rs
Normal file
8
tests/ui/while/while-else-err.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
while false {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
} else {
|
||||
//~^ ERROR `while...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
};
|
||||
}
|
17
tests/ui/while/while-else-err.stderr
Normal file
17
tests/ui/while/while-else-err.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: `while...else` loops are not supported
|
||||
--> $DIR/while-else-err.rs:4:7
|
||||
|
|
||||
LL | while false {
|
||||
| ----- `else` is attached to this loop
|
||||
LL |
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
8
tests/ui/while/while-else-let-else-err.rs
Normal file
8
tests/ui/while/while-else-let-else-err.rs
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let _ = while false {
|
||||
//~^ NOTE `else` is attached to this loop
|
||||
} else {
|
||||
//~^ ERROR `while...else` loops are not supported
|
||||
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
};
|
||||
}
|
17
tests/ui/while/while-else-let-else-err.stderr
Normal file
17
tests/ui/while/while-else-let-else-err.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error: `while...else` loops are not supported
|
||||
--> $DIR/while-else-let-else-err.rs:4:7
|
||||
|
|
||||
LL | let _ = while false {
|
||||
| ----- `else` is attached to this loop
|
||||
LL |
|
||||
LL | } else {
|
||||
| _______^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____^
|
||||
|
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
x
Reference in New Issue
Block a user