Auto merge of #30826 - nagisa:rollup, r=nagisa
- Successful merges: #30538, #30687, #30694, #30737, #30761, #30768, #30774, #30798, #30808, #30812, #30814 - Failed merges:
This commit is contained in:
commit
4405944b94
@ -303,10 +303,10 @@ prints the string to the screen. Easy enough!
|
||||
|
||||
[statically allocated]: the-stack-and-the-heap.html
|
||||
|
||||
The line ends with a semicolon (`;`). Rust is an *[expression oriented]*
|
||||
language, which means that most things are expressions, rather than statements.
|
||||
The `;` indicates that this expression is over, and the next one is ready to
|
||||
begin. Most lines of Rust code end with a `;`.
|
||||
The line ends with a semicolon (`;`). Rust is an *[expression-oriented
|
||||
language]*, which means that most things are expressions, rather than
|
||||
statements. The `;` indicates that this expression is over, and the next one is
|
||||
ready to begin. Most lines of Rust code end with a `;`.
|
||||
|
||||
[expression-oriented language]: glossary.html#expression-oriented-language
|
||||
|
||||
|
@ -10,12 +10,28 @@ This is an index of the documentation included with the Rust
|
||||
compiler. For more comprehensive documentation see [the
|
||||
website](https://www.rust-lang.org).
|
||||
|
||||
[**The Rust Programming Language**](book/index.html)
|
||||
[**The Rust Programming Language**][book]. Also known as "The Book",
|
||||
The Rust Programming Language is the most comprehensive resource for
|
||||
all topics related to Rust, and is the primary official document of
|
||||
the language.
|
||||
|
||||
[**The Rust Reference**](reference.html)
|
||||
[**The Rust Reference**][ref]. While Rust does not have a
|
||||
specification, the reference tries to describe its working in
|
||||
detail. It tends to be out of date.
|
||||
|
||||
[**The Standard Library API Reference**](std/index.html)
|
||||
[**Standard Library API Reference**][api]. Documentation for the
|
||||
standard library.
|
||||
|
||||
[**The Rustonomicon**](nomicon/index.html)
|
||||
[**The Rustonomicon**][nomicon]. An entire book dedicated to
|
||||
explaining how to write unsafe Rust code. It is for advanced Rust
|
||||
programmers.
|
||||
|
||||
[**Compiler Error Index**][err]. Extended explanations of
|
||||
the errors produced by the Rust compiler.
|
||||
|
||||
[book]: book/index.html
|
||||
[ref]: reference.html
|
||||
[api]: std/index.html
|
||||
[nomicon]: nomicon/index.html
|
||||
[err]: error-index.html
|
||||
|
||||
[**The Compiler Error Index**](error-index.html)
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
* configure.ac: Add --enable-host-shared.
|
||||
* configure: Regenerate.
|
||||
|
||||
|
||||
Copyright (C) 2013-2014 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
|
@ -6,12 +6,12 @@
|
||||
# met:
|
||||
|
||||
# (1) Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
|
||||
# (2) Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# distribution.
|
||||
|
||||
# (3) The name of the author may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
|
@ -23,12 +23,12 @@
|
||||
# met:
|
||||
|
||||
# (1) Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
|
||||
# (2) Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# distribution.
|
||||
|
||||
# (3) The name of the author may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
@ -137,10 +137,10 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
|
||||
$(btest_SOURCES) $(stest_SOURCES)
|
||||
MULTISRCTOP =
|
||||
MULTIBUILDTOP =
|
||||
MULTIDIRS =
|
||||
MULTISUBDIR =
|
||||
MULTISRCTOP =
|
||||
MULTIBUILDTOP =
|
||||
MULTIDIRS =
|
||||
MULTISUBDIR =
|
||||
MULTIDO = true
|
||||
MULTICLEAN = true
|
||||
am__can_run_installinfo = \
|
||||
@ -389,7 +389,7 @@ config.h: stamp-h1
|
||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
@ -407,7 +407,7 @@ clean-noinstLTLIBRARIES:
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(EXTRA_libbacktrace_la_DEPENDENCIES)
|
||||
libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(EXTRA_libbacktrace_la_DEPENDENCIES)
|
||||
$(LINK) $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS)
|
||||
|
||||
clean-checkPROGRAMS:
|
||||
@ -418,10 +418,10 @@ clean-checkPROGRAMS:
|
||||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIES)
|
||||
btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIES)
|
||||
@rm -f btest$(EXEEXT)
|
||||
$(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)
|
||||
stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES)
|
||||
stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES)
|
||||
@rm -f stest$(EXEEXT)
|
||||
$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
|
||||
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
@ -460,7 +460,7 @@ f23 (int f1line, int f2line)
|
||||
(unsigned int) bdata.index, j + 1);
|
||||
bdata.failed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check ("test3", 0, all, f3line, "f23", &bdata.failed);
|
||||
check ("test3", 1, all, f2line, "f22", &bdata.failed);
|
||||
|
@ -6,13 +6,13 @@
|
||||
# met:
|
||||
|
||||
# (1) Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
|
||||
# (2) Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
|
||||
# distribution.
|
||||
|
||||
# (3) The name of the author may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
@ -1246,7 +1246,7 @@ add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
|
||||
|
||||
static int
|
||||
find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
|
||||
struct dwarf_buf *unit_buf,
|
||||
struct dwarf_buf *unit_buf,
|
||||
const unsigned char *dwarf_str, size_t dwarf_str_size,
|
||||
const unsigned char *dwarf_ranges,
|
||||
size_t dwarf_ranges_size,
|
||||
@ -1605,7 +1605,7 @@ read_line_header (struct backtrace_state *state, struct unit *u,
|
||||
|
||||
if (!advance (line_buf, hdrlen))
|
||||
return 0;
|
||||
|
||||
|
||||
hdr->min_insn_len = read_byte (&hdr_buf);
|
||||
if (hdr->version < 4)
|
||||
hdr->max_ops_per_insn = 1;
|
||||
@ -1614,7 +1614,7 @@ read_line_header (struct backtrace_state *state, struct unit *u,
|
||||
|
||||
/* We don't care about default_is_stmt. */
|
||||
read_byte (&hdr_buf);
|
||||
|
||||
|
||||
hdr->line_base = read_sbyte (&hdr_buf);
|
||||
hdr->line_range = read_byte (&hdr_buf);
|
||||
|
||||
|
@ -47,27 +47,27 @@
|
||||
|
||||
/* This file declares various DWARF-related constants using a set of
|
||||
macros which can be redefined by the including file.
|
||||
|
||||
|
||||
The macros are in sections. Each section corresponds to a single
|
||||
set of DWARF constants and has a corresponding key. The key is
|
||||
used in all the macro names.
|
||||
|
||||
|
||||
The sections are TAG (for DW_TAG_ constants), FORM (DW_FORM_), AT
|
||||
(DW_AT_), OP (DW_OP_), ATE (DW_ATE_), and CFA (DW_CFA_).
|
||||
|
||||
|
||||
Using TAG as an example, the following macros may be used for each
|
||||
key:
|
||||
|
||||
|
||||
DW_FIRST_TAG(name, value) - Introduce the first DW_TAG constant.
|
||||
|
||||
|
||||
DW_TAG(name, value) - Define a subsequent constant.
|
||||
|
||||
|
||||
DW_TAG_DUP(name, value) - Define a subsequent constant whose value
|
||||
is a duplicate of some other constant. Not all keys use the _DUP
|
||||
macro form. If more than one name shares a value, then the base
|
||||
(DW_TAG) form will be the preferred name and DW_TAG_DUP will hold
|
||||
any alternate names.
|
||||
|
||||
|
||||
DW_END_TAG - Invoked at the end of the DW_TAG constants. */
|
||||
|
||||
DW_FIRST_TAG (DW_TAG_padding, 0x00)
|
||||
|
@ -352,7 +352,7 @@ enum dwarf_macro_record_type
|
||||
DW_MACRO_GNU_lo_user = 0xe0,
|
||||
DW_MACRO_GNU_hi_user = 0xff
|
||||
};
|
||||
|
||||
|
||||
/* @@@ For use with GNU frame unwind information. */
|
||||
|
||||
#define DW_EH_PE_absptr 0x00
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
(1) Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
(2) Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
distribution.
|
||||
|
||||
(3) The name of the author may not be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
@ -321,7 +321,6 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
|
||||
///
|
||||
/// [module-level documentation]: index.html
|
||||
/// [impl]: index.html#implementing-iterator
|
||||
#[lang = "iterator"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
|
||||
`.iter()` or a similar method"]
|
||||
|
@ -1822,6 +1822,30 @@ fn main() {
|
||||
// |
|
||||
// type `i32` assigned to variable `x`
|
||||
```
|
||||
|
||||
Another situation in which this occurs is when you attempt to use the `try!`
|
||||
macro inside a function that does not return a `Result<T, E>`:
|
||||
|
||||
```
|
||||
use std::fs::File;
|
||||
|
||||
fn main() {
|
||||
let mut f = try!(File::create("foo.txt"));
|
||||
}
|
||||
```
|
||||
|
||||
This code gives an error like this:
|
||||
|
||||
```text
|
||||
<std macros>:5:8: 6:42 error: mismatched types:
|
||||
expected `()`,
|
||||
found `core::result::Result<_, _>`
|
||||
(expected (),
|
||||
found enum `core::result::Result`) [E0308]
|
||||
```
|
||||
|
||||
`try!` returns a `Result<T, E>`, and so the function must. But `main()` has
|
||||
`()` as its return type, hence the error.
|
||||
"##,
|
||||
|
||||
E0309: r##"
|
||||
|
@ -19,9 +19,8 @@
|
||||
use middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use middle::def::*;
|
||||
use middle::def_id::{DefId};
|
||||
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
|
||||
use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
|
||||
use middle::expr_use_visitor::WriteAndRead;
|
||||
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
|
||||
use middle::expr_use_visitor::{LoanCause, MutateMode};
|
||||
use middle::expr_use_visitor as euv;
|
||||
use middle::infer;
|
||||
use middle::mem_categorization::{cmt};
|
||||
@ -1161,10 +1160,10 @@ fn borrow(&mut self,
|
||||
fn decl_without_init(&mut self, _: NodeId, _: Span) {}
|
||||
fn mutate(&mut self, _: NodeId, span: Span, _: cmt, mode: MutateMode) {
|
||||
match mode {
|
||||
JustWrite | WriteAndRead => {
|
||||
MutateMode::JustWrite | MutateMode::WriteAndRead => {
|
||||
span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
|
||||
}
|
||||
Init => {}
|
||||
MutateMode::Init => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
//! normal visitor, which just walks the entire body in one shot, the
|
||||
//! `ExprUseVisitor` determines how expressions are being used.
|
||||
|
||||
pub use self::MutateMode::*;
|
||||
pub use self::LoanCause::*;
|
||||
pub use self::ConsumeMode::*;
|
||||
pub use self::MoveReason::*;
|
||||
@ -465,7 +464,11 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
|
||||
self.consume_expr(&*output.expr);
|
||||
} else {
|
||||
self.mutate_expr(expr, &*output.expr,
|
||||
if output.is_rw { WriteAndRead } else { JustWrite });
|
||||
if output.is_rw {
|
||||
MutateMode::WriteAndRead
|
||||
} else {
|
||||
MutateMode::JustWrite
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -519,7 +522,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
|
||||
}
|
||||
|
||||
hir::ExprAssign(ref lhs, ref rhs) => {
|
||||
self.mutate_expr(expr, &**lhs, JustWrite);
|
||||
self.mutate_expr(expr, &**lhs, MutateMode::JustWrite);
|
||||
self.consume_expr(&**rhs);
|
||||
}
|
||||
|
||||
@ -532,7 +535,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
|
||||
assert!(::rustc_front::util::is_by_value_binop(op.node));
|
||||
|
||||
if !self.walk_overloaded_operator(expr, lhs, vec![rhs], PassArgs::ByValue) {
|
||||
self.mutate_expr(expr, &**lhs, WriteAndRead);
|
||||
self.mutate_expr(expr, &**lhs, MutateMode::WriteAndRead);
|
||||
self.consume_expr(&**rhs);
|
||||
}
|
||||
}
|
||||
@ -991,7 +994,7 @@ fn walk_pat(&mut self,
|
||||
let def = def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
match mc.cat_def(pat.id, pat.span, pat_ty, def) {
|
||||
Ok(binding_cmt) => {
|
||||
delegate.mutate(pat.id, pat.span, binding_cmt, Init);
|
||||
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
|
||||
}
|
||||
Err(_) => { }
|
||||
}
|
||||
|
@ -314,10 +314,19 @@ pub fn successors_mut(&mut self) -> &mut [BasicBlock] {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destination(&self) -> Option<Lvalue<'tcx>> {
|
||||
pub fn destination(&self) -> Option<&Lvalue<'tcx>> {
|
||||
match *self {
|
||||
CallKind::Converging { ref destination, .. } |
|
||||
CallKind::ConvergingCleanup { ref destination, .. } => Some(destination.clone()),
|
||||
CallKind::ConvergingCleanup { ref destination, .. } => Some(destination),
|
||||
CallKind::Diverging |
|
||||
CallKind::DivergingCleanup(_) => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destination_mut(&mut self) -> Option<&mut Lvalue<'tcx>> {
|
||||
match *self {
|
||||
CallKind::Converging { ref mut destination, .. } |
|
||||
CallKind::ConvergingCleanup { ref mut destination, .. } => Some(destination),
|
||||
CallKind::Diverging |
|
||||
CallKind::DivergingCleanup(_) => None
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
use borrowck::*;
|
||||
use borrowck::InteriorKind::{InteriorElement, InteriorField};
|
||||
use rustc::middle::expr_use_visitor as euv;
|
||||
use rustc::middle::expr_use_visitor::MutateMode;
|
||||
use rustc::middle::infer;
|
||||
use rustc::middle::mem_categorization as mc;
|
||||
use rustc::middle::mem_categorization::Categorization;
|
||||
@ -161,7 +162,7 @@ fn mutate(&mut self,
|
||||
match opt_loan_path(&assignee_cmt) {
|
||||
Some(lp) => {
|
||||
match mode {
|
||||
euv::Init | euv::JustWrite => {
|
||||
MutateMode::Init | MutateMode::JustWrite => {
|
||||
// In a case like `path = 1`, then path does not
|
||||
// have to be *FULLY* initialized, but we still
|
||||
// must be careful lest it contains derefs of
|
||||
@ -171,7 +172,7 @@ fn mutate(&mut self,
|
||||
MovedInUse,
|
||||
&lp);
|
||||
}
|
||||
euv::WriteAndRead => {
|
||||
MutateMode::WriteAndRead => {
|
||||
// In a case like `path += 1`, then path must be
|
||||
// fully initialized, since we will read it before
|
||||
// we write it.
|
||||
|
@ -20,6 +20,7 @@
|
||||
use rustc::middle::dataflow::DataFlowOperator;
|
||||
use rustc::middle::dataflow::KillFrom;
|
||||
use rustc::middle::expr_use_visitor as euv;
|
||||
use rustc::middle::expr_use_visitor::MutateMode;
|
||||
use rustc::middle::ty;
|
||||
use rustc::util::nodemap::{FnvHashMap, NodeSet};
|
||||
|
||||
@ -406,10 +407,10 @@ pub fn add_assignment(&self,
|
||||
self.fragments.borrow_mut().add_assignment(path_index);
|
||||
|
||||
match mode {
|
||||
euv::Init | euv::JustWrite => {
|
||||
MutateMode::Init | MutateMode::JustWrite => {
|
||||
self.assignee_ids.borrow_mut().insert(assignee_id);
|
||||
}
|
||||
euv::WriteAndRead => { }
|
||||
MutateMode::WriteAndRead => { }
|
||||
}
|
||||
|
||||
let assignment = Assignment {
|
||||
|
@ -38,6 +38,7 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(str_char)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
@ -154,4 +155,5 @@ macro_rules! add_lint_group {
|
||||
store.register_renamed("unknown_features", "unused_features");
|
||||
|
||||
store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
|
||||
store.register_removed("negate_unsigned", "cast a signed value instead");
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use middle::{infer};
|
||||
use middle::def_id::DefId;
|
||||
use middle::subst::Substs;
|
||||
@ -24,13 +26,39 @@
|
||||
use syntax::{abi, ast};
|
||||
use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::codemap::{self, Span};
|
||||
use syntax::feature_gate::{emit_feature_err, GateIssue};
|
||||
use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
|
||||
|
||||
use rustc_front::hir;
|
||||
use rustc_front::intravisit::{self, Visitor};
|
||||
use rustc_front::util::is_shift_binop;
|
||||
|
||||
register_long_diagnostics! {
|
||||
E0519: r##"
|
||||
It is not allowed to negate an unsigned integer.
|
||||
You can negate a signed integer and cast it to an
|
||||
unsigned integer or use the `!` operator.
|
||||
|
||||
```
|
||||
let x: usize = -1isize as usize;
|
||||
let y: usize = !0;
|
||||
assert_eq!(x, y);
|
||||
```
|
||||
|
||||
Alternatively you can use the `Wrapping` newtype
|
||||
or the `wrapping_neg` operation that all
|
||||
integral types support:
|
||||
|
||||
```
|
||||
use std::num::Wrapping;
|
||||
let x: Wrapping<usize> = -Wrapping(1);
|
||||
let Wrapping(x) = x;
|
||||
let y: usize = 1.wrapping_neg();
|
||||
assert_eq!(x, y);
|
||||
```
|
||||
|
||||
"##
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
UNUSED_COMPARISONS,
|
||||
Warn,
|
||||
@ -73,30 +101,24 @@ impl LateLintPass for TypeLimits {
|
||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
||||
match e.node {
|
||||
hir::ExprUnary(hir::UnNeg, ref expr) => {
|
||||
match expr.node {
|
||||
hir::ExprLit(ref lit) => {
|
||||
match lit.node {
|
||||
ast::LitInt(_, ast::UnsignedIntLit(_)) => {
|
||||
check_unsigned_negation_feature(cx, e.span);
|
||||
},
|
||||
ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
|
||||
if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
|
||||
check_unsigned_negation_feature(cx, e.span);
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let t = cx.tcx.node_id_to_type(expr.id);
|
||||
match t.sty {
|
||||
ty::TyUint(_) => {
|
||||
check_unsigned_negation_feature(cx, e.span);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
if let hir::ExprLit(ref lit) = expr.node {
|
||||
match lit.node {
|
||||
ast::LitInt(_, ast::UnsignedIntLit(_)) => {
|
||||
forbid_unsigned_negation(cx, e.span);
|
||||
},
|
||||
ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
|
||||
if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
|
||||
forbid_unsigned_negation(cx, e.span);
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
};
|
||||
} else {
|
||||
let t = cx.tcx.node_id_to_type(expr.id);
|
||||
if let ty::TyUint(_) = t.sty {
|
||||
forbid_unsigned_negation(cx, e.span);
|
||||
}
|
||||
}
|
||||
// propagate negation, if the negation itself isn't negated
|
||||
if self.negated_expr_id != e.id {
|
||||
self.negated_expr_id = expr.id;
|
||||
@ -322,15 +344,11 @@ fn is_comparison(binop: hir::BinOp) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_unsigned_negation_feature(cx: &LateContext, span: Span) {
|
||||
if !cx.sess().features.borrow().negate_unsigned {
|
||||
emit_feature_err(
|
||||
&cx.sess().parse_sess.span_diagnostic,
|
||||
"negate_unsigned",
|
||||
span,
|
||||
GateIssue::Language,
|
||||
"unary negation of unsigned integers may be removed in the future");
|
||||
}
|
||||
fn forbid_unsigned_negation(cx: &LateContext, span: Span) {
|
||||
cx.sess()
|
||||
.struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519")
|
||||
.span_help(span, "use a cast or the `!` operator")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
matches, it sometimes happen that certain code (namely guards) gets
|
||||
executed multiple times. This means that the scope lexical scope may
|
||||
in fact correspond to multiple, disjoint SEME regions. So in fact our
|
||||
mapping os from one scope to a vector of SEME regions.
|
||||
mapping is from one scope to a vector of SEME regions.
|
||||
|
||||
### Drops
|
||||
|
||||
|
@ -94,7 +94,7 @@ fn erase_regions_terminator(&mut self,
|
||||
*switch_ty = self.tcx.erase_regions(switch_ty);
|
||||
},
|
||||
Terminator::Call { ref mut func, ref mut args, ref mut kind } => {
|
||||
if let Some(ref mut destination) = kind.destination() {
|
||||
if let Some(destination) = kind.destination_mut() {
|
||||
self.erase_regions_lvalue(destination);
|
||||
}
|
||||
self.erase_regions_operand(func);
|
||||
|
@ -100,7 +100,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
|
||||
let mut llargs = Vec::with_capacity(args.len() + 1);
|
||||
|
||||
// Prepare the return value destination
|
||||
let (ret_dest_ty, must_copy_dest) = if let Some(ref d) = kind.destination() {
|
||||
let (ret_dest_ty, must_copy_dest) = if let Some(d) = kind.destination() {
|
||||
let dest = self.trans_lvalue(bcx, d);
|
||||
let ret_ty = dest.ty.to_ty(bcx.tcx());
|
||||
if type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
|
||||
|
@ -15,13 +15,14 @@
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::mir::repr as mir;
|
||||
use trans::common::{self, Block, C_bool, C_bytes, C_floating_f64, C_integral, C_str_slice};
|
||||
use trans::consts::{self, TrueConst};
|
||||
use trans::{type_of, expr};
|
||||
|
||||
use trans::consts;
|
||||
use trans::expr;
|
||||
use trans::type_of;
|
||||
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::MirContext;
|
||||
|
||||
|
||||
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
pub fn trans_constval(&mut self,
|
||||
bcx: Block<'bcx, 'tcx>,
|
||||
@ -66,13 +67,7 @@ fn trans_constval_inner(&mut self,
|
||||
ConstVal::Uint(v) => C_integral(llty, v, false),
|
||||
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
|
||||
ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
|
||||
ConstVal::Struct(id) | ConstVal::Tuple(id) => {
|
||||
let expr = bcx.tcx().map.expect_expr(id);
|
||||
match consts::const_expr(ccx, expr, param_substs, None, TrueConst::Yes) {
|
||||
Ok((val, _)) => val,
|
||||
Err(e) => panic!("const eval failure: {}", e.description()),
|
||||
}
|
||||
},
|
||||
ConstVal::Struct(id) | ConstVal::Tuple(id) |
|
||||
ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => {
|
||||
let expr = bcx.tcx().map.expect_expr(id);
|
||||
expr::trans(bcx, expr).datum.val
|
||||
|
@ -25,8 +25,9 @@
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap};
|
||||
use std::collections::hash_map::{Entry};
|
||||
use std::rc::Rc;
|
||||
use std::iter::once;
|
||||
|
||||
struct ParserAnyMacro<'a> {
|
||||
parser: RefCell<Parser<'a>>,
|
||||
@ -320,15 +321,18 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
|
||||
NormalTT(exp, Some(def.span), def.allow_internal_unstable)
|
||||
}
|
||||
|
||||
// why is this here? because of https://github.com/rust-lang/rust/issues/27774
|
||||
fn ref_slice<A>(s: &A) -> &[A] { use std::slice::from_raw_parts; unsafe { from_raw_parts(s, 1) } }
|
||||
|
||||
fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree, sp: Span) {
|
||||
// lhs is going to be like TokenTree::Delimited(...), where the
|
||||
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
|
||||
match lhs {
|
||||
&TokenTree::Delimited(_, ref tts) => {
|
||||
check_matcher(cx, tts.tts.iter(), &Eof);
|
||||
check_matcher(cx, &tts.tts);
|
||||
},
|
||||
tt @ &TokenTree::Sequence(..) => {
|
||||
check_matcher(cx, Some(tt).into_iter(), &Eof);
|
||||
check_matcher(cx, ref_slice(tt));
|
||||
},
|
||||
_ => cx.span_err(sp, "invalid macro matcher; matchers must be contained \
|
||||
in balanced delimiters or a repetition indicator")
|
||||
@ -345,10 +349,59 @@ fn check_rhs(cx: &mut ExtCtxt, rhs: &TokenTree) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
// returns the last token that was checked, for TokenTree::Sequence. this gets used later on.
|
||||
fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
// Issue 30450: when we are through a warning cycle, we can just error
|
||||
// on all failure conditions and remove this struct and enum.
|
||||
|
||||
#[derive(Debug)]
|
||||
struct OnFail {
|
||||
saw_failure: bool,
|
||||
action: OnFailAction,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum OnFailAction { Warn, Error, DoNothing }
|
||||
|
||||
impl OnFail {
|
||||
fn warn() -> OnFail { OnFail { saw_failure: false, action: OnFailAction::Warn } }
|
||||
fn error() -> OnFail { OnFail { saw_failure: false, action: OnFailAction::Error } }
|
||||
fn do_nothing() -> OnFail { OnFail { saw_failure: false, action: OnFailAction::DoNothing } }
|
||||
fn react(&mut self, cx: &mut ExtCtxt, sp: Span, msg: &str) {
|
||||
match self.action {
|
||||
OnFailAction::DoNothing => {}
|
||||
OnFailAction::Error => cx.span_err(sp, msg),
|
||||
OnFailAction::Warn => {
|
||||
cx.struct_span_warn(sp, msg)
|
||||
.span_note(sp, "The above warning will be a hard error in the next release.")
|
||||
.emit();
|
||||
}
|
||||
};
|
||||
self.saw_failure = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn check_matcher(cx: &mut ExtCtxt, matcher: &[TokenTree]) {
|
||||
// Issue 30450: when we are through a warning cycle, we can just
|
||||
// error on all failure conditions (and remove check_matcher_old).
|
||||
|
||||
// First run the old-pass, but *only* to find out if it would have failed.
|
||||
let mut on_fail = OnFail::do_nothing();
|
||||
check_matcher_old(cx, matcher.iter(), &Eof, &mut on_fail);
|
||||
// Then run the new pass, but merely warn if the old pass accepts and new pass rejects.
|
||||
// (Note this silently accepts code if new pass accepts.)
|
||||
let mut on_fail = if on_fail.saw_failure {
|
||||
OnFail::error()
|
||||
} else {
|
||||
OnFail::warn()
|
||||
};
|
||||
check_matcher_new(cx, matcher, &mut on_fail);
|
||||
}
|
||||
|
||||
// returns the last token that was checked, for TokenTree::Sequence.
|
||||
// return value is used by recursive calls.
|
||||
fn check_matcher_old<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token, on_fail: &mut OnFail)
|
||||
-> Option<(Span, Token)> where I: Iterator<Item=&'a TokenTree> {
|
||||
use print::pprust::token_to_string;
|
||||
use std::iter::once;
|
||||
|
||||
let mut last = None;
|
||||
|
||||
@ -375,7 +428,7 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
// look at the token that follows the
|
||||
// sequence, which may itself be a sequence,
|
||||
// and so on).
|
||||
cx.span_err(sp,
|
||||
on_fail.react(cx, sp,
|
||||
&format!("`${0}:{1}` is followed by a \
|
||||
sequence repetition, which is not \
|
||||
allowed for `{1}` fragments",
|
||||
@ -398,13 +451,13 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
// If T' is in the set FOLLOW(NT), continue. Else, reject.
|
||||
match (&next_token, is_in_follow(cx, &next_token, &frag_spec.name.as_str())) {
|
||||
(_, Err(msg)) => {
|
||||
cx.span_err(sp, &msg);
|
||||
on_fail.react(cx, sp, &msg);
|
||||
continue
|
||||
}
|
||||
(&Eof, _) => return Some((sp, tok.clone())),
|
||||
(_, Ok(true)) => continue,
|
||||
(next, Ok(false)) => {
|
||||
cx.span_err(sp, &format!("`${0}:{1}` is followed by `{2}`, which \
|
||||
on_fail.react(cx, sp, &format!("`${0}:{1}` is followed by `{2}`, which \
|
||||
is not allowed for `{1}` fragments",
|
||||
name, frag_spec,
|
||||
token_to_string(next)));
|
||||
@ -420,7 +473,7 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
// run the algorithm on the contents with F set to U. If it
|
||||
// accepts, continue, else, reject.
|
||||
Some(ref u) => {
|
||||
let last = check_matcher(cx, seq.tts.iter(), u);
|
||||
let last = check_matcher_old(cx, seq.tts.iter(), u, on_fail);
|
||||
match last {
|
||||
// Since the delimiter isn't required after the last
|
||||
// repetition, make sure that the *next* token is
|
||||
@ -434,14 +487,14 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
Some(&&TokenTree::Delimited(_, ref delim)) =>
|
||||
delim.close_token(),
|
||||
Some(_) => {
|
||||
cx.span_err(sp, "sequence repetition followed by \
|
||||
on_fail.react(cx, sp, "sequence repetition followed by \
|
||||
another sequence repetition, which is not allowed");
|
||||
Eof
|
||||
},
|
||||
None => Eof
|
||||
};
|
||||
check_matcher(cx, once(&TokenTree::Token(span, tok.clone())),
|
||||
&fol)
|
||||
check_matcher_old(cx, once(&TokenTree::Token(span, tok.clone())),
|
||||
&fol, on_fail)
|
||||
},
|
||||
None => last,
|
||||
}
|
||||
@ -454,13 +507,13 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
Some(&&TokenTree::Token(_, ref tok)) => tok.clone(),
|
||||
Some(&&TokenTree::Delimited(_, ref delim)) => delim.close_token(),
|
||||
Some(_) => {
|
||||
cx.span_err(sp, "sequence repetition followed by another \
|
||||
on_fail.react(cx, sp, "sequence repetition followed by another \
|
||||
sequence repetition, which is not allowed");
|
||||
Eof
|
||||
},
|
||||
None => Eof
|
||||
};
|
||||
check_matcher(cx, seq.tts.iter(), &fol)
|
||||
check_matcher_old(cx, seq.tts.iter(), &fol, on_fail)
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -471,13 +524,425 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
|
||||
TokenTree::Delimited(_, ref tts) => {
|
||||
// if we don't pass in that close delimiter, we'll incorrectly consider the matcher
|
||||
// `{ $foo:ty }` as having a follow that isn't `RBrace`
|
||||
check_matcher(cx, tts.tts.iter(), &tts.close_token())
|
||||
check_matcher_old(cx, tts.tts.iter(), &tts.close_token(), on_fail)
|
||||
}
|
||||
}
|
||||
}
|
||||
last
|
||||
}
|
||||
|
||||
fn check_matcher_new(cx: &mut ExtCtxt, matcher: &[TokenTree], on_fail: &mut OnFail) {
|
||||
let first_sets = FirstSets::new(matcher);
|
||||
let empty_suffix = TokenSet::empty();
|
||||
check_matcher_core(cx, &first_sets, matcher, &empty_suffix, on_fail);
|
||||
}
|
||||
|
||||
// The FirstSets for a matcher is a mapping from subsequences in the
|
||||
// matcher to the FIRST set for that subsequence.
|
||||
//
|
||||
// This mapping is partially precomputed via a backwards scan over the
|
||||
// token trees of the matcher, which provides a mapping from each
|
||||
// repetition sequence to its FIRST set.
|
||||
//
|
||||
// (Hypothetically sequences should be uniquely identifiable via their
|
||||
// spans, though perhaps that is false e.g. for macro-generated macros
|
||||
// that do not try to inject artificial span information. My plan is
|
||||
// to try to catch such cases ahead of time and not include them in
|
||||
// the precomputed mapping.)
|
||||
struct FirstSets {
|
||||
// this maps each TokenTree::Sequence `$(tt ...) SEP OP` that is uniquely identified by its
|
||||
// span in the original matcher to the First set for the inner sequence `tt ...`.
|
||||
//
|
||||
// If two sequences have the same span in a matcher, then map that
|
||||
// span to None (invalidating the mapping here and forcing the code to
|
||||
// use a slow path).
|
||||
first: HashMap<Span, Option<TokenSet>>,
|
||||
}
|
||||
|
||||
impl FirstSets {
|
||||
fn new(tts: &[TokenTree]) -> FirstSets {
|
||||
let mut sets = FirstSets { first: HashMap::new() };
|
||||
build_recur(&mut sets, tts);
|
||||
return sets;
|
||||
|
||||
// walks backward over `tts`, returning the FIRST for `tts`
|
||||
// and updating `sets` at the same time for all sequence
|
||||
// substructure we find within `tts`.
|
||||
fn build_recur(sets: &mut FirstSets, tts: &[TokenTree]) -> TokenSet {
|
||||
let mut first = TokenSet::empty();
|
||||
for tt in tts.iter().rev() {
|
||||
match *tt {
|
||||
TokenTree::Token(sp, ref tok) => {
|
||||
first.replace_with((sp, tok.clone()));
|
||||
}
|
||||
TokenTree::Delimited(_, ref delimited) => {
|
||||
build_recur(sets, &delimited.tts[..]);
|
||||
first.replace_with((delimited.open_span,
|
||||
Token::OpenDelim(delimited.delim)));
|
||||
}
|
||||
TokenTree::Sequence(sp, ref seq_rep) => {
|
||||
let subfirst = build_recur(sets, &seq_rep.tts[..]);
|
||||
|
||||
match sets.first.entry(sp) {
|
||||
Entry::Vacant(vac) => {
|
||||
vac.insert(Some(subfirst.clone()));
|
||||
}
|
||||
Entry::Occupied(mut occ) => {
|
||||
// if there is already an entry, then a span must have collided.
|
||||
// This should not happen with typical macro_rules macros,
|
||||
// but syntax extensions need not maintain distinct spans,
|
||||
// so distinct syntax trees can be assigned the same span.
|
||||
// In such a case, the map cannot be trusted; so mark this
|
||||
// entry as unusable.
|
||||
occ.insert(None);
|
||||
}
|
||||
}
|
||||
|
||||
// If the sequence contents can be empty, then the first
|
||||
// token could be the separator token itself.
|
||||
|
||||
if let (Some(ref sep), true) = (seq_rep.separator.clone(),
|
||||
subfirst.maybe_empty) {
|
||||
first.add_one_maybe((sp, sep.clone()));
|
||||
}
|
||||
|
||||
// Reverse scan: Sequence comes before `first`.
|
||||
if subfirst.maybe_empty || seq_rep.op == ast::KleeneOp::ZeroOrMore {
|
||||
// If sequence is potentially empty, then
|
||||
// union them (preserving first emptiness).
|
||||
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
|
||||
} else {
|
||||
// Otherwise, sequence guaranteed
|
||||
// non-empty; replace first.
|
||||
first = subfirst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
// walks forward over `tts` until all potential FIRST tokens are
|
||||
// identified.
|
||||
fn first(&self, tts: &[TokenTree]) -> TokenSet {
|
||||
let mut first = TokenSet::empty();
|
||||
for tt in tts.iter() {
|
||||
assert!(first.maybe_empty);
|
||||
match *tt {
|
||||
TokenTree::Token(sp, ref tok) => {
|
||||
first.add_one((sp, tok.clone()));
|
||||
return first;
|
||||
}
|
||||
TokenTree::Delimited(_, ref delimited) => {
|
||||
first.add_one((delimited.open_span,
|
||||
Token::OpenDelim(delimited.delim)));
|
||||
return first;
|
||||
}
|
||||
TokenTree::Sequence(sp, ref seq_rep) => {
|
||||
match self.first.get(&sp) {
|
||||
Some(&Some(ref subfirst)) => {
|
||||
|
||||
// If the sequence contents can be empty, then the first
|
||||
// token could be the separator token itself.
|
||||
|
||||
if let (Some(ref sep), true) = (seq_rep.separator.clone(),
|
||||
subfirst.maybe_empty) {
|
||||
first.add_one_maybe((sp, sep.clone()));
|
||||
}
|
||||
|
||||
assert!(first.maybe_empty);
|
||||
first.add_all(subfirst);
|
||||
if subfirst.maybe_empty || seq_rep.op == ast::KleeneOp::ZeroOrMore {
|
||||
// continue scanning for more first
|
||||
// tokens, but also make sure we
|
||||
// restore empty-tracking state
|
||||
first.maybe_empty = true;
|
||||
continue;
|
||||
} else {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
Some(&None) => {
|
||||
panic!("assume all sequences have (unique) spans for now");
|
||||
}
|
||||
|
||||
None => {
|
||||
panic!("We missed a sequence during FirstSets construction");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we only exit the loop if `tts` was empty or if every
|
||||
// element of `tts` matches the empty sequence.
|
||||
assert!(first.maybe_empty);
|
||||
return first;
|
||||
}
|
||||
}
|
||||
|
||||
// A set of Tokens, which may include MatchNt tokens (for
|
||||
// macro-by-example syntactic variables). It also carries the
|
||||
// `maybe_empty` flag; that is true if and only if the matcher can
|
||||
// match an empty token sequence.
|
||||
//
|
||||
// The First set is computed on submatchers like `$($a:expr b),* $(c)* d`,
|
||||
// which has corresponding FIRST = {$a:expr, c, d}.
|
||||
// Likewise, `$($a:expr b),* $(c)+ d` has FIRST = {$a:expr, c}.
|
||||
//
|
||||
// (Notably, we must allow for *-op to occur zero times.)
|
||||
#[derive(Clone, Debug)]
|
||||
struct TokenSet {
|
||||
tokens: Vec<(Span, Token)>,
|
||||
maybe_empty: bool,
|
||||
}
|
||||
|
||||
impl TokenSet {
|
||||
// Returns a set for the empty sequence.
|
||||
fn empty() -> Self { TokenSet { tokens: Vec::new(), maybe_empty: true } }
|
||||
|
||||
// Returns the set `{ tok }` for the single-token (and thus
|
||||
// non-empty) sequence [tok].
|
||||
fn singleton(tok: (Span, Token)) -> Self {
|
||||
TokenSet { tokens: vec![tok], maybe_empty: false }
|
||||
}
|
||||
|
||||
// Changes self to be the set `{ tok }`.
|
||||
// Since `tok` is always present, marks self as non-empty.
|
||||
fn replace_with(&mut self, tok: (Span, Token)) {
|
||||
self.tokens.clear();
|
||||
self.tokens.push(tok);
|
||||
self.maybe_empty = false;
|
||||
}
|
||||
|
||||
// Changes self to be the empty set `{}`; meant for use when
|
||||
// the particular token does not matter, but we want to
|
||||
// record that it occurs.
|
||||
fn replace_with_irrelevant(&mut self) {
|
||||
self.tokens.clear();
|
||||
self.maybe_empty = false;
|
||||
}
|
||||
|
||||
// Adds `tok` to the set for `self`, marking sequence as non-empy.
|
||||
fn add_one(&mut self, tok: (Span, Token)) {
|
||||
if !self.tokens.contains(&tok) {
|
||||
self.tokens.push(tok);
|
||||
}
|
||||
self.maybe_empty = false;
|
||||
}
|
||||
|
||||
// Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.)
|
||||
fn add_one_maybe(&mut self, tok: (Span, Token)) {
|
||||
if !self.tokens.contains(&tok) {
|
||||
self.tokens.push(tok);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds all elements of `other` to this.
|
||||
//
|
||||
// (Since this is a set, we filter out duplicates.)
|
||||
//
|
||||
// If `other` is potentially empty, then preserves the previous
|
||||
// setting of the empty flag of `self`. If `other` is guaranteed
|
||||
// non-empty, then `self` is marked non-empty.
|
||||
fn add_all(&mut self, other: &Self) {
|
||||
for tok in &other.tokens {
|
||||
if !self.tokens.contains(tok) {
|
||||
self.tokens.push(tok.clone());
|
||||
}
|
||||
}
|
||||
if !other.maybe_empty {
|
||||
self.maybe_empty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checks that `matcher` is internally consistent and that it
|
||||
// can legally by followed by a token N, for all N in `follow`.
|
||||
// (If `follow` is empty, then it imposes no constraint on
|
||||
// the `matcher`.)
|
||||
//
|
||||
// Returns the set of NT tokens that could possibly come last in
|
||||
// `matcher`. (If `matcher` matches the empty sequence, then
|
||||
// `maybe_empty` will be set to true.)
|
||||
//
|
||||
// Requires that `first_sets` is pre-computed for `matcher`;
|
||||
// see `FirstSets::new`.
|
||||
fn check_matcher_core(cx: &mut ExtCtxt,
|
||||
first_sets: &FirstSets,
|
||||
matcher: &[TokenTree],
|
||||
follow: &TokenSet,
|
||||
on_fail: &mut OnFail) -> TokenSet {
|
||||
use print::pprust::token_to_string;
|
||||
|
||||
let mut last = TokenSet::empty();
|
||||
|
||||
// 2. For each token and suffix [T, SUFFIX] in M:
|
||||
// ensure that T can be followed by SUFFIX, and if SUFFIX may be empty,
|
||||
// then ensure T can also be followed by any element of FOLLOW.
|
||||
'each_token: for i in 0..matcher.len() {
|
||||
let token = &matcher[i];
|
||||
let suffix = &matcher[i+1..];
|
||||
|
||||
let build_suffix_first = || {
|
||||
let mut s = first_sets.first(suffix);
|
||||
if s.maybe_empty { s.add_all(follow); }
|
||||
return s;
|
||||
};
|
||||
|
||||
// (we build `suffix_first` on demand below; you can tell
|
||||
// which cases are supposed to fall through by looking for the
|
||||
// initialization of this variable.)
|
||||
let suffix_first;
|
||||
|
||||
// First, update `last` so that it corresponds to the set
|
||||
// of NT tokens that might end the sequence `... token`.
|
||||
match *token {
|
||||
TokenTree::Token(sp, ref tok) => {
|
||||
let can_be_followed_by_any;
|
||||
if let Err(bad_frag) = has_legal_fragment_specifier(tok) {
|
||||
on_fail.react(cx, sp, &format!("invalid fragment specifier `{}`", bad_frag));
|
||||
// (This eliminates false positives and duplicates
|
||||
// from error messages.)
|
||||
can_be_followed_by_any = true;
|
||||
} else {
|
||||
can_be_followed_by_any = token_can_be_followed_by_any(tok);
|
||||
}
|
||||
|
||||
if can_be_followed_by_any {
|
||||
// don't need to track tokens that work with any,
|
||||
last.replace_with_irrelevant();
|
||||
// ... and don't need to check tokens that can be
|
||||
// followed by anything against SUFFIX.
|
||||
continue 'each_token;
|
||||
} else {
|
||||
last.replace_with((sp, tok.clone()));
|
||||
suffix_first = build_suffix_first();
|
||||
}
|
||||
}
|
||||
TokenTree::Delimited(_, ref d) => {
|
||||
let my_suffix = TokenSet::singleton((d.close_span, Token::CloseDelim(d.delim)));
|
||||
check_matcher_core(cx, first_sets, &d.tts, &my_suffix, on_fail);
|
||||
// don't track non NT tokens
|
||||
last.replace_with_irrelevant();
|
||||
|
||||
// also, we don't need to check delimited sequences
|
||||
// against SUFFIX
|
||||
continue 'each_token;
|
||||
}
|
||||
TokenTree::Sequence(sp, ref seq_rep) => {
|
||||
suffix_first = build_suffix_first();
|
||||
// The trick here: when we check the interior, we want
|
||||
// to include the separator (if any) as a potential
|
||||
// (but not guaranteed) element of FOLLOW. So in that
|
||||
// case, we make a temp copy of suffix and stuff
|
||||
// delimiter in there.
|
||||
//
|
||||
// FIXME: Should I first scan suffix_first to see if
|
||||
// delimiter is already in it before I go through the
|
||||
// work of cloning it? But then again, this way I may
|
||||
// get a "tighter" span?
|
||||
let mut new;
|
||||
let my_suffix = if let Some(ref u) = seq_rep.separator {
|
||||
new = suffix_first.clone();
|
||||
new.add_one_maybe((sp, u.clone()));
|
||||
&new
|
||||
} else {
|
||||
&suffix_first
|
||||
};
|
||||
|
||||
// At this point, `suffix_first` is built, and
|
||||
// `my_suffix` is some TokenSet that we can use
|
||||
// for checking the interior of `seq_rep`.
|
||||
let next = check_matcher_core(cx, first_sets, &seq_rep.tts, my_suffix, on_fail);
|
||||
if next.maybe_empty {
|
||||
last.add_all(&next);
|
||||
} else {
|
||||
last = next;
|
||||
}
|
||||
|
||||
// the recursive call to check_matcher_core already ran the 'each_last
|
||||
// check below, so we can just keep going forward here.
|
||||
continue 'each_token;
|
||||
}
|
||||
}
|
||||
|
||||
// (`suffix_first` guaranteed initialized once reaching here.)
|
||||
|
||||
// Now `last` holds the complete set of NT tokens that could
|
||||
// end the sequence before SUFFIX. Check that every one works with `suffix`.
|
||||
'each_last: for &(_sp, ref t) in &last.tokens {
|
||||
if let MatchNt(ref name, ref frag_spec, _, _) = *t {
|
||||
for &(sp, ref next_token) in &suffix_first.tokens {
|
||||
match is_in_follow(cx, next_token, &frag_spec.name.as_str()) {
|
||||
Err(msg) => {
|
||||
on_fail.react(cx, sp, &msg);
|
||||
// don't bother reporting every source of
|
||||
// conflict for a particular element of `last`.
|
||||
continue 'each_last;
|
||||
}
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
let may_be = if last.tokens.len() == 1 &&
|
||||
suffix_first.tokens.len() == 1
|
||||
{
|
||||
"is"
|
||||
} else {
|
||||
"may be"
|
||||
};
|
||||
|
||||
on_fail.react(
|
||||
cx, sp,
|
||||
&format!("`${name}:{frag}` {may_be} followed by `{next}`, which \
|
||||
is not allowed for `{frag}` fragments",
|
||||
name=name,
|
||||
frag=frag_spec,
|
||||
next=token_to_string(next_token),
|
||||
may_be=may_be));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
last
|
||||
}
|
||||
|
||||
|
||||
fn token_can_be_followed_by_any(tok: &Token) -> bool {
|
||||
if let &MatchNt(_, ref frag_spec, _, _) = tok {
|
||||
frag_can_be_followed_by_any(&frag_spec.name.as_str())
|
||||
} else {
|
||||
// (Non NT's can always be followed by anthing in matchers.)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// True if a fragment of type `frag` can be followed by any sort of
|
||||
/// token. We use this (among other things) as a useful approximation
|
||||
/// for when `frag` can be followed by a repetition like `$(...)*` or
|
||||
/// `$(...)+`. In general, these can be a bit tricky to reason about,
|
||||
/// so we adopt a conservative position that says that any fragment
|
||||
/// specifier which consumes at most one token tree can be followed by
|
||||
/// a fragment specifier (indeed, these fragments can be followed by
|
||||
/// ANYTHING without fear of future compatibility hazards).
|
||||
fn frag_can_be_followed_by_any(frag: &str) -> bool {
|
||||
match frag {
|
||||
"item" | // always terminated by `}` or `;`
|
||||
"block" | // exactly one token tree
|
||||
"ident" | // exactly one token tree
|
||||
"meta" | // exactly one token tree
|
||||
"tt" => // exactly one token tree
|
||||
true,
|
||||
|
||||
_ =>
|
||||
false,
|
||||
}
|
||||
}
|
||||
|
||||
/// True if a fragment of type `frag` can be followed by any sort of
|
||||
/// token. We use this (among other things) as a useful approximation
|
||||
/// for when `frag` can be followed by a repetition like `$(...)*` or
|
||||
@ -501,7 +966,7 @@ fn can_be_followed_by_any(frag: &str) -> bool {
|
||||
}
|
||||
|
||||
/// True if `frag` can legally be followed by the token `tok`. For
|
||||
/// fragments that can consume an unbounded numbe of tokens, `tok`
|
||||
/// fragments that can consume an unbounded number of tokens, `tok`
|
||||
/// must be within a well-defined follow set. This is intended to
|
||||
/// guarantee future compatibility: for example, without this rule, if
|
||||
/// we expanded `expr` to include a new binary operator, we might
|
||||
@ -532,15 +997,18 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
|
||||
},
|
||||
"pat" => {
|
||||
match *tok {
|
||||
FatArrow | Comma | Eq => Ok(true),
|
||||
Ident(i, _) if i.name.as_str() == "if" || i.name.as_str() == "in" => Ok(true),
|
||||
FatArrow | Comma | Eq | BinOp(token::Or) => Ok(true),
|
||||
Ident(i, _) if (i.name.as_str() == "if" ||
|
||||
i.name.as_str() == "in") => Ok(true),
|
||||
_ => Ok(false)
|
||||
}
|
||||
},
|
||||
"path" | "ty" => {
|
||||
match *tok {
|
||||
Comma | FatArrow | Colon | Eq | Gt | Semi => Ok(true),
|
||||
Ident(i, _) if i.name.as_str() == "as" => Ok(true),
|
||||
OpenDelim(token::DelimToken::Brace) |
|
||||
Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true),
|
||||
Ident(i, _) if (i.name.as_str() == "as" ||
|
||||
i.name.as_str() == "where") => Ok(true),
|
||||
_ => Ok(false)
|
||||
}
|
||||
},
|
||||
@ -557,3 +1025,22 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_legal_fragment_specifier(tok: &Token) -> Result<(), String> {
|
||||
debug!("has_legal_fragment_specifier({:?})", tok);
|
||||
if let &MatchNt(_, ref frag_spec, _, _) = tok {
|
||||
let s = &frag_spec.name.as_str();
|
||||
if !is_legal_fragment_specifier(s) {
|
||||
return Err(s.to_string());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_legal_fragment_specifier(frag: &str) -> bool {
|
||||
match frag {
|
||||
"item" | "block" | "stmt" | "expr" | "pat" |
|
||||
"path" | "ty" | "ident" | "meta" | "tt" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@
|
||||
("slice_patterns", "1.0.0", Some(23121), Active),
|
||||
|
||||
// Allows use of unary negate on unsigned integers, e.g. -e for e: u8
|
||||
("negate_unsigned", "1.0.0", Some(29645), Active),
|
||||
("negate_unsigned", "1.0.0", Some(29645), Removed),
|
||||
|
||||
// Allows the definition of associated constants in `trait` or `impl`
|
||||
// blocks.
|
||||
@ -548,7 +548,6 @@ pub struct Features {
|
||||
pub allow_pushpop_unsafe: bool,
|
||||
pub simd_ffi: bool,
|
||||
pub unmarked_api: bool,
|
||||
pub negate_unsigned: bool,
|
||||
/// spans of #![feature] attrs for stable language features. for error reporting
|
||||
pub declared_stable_lang_features: Vec<Span>,
|
||||
/// #![feature] attrs for non-language (library) features
|
||||
@ -585,7 +584,6 @@ pub fn new() -> Features {
|
||||
allow_pushpop_unsafe: false,
|
||||
simd_ffi: false,
|
||||
unmarked_api: false,
|
||||
negate_unsigned: false,
|
||||
declared_stable_lang_features: Vec::new(),
|
||||
declared_lib_features: Vec::new(),
|
||||
const_fn: false,
|
||||
@ -1174,7 +1172,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
|
||||
allow_pushpop_unsafe: cx.has_feature("pushpop_unsafe"),
|
||||
simd_ffi: cx.has_feature("simd_ffi"),
|
||||
unmarked_api: cx.has_feature("unmarked_api"),
|
||||
negate_unsigned: cx.has_feature("negate_unsigned"),
|
||||
declared_stable_lang_features: accepted_features,
|
||||
declared_lib_features: unknown_features,
|
||||
const_fn: cx.has_feature("const_fn"),
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
#![feature(negate_unsigned)]
|
||||
|
||||
// Note: the relevant lint pass here runs before some of the constant
|
||||
// evaluation below (e.g. that performed by trans and llvm), so if you
|
||||
@ -65,7 +64,7 @@
|
||||
);
|
||||
|
||||
const VALS_U8: (u8, u8, u8, u8) =
|
||||
(-u8::MIN,
|
||||
(-(u8::MIN as i8) as u8,
|
||||
u8::MIN - 1,
|
||||
//~^ ERROR attempted to sub with overflow
|
||||
u8::MAX + 1,
|
||||
@ -75,7 +74,7 @@
|
||||
);
|
||||
|
||||
const VALS_U16: (u16, u16, u16, u16) =
|
||||
(-u16::MIN,
|
||||
(-(u16::MIN as i16) as u16,
|
||||
u16::MIN - 1,
|
||||
//~^ ERROR attempted to sub with overflow
|
||||
u16::MAX + 1,
|
||||
@ -85,7 +84,7 @@
|
||||
);
|
||||
|
||||
const VALS_U32: (u32, u32, u32, u32) =
|
||||
(-u32::MIN,
|
||||
(-(u32::MIN as i32) as u32,
|
||||
u32::MIN - 1,
|
||||
//~^ ERROR attempted to sub with overflow
|
||||
u32::MAX + 1,
|
||||
@ -95,7 +94,7 @@
|
||||
);
|
||||
|
||||
const VALS_U64: (u64, u64, u64, u64) =
|
||||
(-u64::MIN,
|
||||
(-(u64::MIN as i64) as u64,
|
||||
u64::MIN - 1,
|
||||
//~^ ERROR attempted to sub with overflow
|
||||
u64::MAX + 1,
|
||||
|
100
src/test/compile-fail/const-eval-overflow0.rs
Normal file
100
src/test/compile-fail/const-eval-overflow0.rs
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
// Note: the relevant lint pass here runs before some of the constant
|
||||
// evaluation below (e.g. that performed by trans and llvm), so if you
|
||||
// change this warn to a deny, then the compiler will exit before
|
||||
// those errors are detected.
|
||||
|
||||
use std::fmt;
|
||||
use std::{i8, i16, i32, i64, isize};
|
||||
use std::{u8, u16, u32, u64, usize};
|
||||
|
||||
const VALS_I8: (i8, i8, i8, i8) =
|
||||
(-i8::MIN,
|
||||
i8::MIN - 1,
|
||||
i8::MAX + 1,
|
||||
i8::MIN * 2,
|
||||
);
|
||||
|
||||
const VALS_I16: (i16, i16, i16, i16) =
|
||||
(-i16::MIN,
|
||||
i16::MIN - 1,
|
||||
i16::MAX + 1,
|
||||
i16::MIN * 2,
|
||||
);
|
||||
|
||||
const VALS_I32: (i32, i32, i32, i32) =
|
||||
(-i32::MIN,
|
||||
i32::MIN - 1,
|
||||
i32::MAX + 1,
|
||||
i32::MIN * 2,
|
||||
);
|
||||
|
||||
const VALS_I64: (i64, i64, i64, i64) =
|
||||
(-i64::MIN,
|
||||
i64::MIN - 1,
|
||||
i64::MAX + 1,
|
||||
i64::MAX * 2,
|
||||
);
|
||||
|
||||
const VALS_U8: (u8, u8, u8, u8) =
|
||||
(-u8::MIN,
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
u8::MIN - 1,
|
||||
u8::MAX + 1,
|
||||
u8::MAX * 2,
|
||||
);
|
||||
|
||||
const VALS_U16: (u16, u16, u16, u16) =
|
||||
(-u16::MIN,
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
u16::MIN - 1,
|
||||
u16::MAX + 1,
|
||||
u16::MAX * 2,
|
||||
);
|
||||
|
||||
const VALS_U32: (u32, u32, u32, u32) =
|
||||
(-u32::MIN,
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
u32::MIN - 1,
|
||||
u32::MAX + 1,
|
||||
u32::MAX * 2,
|
||||
);
|
||||
|
||||
const VALS_U64: (u64, u64, u64, u64) =
|
||||
(-u64::MIN,
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
u64::MIN - 1,
|
||||
u64::MAX + 1,
|
||||
u64::MAX * 2,
|
||||
);
|
||||
|
||||
fn main() {
|
||||
foo(VALS_I8);
|
||||
foo(VALS_I16);
|
||||
foo(VALS_I32);
|
||||
foo(VALS_I64);
|
||||
|
||||
foo(VALS_U8);
|
||||
foo(VALS_U16);
|
||||
foo(VALS_U32);
|
||||
foo(VALS_U64);
|
||||
}
|
||||
|
||||
fn foo<T:fmt::Debug>(x: T) {
|
||||
println!("{:?}", x);
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(negate_unsigned)]
|
||||
|
||||
#[repr(u8)] //~ NOTE discriminant type specified here
|
||||
enum Eu8 {
|
||||
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that negating unsigned integers is gated by `negate_unsigned` feature
|
||||
// gate
|
||||
// Test that negating unsigned integers doesn't compile
|
||||
|
||||
struct S;
|
||||
impl std::ops::Neg for S {
|
||||
@ -18,21 +17,26 @@ fn neg(self) -> u32 { 0 }
|
||||
}
|
||||
|
||||
const _MAX: usize = -1;
|
||||
//~^ ERROR unary negation of unsigned integers may be removed in the future
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
|
||||
fn main() {
|
||||
let a = -1;
|
||||
//~^ ERROR unary negation of unsigned integers may be removed in the future
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
let _b : u8 = a; // for infering variable a to u8.
|
||||
|
||||
-a;
|
||||
//~^ ERROR unary negation of unsigned integers may be removed in the future
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
|
||||
let _d = -1u8;
|
||||
//~^ ERROR unary negation of unsigned integers may be removed in the future
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
|
||||
for _ in -10..10u8 {}
|
||||
//~^ ERROR unary negation of unsigned integers may be removed in the future
|
||||
//~^ ERROR unary negation of unsigned integer
|
||||
//~| HELP use a cast or the `!` operator
|
||||
|
||||
-S; // should not trigger the gate; issue 26840
|
||||
}
|
||||
|
@ -10,7 +10,12 @@
|
||||
|
||||
macro_rules! parallel {
|
||||
(
|
||||
for $id:ident in $iter:expr {
|
||||
// If future has `pred`/`moelarry` fragments (where "pred" is
|
||||
// "like expr, but with `{` in its FOLLOW set"), then could
|
||||
// use `pred` instead of future-proof erroring here. See also:
|
||||
//
|
||||
// https://github.com/rust-lang/rfcs/pull/1384#issuecomment-160165525
|
||||
for $id:ident in $iter:expr { //~ WARN `$iter:expr` is followed by `{`
|
||||
$( $inner:expr; )*
|
||||
}
|
||||
) => {};
|
||||
|
@ -8,9 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(negate_unsigned)]
|
||||
#![allow(dead_code)]
|
||||
#![feature(negate_unsigned)]
|
||||
|
||||
// compile-flags: -D unused-comparisons
|
||||
fn main() { }
|
||||
|
@ -18,13 +18,14 @@ macro_rules! errors_everywhere {
|
||||
($bl:block < ) => ();
|
||||
($pa:pat >) => (); //~ ERROR `$pa:pat` is followed by `>`, which is not allowed for `pat`
|
||||
($pa:pat , ) => ();
|
||||
($pa:pat | ) => (); //~ ERROR `$pa:pat` is followed by `|`
|
||||
($pa:pat $pb:pat $ty:ty ,) => ();
|
||||
//~^ ERROR `$pa:pat` is followed by `$pb:pat`, which is not allowed
|
||||
//~^^ ERROR `$pb:pat` is followed by `$ty:ty`, which is not allowed
|
||||
($($ty:ty)* -) => (); //~ ERROR `$ty:ty` is followed by `-`
|
||||
($($a:ty, $b:ty)* -) => (); //~ ERROR `$b:ty` is followed by `-`
|
||||
($($ty:ty)-+) => (); //~ ERROR `$ty:ty` is followed by `-`, which is not allowed for `ty`
|
||||
( $($a:expr)* $($b:tt)* ) => { };
|
||||
//~^ ERROR `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,18 +0,0 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Check that we cannot have two sequence repetitions in a row.
|
||||
|
||||
macro_rules! foo {
|
||||
( $($a:expr)* $($b:tt)* ) => { }; //~ ERROR sequence repetition followed by another sequence
|
||||
( $($a:tt)* $($b:tt)* ) => { }; //~ ERROR sequence repetition followed by another sequence
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -8,16 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(negate_unsigned)]
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "arm"))]
|
||||
fn target() {
|
||||
assert_eq!(-1000 as usize >> 3_usize, 536870787_usize);
|
||||
assert_eq!(-1000isize as usize >> 3_usize, 536870787_usize);
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
fn target() {
|
||||
assert_eq!(-1000 as usize >> 3_usize, 2305843009213693827_usize);
|
||||
assert_eq!(-1000isize as usize >> 3_usize, 2305843009213693827_usize);
|
||||
}
|
||||
|
||||
fn general() {
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
#![feature(negate_unsigned)]
|
||||
#![feature(intrinsics)]
|
||||
|
||||
mod rusti {
|
||||
@ -45,10 +43,10 @@ pub fn main() {
|
||||
assert_eq!(ctpop(100u32), 3); assert_eq!(ctpop(100i32), 3);
|
||||
assert_eq!(ctpop(100u64), 3); assert_eq!(ctpop(100i64), 3);
|
||||
|
||||
assert_eq!(ctpop(-1u8), 8); assert_eq!(ctpop(-1i8), 8);
|
||||
assert_eq!(ctpop(-1u16), 16); assert_eq!(ctpop(-1i16), 16);
|
||||
assert_eq!(ctpop(-1u32), 32); assert_eq!(ctpop(-1i32), 32);
|
||||
assert_eq!(ctpop(-1u64), 64); assert_eq!(ctpop(-1i64), 64);
|
||||
assert_eq!(ctpop(-1i8 as u8), 8); assert_eq!(ctpop(-1i8), 8);
|
||||
assert_eq!(ctpop(-1i16 as u16), 16); assert_eq!(ctpop(-1i16), 16);
|
||||
assert_eq!(ctpop(-1i32 as u32), 32); assert_eq!(ctpop(-1i32), 32);
|
||||
assert_eq!(ctpop(-1i64 as u64), 64); assert_eq!(ctpop(-1i64), 64);
|
||||
|
||||
assert_eq!(ctlz(0u8), 8); assert_eq!(ctlz(0i8), 8);
|
||||
assert_eq!(ctlz(0u16), 16); assert_eq!(ctlz(0i16), 16);
|
||||
@ -70,10 +68,10 @@ pub fn main() {
|
||||
assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25);
|
||||
assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57);
|
||||
|
||||
assert_eq!(cttz(-1u8), 0); assert_eq!(cttz(-1i8), 0);
|
||||
assert_eq!(cttz(-1u16), 0); assert_eq!(cttz(-1i16), 0);
|
||||
assert_eq!(cttz(-1u32), 0); assert_eq!(cttz(-1i32), 0);
|
||||
assert_eq!(cttz(-1u64), 0); assert_eq!(cttz(-1i64), 0);
|
||||
assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0);
|
||||
assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0);
|
||||
assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0);
|
||||
assert_eq!(cttz(-1i64 as u64), 0); assert_eq!(cttz(-1i64), 0);
|
||||
|
||||
assert_eq!(cttz(0u8), 8); assert_eq!(cttz(0i8), 8);
|
||||
assert_eq!(cttz(0u16), 16); assert_eq!(cttz(0i16), 16);
|
||||
|
@ -24,7 +24,17 @@ macro_rules! pat_if {
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! pat_bar {
|
||||
($p:pat | $p2:pat) => {{
|
||||
match Some(1u8) {
|
||||
$p | $p2 => {},
|
||||
_ => {}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pat_in!(Some(_) in 0..10);
|
||||
pat_if!(Some(x) if x > 0);
|
||||
pat_bar!(Some(1u8) | None);
|
||||
}
|
||||
|
26
src/test/run-pass/macro-seq-followed-by-seq.rs
Normal file
26
src/test/run-pass/macro-seq-followed-by-seq.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test of allowing two sequences repetitions in a row,
|
||||
// functionality added as byproduct of RFC amendment #1384
|
||||
// https://github.com/rust-lang/rfcs/pull/1384
|
||||
|
||||
// Old version of Rust would reject this macro definition, even though
|
||||
// there are no local ambiguities (the initial `banana` and `orange`
|
||||
// tokens are enough for the expander to distinguish which case is
|
||||
// intended).
|
||||
macro_rules! foo {
|
||||
( $(banana $a:ident)* $(orange $b:tt)* ) => { };
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo!( banana id1 banana id2
|
||||
orange hi orange (hello world) );
|
||||
}
|
32
src/test/run-pass/mir_constval_adts.rs
Normal file
32
src/test/run-pass/mir_constval_adts.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Point {
|
||||
_x: i32,
|
||||
_y: i32,
|
||||
}
|
||||
const STRUCT: Point = Point { _x: 42, _y: 42 };
|
||||
const TUPLE1: (i32, i32) = (42, 42);
|
||||
const TUPLE2: (&'static str, &'static str) = ("hello","world");
|
||||
|
||||
#[rustc_mir]
|
||||
fn mir() -> (Point, (i32, i32), (&'static str, &'static str)){
|
||||
let struct1 = STRUCT;
|
||||
let tuple1 = TUPLE1;
|
||||
let tuple2 = TUPLE2;
|
||||
(struct1, tuple1, tuple2)
|
||||
}
|
||||
|
||||
fn main(){
|
||||
assert_eq!(mir(), (STRUCT, TUPLE1, TUPLE2));
|
||||
}
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(negate_unsigned)]
|
||||
|
||||
pub fn main() {
|
||||
let a = 1;
|
||||
let a_neg: i8 = -a;
|
||||
@ -30,26 +28,4 @@ pub fn main() {
|
||||
let e = 1;
|
||||
let e_neg: isize = -e;
|
||||
println!("{}", e_neg);
|
||||
|
||||
// intentional overflows
|
||||
|
||||
let f = 1;
|
||||
let f_neg: u8 = -f;
|
||||
println!("{}", f_neg);
|
||||
|
||||
let g = 1;
|
||||
let g_neg: u16 = -g;
|
||||
println!("{}", g_neg);
|
||||
|
||||
let h = 1;
|
||||
let h_neg: u32 = -h;
|
||||
println!("{}", h_neg);
|
||||
|
||||
let i = 1;
|
||||
let i_neg: u64 = -i;
|
||||
println!("{}", i_neg);
|
||||
|
||||
let j = 1;
|
||||
let j_neg: usize = -j;
|
||||
println!("{}", j_neg);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user