diff options
| author | bors <bors@rust-lang.org> | 2020-02-12 10:10:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-02-12 10:10:15 +0000 |
| commit | cd5441faf4e56d136d7c05d5eb55b4a41396edaf (patch) | |
| tree | 27e27611e789f2cf88d5efe83c1fa543dee6590f /src | |
| parent | 7cba853b4f6080bf7831169fe5632ec9b6833242 (diff) | |
| parent | 486856f75fd8c681f728ed3445e285666dbe19b9 (diff) | |
| download | rust-cd5441faf4e56d136d7c05d5eb55b4a41396edaf.tar.gz rust-cd5441faf4e56d136d7c05d5eb55b4a41396edaf.zip | |
Auto merge of #69088 - JohnTitor:rollup-x7bk7h7, r=JohnTitor
Rollup of 11 pull requests Successful merges: - #67695 (Added dyn and true keyword docs) - #68487 ([experiment] Support linking from a .rlink file) - #68554 (Split lang_items to crates `rustc_hir` and `rustc_passes`.) - #68937 (Test failure of unchecked arithmetic intrinsics in const eval) - #68947 (Python script PEP8 style guide space formatting and minor Python source cleanup) - #68999 (remove dependency on itertools) - #69026 (Remove common usage pattern from `AllocRef`) - #69027 (Add missing `_zeroed` varants to `AllocRef`) - #69058 (Preparation for allocator aware `Box`) - #69070 (Add self to .mailmap) - #69077 (Fix outdated doc comment.) Failed merges: r? @ghost
Diffstat (limited to 'src')
55 files changed, 1198 insertions, 1022 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1935759a562..50e1726240f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -80,7 +80,7 @@ def _download(path, url, probably_big, verbose, exception): option = "-s" run(["curl", option, "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds - "--connect-timeout", "30", # timeout if cannot connect within 30 seconds + "--connect-timeout", "30", # timeout if cannot connect within 30 seconds "--retry", "3", "-Sf", "-o", path, url], verbose=verbose, exception=exception) @@ -332,7 +332,6 @@ class RustBuild(object): self.use_vendored_sources = '' self.verbose = False - def download_stage0(self): """Fetch the build system for Rust, written in Rust @@ -351,7 +350,7 @@ class RustBuild(object): try: with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name - with tarfile.open(temp_path, "w:xz") as tar: + with tarfile.open(temp_path, "w:xz"): pass return True except tarfile.CompressionError: @@ -825,7 +824,7 @@ class RustBuild(object): if not os.path.exists(vendor_dir): print('error: vendoring required, but vendor directory does not exist.') print(' Run `cargo vendor` without sudo to initialize the ' - 'vendor directory.') + 'vendor directory.') raise Exception("{} not found".format(vendor_dir)) if self.use_vendored_sources: @@ -839,7 +838,7 @@ class RustBuild(object): "\n" "[source.vendored-sources]\n" "directory = '{}/vendor'\n" - .format(self.rust_root)) + .format(self.rust_root)) else: if os.path.exists('.cargo'): shutil.rmtree('.cargo') diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 1fdd5d13e7f..3d2eead6788 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -393,11 +393,12 @@ for target in configured_targets: def is_number(value): - try: - float(value) - return True - except ValueError: - return False + try: + float(value) + return True + except ValueError: + return False + # Here we walk through the constructed configuration we have from the parsed # command line arguments. We then apply each piece of configuration by diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py index daf21670b33..78ac0603681 100644 --- a/src/ci/cpu-usage-over-time.py +++ b/src/ci/cpu-usage-over-time.py @@ -148,11 +148,11 @@ else: print('unknown platform', sys.platform) sys.exit(1) -cur_state = State(); +cur_state = State() print("Time,Idle") while True: - time.sleep(1); - next_state = State(); + time.sleep(1) + next_state = State() now = datetime.datetime.utcnow().isoformat() idle = next_state.idle_since(cur_state) print("%s,%s" % (now, idle)) diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 385ce8efab8..b3f8f50636b 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -212,7 +212,6 @@ class Type(object): # REGULAR STRUCT return TYPE_KIND_REGULAR_STRUCT - def __classify_union(self): assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION @@ -233,7 +232,6 @@ class Type(object): else: return TYPE_KIND_REGULAR_UNION - def __conforms_to_field_layout(self, expected_fields): actual_fields = self.get_fields() actual_field_count = len(actual_fields) @@ -363,6 +361,7 @@ def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val): assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR return (tail, head, data_ptr, capacity) + def extract_length_and_ptr_from_slice(slice_val): assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE) @@ -376,8 +375,10 @@ def extract_length_and_ptr_from_slice(slice_val): assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR return (length, data_ptr) + UNQUALIFIED_TYPE_MARKERS = frozenset(["(", "[", "&", "*"]) + def extract_type_name(qualified_type_name): """Extracts the type name from a fully qualified path""" if qualified_type_name[0] in UNQUALIFIED_TYPE_MARKERS: @@ -393,6 +394,7 @@ def extract_type_name(qualified_type_name): else: return qualified_type_name[index + 2:] + try: compat_str = unicode # Python 2 except NameError: diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py index 85395d2ecdf..4979882ffea 100755 --- a/src/etc/dec2flt_table.py +++ b/src/etc/dec2flt_table.py @@ -14,7 +14,6 @@ is used because (u64, i16) has a ton of padding which would make the table even larger, and it's already uncomfortably large (6 KiB). """ from __future__ import print_function -import sys from math import ceil, log from fractions import Fraction from collections import namedtuple @@ -82,6 +81,7 @@ def error(f, e, z): ulp_err = abs_err / Fraction(2) ** z.exp return float(ulp_err) + HEADER = """ //! Tables of approximations of powers of ten. //! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py` diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 5da01b96fa5..0914c22eb13 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -9,7 +9,7 @@ import debugger_pretty_printers_common as rustpp if sys.version_info[0] >= 3: xrange = range -rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True) +rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True) # The btree pretty-printers fail in a confusing way unless # https://sourceware.org/bugzilla/show_bug.cgi?id=21763 is fixed. @@ -21,9 +21,10 @@ if _match: if int(_match.group(1)) > 8 or (int(_match.group(1)) == 8 and int(_match.group(2)) >= 1): gdb_81 = True -#=============================================================================== +# =============================================================================== # GDB Pretty Printing Module for Rust -#=============================================================================== +# =============================================================================== + class GdbType(rustpp.Type): @@ -133,39 +134,39 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: return RustStructPrinter(val, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = False) + omit_first_field=False, + omit_type_name=False, + is_tuple_like=False) if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: return RustStructPrinter(val, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = False) + omit_first_field=True, + omit_type_name=False, + is_tuple_like=False) if type_kind == rustpp.TYPE_KIND_STR_SLICE: return RustStringSlicePrinter(val) if type_kind == rustpp.TYPE_KIND_TUPLE: return RustStructPrinter(val, - omit_first_field = False, - omit_type_name = True, - is_tuple_like = True) + omit_first_field=False, + omit_type_name=True, + is_tuple_like=True) if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT: return RustStructPrinter(val, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = True) + omit_first_field=False, + omit_type_name=False, + is_tuple_like=True) if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT: return RustCStyleVariantPrinter(val.get_child_at_index(0)) if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT: return RustStructPrinter(val, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = True) + omit_first_field=True, + omit_type_name=False, + is_tuple_like=True) if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM: variant = get_field_at_index(gdb_val, 0) @@ -189,9 +190,9 @@ def rust_pretty_printer_lookup_function(gdb_val): return None -#=------------------------------------------------------------------------------ +# =------------------------------------------------------------------------------ # Pretty Printer Classes -#=------------------------------------------------------------------------------ +# =------------------------------------------------------------------------------ class RustEmptyPrinter(object): def __init__(self, val): self.__val = val @@ -355,6 +356,7 @@ def children_of_node(boxed_node, height, want_values): else: yield keys[i]['value']['value'] + class RustStdBTreeSetPrinter(object): def __init__(self, val): self.__val = val @@ -429,6 +431,7 @@ class RustOsStringPrinter(object): def display_hint(self): return "string" + class RustCStyleVariantPrinter(object): def __init__(self, val): assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index afa6bbdae4e..c42f942c63c 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -8,7 +8,8 @@ derives have spans that point to the fields, rather than the sample usage: src/etc/generate-deriving-span-tests.py """ -import os, stat +import os +import stat TEST_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), '../test/ui/derives/')) @@ -56,6 +57,7 @@ struct Struct( ENUM_TUPLE, ENUM_STRUCT, STRUCT_FIELDS, STRUCT_TUPLE = range(4) + def create_test_case(type, trait, super_traits, error_count): string = [ENUM_STRING, ENUM_STRUCT_VARIANT_STRING, STRUCT_STRING, STRUCT_TUPLE_STRING][type] all_traits = ','.join([trait] + super_traits) @@ -63,8 +65,9 @@ def create_test_case(type, trait, super_traits, error_count): error_deriving = '#[derive(%s)]' % super_traits if super_traits else '' errors = '\n'.join('//~%s ERROR' % ('^' * n) for n in range(error_count)) - code = string.format(traits = all_traits, errors = errors) - return TEMPLATE.format(error_deriving=error_deriving, code = code) + code = string.format(traits=all_traits, errors=errors) + return TEMPLATE.format(error_deriving=error_deriving, code=code) + def write_file(name, string): test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name) @@ -86,10 +89,10 @@ ALL = STRUCT | ENUM traits = { 'Default': (STRUCT, [], 1), - 'FromPrimitive': (0, [], 0), # only works for C-like enums + 'FromPrimitive': (0, [], 0), # only works for C-like enums - 'Decodable': (0, [], 0), # FIXME: quoting gives horrible spans - 'Encodable': (0, [], 0), # FIXME: quoting gives horrible spans + 'Decodable': (0, [], 0), # FIXME: quoting gives horrible spans + 'Encodable': (0, [], 0), # FIXME: quoting gives horrible spans } for (trait, supers, errs) in [('Clone', [], 1), diff --git a/src/etc/generate-keyword-tests.py b/src/etc/generate-keyword-tests.py index bc046a8f42d..77c3d2758c6 100755 --- a/src/etc/generate-keyword-tests.py +++ b/src/etc/generate-keyword-tests.py @@ -11,7 +11,6 @@ sample usage: src/etc/generate-keyword-tests.py as break import sys import os -import datetime import stat diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index e8be2b9b537..7789b24b62c 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -131,6 +131,7 @@ try: except NameError: unichr = chr + class CustomHTMLParser(HTMLParser): """simplified HTML parser. @@ -169,21 +170,25 @@ class CustomHTMLParser(HTMLParser): HTMLParser.close(self) return self.__builder.close() + Command = namedtuple('Command', 'negated cmd args lineno context') + class FailedCheck(Exception): pass + class InvalidCheck(Exception): pass + def concat_multi_lines(f): """returns a generator out of the file object, which - removes `\\` then `\n` then a shared prefix with the previous line then optional whitespace; - keeps a line number (starting from 0) of the first line being concatenated.""" - lastline = None # set to the last line when the last line has a backslash + lastline = None # set to the last line when the last line has a backslash firstlineno = None catenated = '' for lineno, line in enumerate(f): @@ -208,6 +213,7 @@ def concat_multi_lines(f): if lastline is not None: print_err(lineno, line, 'Trailing backslash at the end of the file') + LINE_PATTERN = re.compile(r''' (?<=(?<!\S)@)(?P<negated>!?) (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*) @@ -252,7 +258,7 @@ def flatten(node): def normalize_xpath(path): if path.startswith('//'): - return '.' + path # avoid warnings + return '.' + path # avoid warnings elif path.startswith('.//'): return path else: @@ -316,7 +322,7 @@ class CachedFiles(object): def check_string(data, pat, regexp): if not pat: - return True # special case a presence testing + return True # special case a presence testing elif regexp: return re.search(pat, data, flags=re.UNICODE) is not None else: @@ -353,7 +359,7 @@ def check_tree_text(tree, path, pat, regexp): ret = check_string(value, pat, regexp) if ret: break - except Exception as e: + except Exception: print('Failed to get path "{}"'.format(path)) raise return ret @@ -363,6 +369,7 @@ def get_tree_count(tree, path): path = normalize_xpath(path) return len(tree.findall(path)) + def stderr(*args): if sys.version_info.major < 3: file = codecs.getwriter('utf-8')(sys.stderr) @@ -371,6 +378,7 @@ def stderr(*args): print(*args, file=file) + def print_err(lineno, context, err, message=None): global ERR_COUNT ERR_COUNT += 1 @@ -381,31 +389,33 @@ def print_err(lineno, context, err, message=None): if context: stderr("\t{}".format(context)) + ERR_COUNT = 0 + def check_command(c, cache): try: cerr = "" - if c.cmd == 'has' or c.cmd == 'matches': # string test + if c.cmd == 'has' or c.cmd == 'matches': # string test regexp = (c.cmd == 'matches') - if len(c.args) == 1 and not regexp: # @has <path> = file existence + if len(c.args) == 1 and not regexp: # @has <path> = file existence try: cache.get_file(c.args[0]) ret = True except FailedCheck as err: cerr = str(err) ret = False - elif len(c.args) == 2: # @has/matches <path> <pat> = string test + elif len(c.args) == 2: # @has/matches <path> <pat> = string test cerr = "`PATTERN` did not match" ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp) - elif len(c.args) == 3: # @has/matches <path> <pat> <match> = XML tree test + elif len(c.args) == 3: # @has/matches <path> <pat> <match> = XML tree test cerr = "`XPATH PATTERN` did not match" tree = cache.get_tree(c.args[0]) pat, sep, attr = c.args[1].partition('/@') - if sep: # attribute + if sep: # attribute tree = cache.get_tree(c.args[0]) ret = check_tree_attr(tree, pat, attr, c.args[2], regexp) - else: # normalized text + else: # normalized text pat = c.args[1] if pat.endswith('/text()'): pat = pat[:-7] @@ -413,16 +423,16 @@ def check_command(c, cache): else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) - elif c.cmd == 'count': # count test - if len(c.args) == 3: # @count <path> <pat> <count> = count test + elif c.cmd == 'count': # count test + if len(c.args) == 3: # @count <path> <pat> <count> = count test expected = int(c.args[2]) found = get_tree_count(cache.get_tree(c.args[0]), c.args[1]) cerr = "Expected {} occurrences but found {}".format(expected, found) ret = expected == found else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) - elif c.cmd == 'has-dir': # has-dir test - if len(c.args) == 1: # @has-dir <path> = has-dir test + elif c.cmd == 'has-dir': # has-dir test + if len(c.args) == 1: # @has-dir <path> = has-dir test try: cache.get_dir(c.args[0]) ret = True @@ -448,11 +458,13 @@ def check_command(c, cache): except InvalidCheck as err: print_err(c.lineno, c.context, str(err)) + def check(target, commands): cache = CachedFiles(target) for c in commands: check_command(c, cache) + if __name__ == '__main__': if len(sys.argv) != 3: stderr('Usage: {} <doc dir> <template>'.format(sys.argv[0])) diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py index 7c2e91474c1..d9c4bc5562f 100644 --- a/src/etc/lldb_batchmode.py +++ b/src/etc/lldb_batchmode.py @@ -157,6 +157,7 @@ def start_watchdog(): # ~main #################################################################################################### + if len(sys.argv) != 3: print("usage: python lldb_batchmode.py target-path script-path") sys.exit(1) diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py index fdc1c4fa0cc..0c4021b36fb 100644 --- a/src/etc/lldb_rust_formatters.py +++ b/src/etc/lldb_rust_formatters.py @@ -1,10 +1,10 @@ import lldb -import re import debugger_pretty_printers_common as rustpp -#=============================================================================== +# =============================================================================== # LLDB Pretty Printing Module for Rust -#=============================================================================== +# =============================================================================== + class LldbType(rustpp.Type): @@ -84,16 +84,16 @@ def print_val(lldb_val, internal_dict): type_kind == rustpp.TYPE_KIND_EMPTY): return print_struct_val(val, internal_dict, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = False) + omit_first_field=False, + omit_type_name=False, + is_tuple_like=False) if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: return print_struct_val(val, internal_dict, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = False) + omit_first_field=True, + omit_type_name=False, + is_tuple_like=False) if type_kind == rustpp.TYPE_KIND_SLICE: return print_vec_slice_val(val, internal_dict) @@ -110,16 +110,16 @@ def print_val(lldb_val, internal_dict): if type_kind == rustpp.TYPE_KIND_TUPLE: return print_struct_val(val, internal_dict, - omit_first_field = False, - omit_type_name = True, - is_tuple_like = True) + omit_first_field=False, + omit_type_name=True, + is_tuple_like=True) if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT: return print_struct_val(val, internal_dict, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = True) + omit_first_field=False, + omit_type_name=False, + is_tuple_like=True) if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT: return val.type.get_unqualified_type_name() @@ -127,9 +127,9 @@ def print_val(lldb_val, internal_dict): if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT: return print_struct_val(val, internal_dict, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = True) + omit_first_field=True, + omit_type_name=False, + is_tuple_like=True) if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM: return print_val(lldb_val.GetChildAtIndex(0), internal_dict) @@ -157,9 +157,9 @@ def print_val(lldb_val, internal_dict): return lldb_val.GetValue() -#=-------------------------------------------------------------------------------------------------- +# =--------------------------------------------------------------------------------------- # Type-Specialized Printing Functions -#=-------------------------------------------------------------------------------------------------- +# =--------------------------------------------------------------------------------------- def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tuple_like): """ @@ -212,6 +212,7 @@ def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tu return template % {"type_name": type_name, "body": body} + def print_pointer_val(val, internal_dict): """Prints a pointer value with Rust syntax""" assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR @@ -253,18 +254,21 @@ def print_std_vec_val(val, internal_dict): length, internal_dict) + def print_str_slice_val(val, internal_dict): (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(val) return read_utf8_string(data_ptr, length) + def print_std_string_val(val, internal_dict): vec = val.get_child_at_index(0) (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec) return read_utf8_string(data_ptr, length) -#=-------------------------------------------------------------------------------------------------- +# =----------------------------------------------------------------------- # Helper Functions -#=-------------------------------------------------------------------------------------------------- +# =----------------------------------------------------------------------- + def print_array_of_values(array_name, data_ptr_val, length, internal_dict): """Prints a contiguous memory range, interpreting it as values of the diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 9fb0de63e6f..f41404bf8ca 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -200,21 +200,27 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { align as *mut u8 } else { let layout = Layout::from_size_align_unchecked(size, align); - let ptr = alloc(layout); - if !ptr.is_null() { ptr } else { handle_alloc_error(layout) } + match Global.alloc(layout) { + Ok(ptr) => ptr.as_ptr(), + Err(_) => handle_alloc_error(layout), + } } } #[cfg_attr(not(test), lang = "box_free")] #[inline] +// This signature has to be the same as `Box`, otherwise an ICE will happen. +// When an additional parameter to `Box` is added (like `A: AllocRef`), this has to be added here as +// well. +// For example if `Box` is changed to `struct Box<T: ?Sized, A: AllocRef>(Unique<T>, A)`, +// this function has to be changed to `fn box_free<T: ?Sized, A: AllocRef>(Unique<T>, A)` as well. pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) { - let ptr = ptr.as_ptr(); - let size = size_of_val(&*ptr); - let align = min_align_of_val(&*ptr); + let size = size_of_val(ptr.as_ref()); + let align = min_align_of_val(ptr.as_ref()); // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary. if size != 0 { let layout = Layout::from_size_align_unchecked(size, align); - dealloc(ptr as *mut u8, layout); + Global.dealloc(ptr.cast().into(), layout); } } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index d65aee09232..3ac4bd82a3a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -196,12 +196,14 @@ impl<T> Box<T> { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box<mem::MaybeUninit<T>> { let layout = alloc::Layout::new::<mem::MaybeUninit<T>>(); - if layout.size() == 0 { - return Box(NonNull::dangling().into()); + unsafe { + let ptr = if layout.size() == 0 { + NonNull::dangling() + } else { + Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast() + }; + Box::from_raw(ptr.as_ptr()) } - let ptr = - unsafe { Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)) }; - Box(ptr.cast().into()) } /// Constructs a new `Box` with uninitialized contents, with the memory @@ -264,15 +266,14 @@ impl<T> Box<[T]> { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> { let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap(); - let ptr = if layout.size() == 0 { - NonNull::dangling() - } else { - unsafe { + unsafe { + let ptr = if layout.size() == 0 { + NonNull::dangling() + } else { Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast() - } - }; - let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) }; - Box(Unique::from(slice)) + }; + Box::from_raw(slice::from_raw_parts_mut(ptr.as_ptr(), len)) + } } } @@ -308,7 +309,7 @@ impl<T> Box<mem::MaybeUninit<T>> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box<T> { - Box(Box::into_unique(self).cast()) + Box::from_raw(Box::into_raw(self) as *mut T) } } @@ -346,7 +347,7 @@ impl<T> Box<[mem::MaybeUninit<T>]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box<[T]> { - Box(Unique::new_unchecked(Box::into_raw(self) as _)) + Box::from_raw(Box::into_raw(self) as *mut [T]) } } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index e1b549bed18..144654946a2 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -280,7 +280,7 @@ impl<T, A: AllocRef> RawVec<T, A> { // 0, getting to here necessarily means the `RawVec` is overfull. assert!(elem_size != 0, "capacity overflow"); - let (new_cap, uniq) = match self.current_layout() { + let (new_cap, ptr) = match self.current_layout() { Some(cur) => { // Since we guarantee that we never allocate more than // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as @@ -297,7 +297,7 @@ impl<T, A: AllocRef> RawVec<T, A> { alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size); match ptr_res { - Ok(ptr) => (new_cap, ptr.cast().into()), + Ok(ptr) => (new_cap, ptr), Err(_) => handle_alloc_error(Layout::from_size_align_unchecked( new_size, cur.align(), @@ -308,13 +308,14 @@ impl<T, A: AllocRef> RawVec<T, A> { // Skip to 4 because tiny `Vec`'s are dumb; but not if that // would cause overflow. let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; - match self.a.alloc_array::<T>(new_cap) { - Ok(ptr) => (new_cap, ptr.into()), - Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()), + let layout = Layout::array::<T>(new_cap).unwrap(); + match self.a.alloc(layout) { + Ok(ptr) => (new_cap, ptr), + Err(_) => handle_alloc_error(layout), } } }; - self.ptr = uniq; + self.ptr = ptr.cast().into(); self.cap = new_cap; } } diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 38df843d258..71f7f971eab 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -593,9 +593,8 @@ pub unsafe trait GlobalAlloc { /// /// * the starting address for that memory block was previously /// returned by a previous call to an allocation method (`alloc`, -/// `alloc_zeroed`, `alloc_excess`, `alloc_one`, `alloc_array`) or -/// reallocation method (`realloc`, `realloc_excess`, or -/// `realloc_array`), and +/// `alloc_zeroed`, `alloc_excess`) or reallocation method +/// (`realloc`, `realloc_excess`), and /// /// * the memory block has not been subsequently deallocated, where /// blocks are deallocated either by being passed to a deallocation @@ -606,11 +605,6 @@ pub unsafe trait GlobalAlloc { /// methods in the `AllocRef` trait state that allocation requests /// must be non-zero size, or else undefined behavior can result. /// -/// * However, some higher-level allocation methods (`alloc_one`, -/// `alloc_array`) are well-defined on zero-sized types and can -/// optionally support them: it is left up to the implementor -/// whether to return `Err`, or to return `Ok` with some pointer. -/// /// * If an `AllocRef` implementation chooses to return `Ok` in this /// case (i.e., the pointer denotes a zero-sized inaccessible block) /// then that returned pointer must be considered "currently @@ -853,6 +847,59 @@ pub unsafe trait AllocRef { result } + /// Behaves like `realloc`, but also ensures that the new contents + /// are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `realloc` is. + /// + /// # Errors + /// + /// Returns `Err` only if the new layout + /// does not meet the allocator's size + /// and alignment constraints of the allocator, or if reallocation + /// otherwise fails. + /// + /// Implementations are encouraged to return `Err` on memory + /// exhaustion rather than panicking or aborting, but this is not + /// a strict requirement. (Specifically: it is *legal* to + /// implement this trait atop an underlying native allocation + /// library that aborts on memory exhaustion.) + /// + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn realloc_zeroed( + &mut self, + ptr: NonNull<u8>, + layout: Layout, + new_size: usize, + ) -> Result<NonNull<u8>, AllocErr> { + let old_size = layout.size(); + + if new_size >= old_size { + if let Ok(()) = self.grow_in_place_zeroed(ptr, layout, new_size) { + return Ok(ptr); + } + } else if new_size < old_size { + if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) { + return Ok(ptr); + } + } + + // otherwise, fall back on alloc + copy + dealloc. + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let result = self.alloc_zeroed(new_layout); + if let Ok(new_ptr) = result { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size)); + self.dealloc(ptr, layout); + } + result + } + /// Behaves like `alloc`, but also ensures that the contents /// are set to zero before being returned. /// @@ -904,6 +951,31 @@ pub unsafe trait AllocRef { self.alloc(layout).map(|p| Excess(p, usable_size.1)) } + /// Behaves like `alloc`, but also returns the whole size of + /// the returned block. For some `layout` inputs, like arrays, this + /// may include extra storage usable for additional data. + /// Also it ensures that the contents are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn alloc_excess_zeroed(&mut self, layout: Layout) -> Result<Excess, AllocErr> { + let usable_size = self.usable_size(&layout); + self.alloc_zeroed(layout).map(|p| Excess(p, usable_size.1)) + } + /// Behaves like `realloc`, but also returns the whole size of /// the returned block. For some `layout` inputs, like arrays, this /// may include extra storage usable for additional data. @@ -934,6 +1006,37 @@ pub unsafe trait AllocRef { self.realloc(ptr, layout, new_size).map(|p| Excess(p, usable_size.1)) } + /// Behaves like `realloc`, but also returns the whole size of + /// the returned block. For some `layout` inputs, like arrays, this + /// may include extra storage usable for additional data. + /// Also it ensures that the contents are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `realloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `realloc`. + /// + /// Clients wishing to abort computation in response to a + /// reallocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn realloc_excess_zeroed( + &mut self, + ptr: NonNull<u8>, + layout: Layout, + new_size: usize, + ) -> Result<Excess, AllocErr> { + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let usable_size = self.usable_size(&new_layout); + self.realloc_zeroed(ptr, layout, new_size).map(|p| Excess(p, usable_size.1)) + } + /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`. /// /// If this returns `Ok`, then the allocator has asserted that the @@ -983,6 +1086,34 @@ pub unsafe trait AllocRef { if new_size <= u { Ok(()) } else { Err(CannotReallocInPlace) } } + /// Behaves like `grow_in_place`, but also ensures that the new + /// contents are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `grow_in_place` is. + /// + /// # Errors + /// + /// Returns `Err(CannotReallocInPlace)` when the allocator is + /// unable to assert that the memory block referenced by `ptr` + /// could fit `layout`. + /// + /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error` + /// function; clients are expected either to be able to recover from + /// `grow_in_place` failures without aborting, or to fall back on + /// another reallocation method before resorting to an abort. + unsafe fn grow_in_place_zeroed( + &mut self, + ptr: NonNull<u8>, + layout: Layout, + new_size: usize, + ) -> Result<(), CannotReallocInPlace> { + self.grow_in_place(ptr, layout, new_size)?; + ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size()); + Ok(()) + } + /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`. /// /// If this returns `Ok`, then the allocator has asserted that the @@ -1035,195 +1166,4 @@ pub unsafe trait AllocRef { // new_layout.size() <= layout.size() [required by this method] if l <= new_size { Ok(()) } else { Err(CannotReallocInPlace) } } - - // == COMMON USAGE PATTERNS == - // alloc_one, dealloc_one, alloc_array, realloc_array. dealloc_array - - /// Allocates a block suitable for holding an instance of `T`. - /// - /// Captures a common usage pattern for allocators. - /// - /// The returned block is suitable for passing to the - /// `realloc`/`dealloc` methods of this allocator. - /// - /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` - /// must be considered "currently allocated" and must be - /// acceptable input to methods such as `realloc` or `dealloc`, - /// *even if* `T` is a zero-sized type. In other words, if your - /// `AllocRef` implementation overrides this method in a manner - /// that can return a zero-sized `ptr`, then all reallocation and - /// deallocation methods need to be similarly overridden to accept - /// such values as input. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `T` does not meet allocator's size or alignment constraints. - /// - /// For zero-sized `T`, may return either of `Ok` or `Err`, but - /// will *not* yield undefined behavior. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr> - where - Self: Sized, - { - let k = Layout::new::<T>(); - if k.size() > 0 { unsafe { self.alloc(k).map(|p| p.cast()) } } else { Err(AllocErr) } - } - - /// Deallocates a block suitable for holding an instance of `T`. - /// - /// The given block must have been produced by this allocator, - /// and must be suitable for storing a `T` (in terms of alignment - /// as well as minimum and maximum size); otherwise yields - /// undefined behavior. - /// - /// Captures a common usage pattern for allocators. - /// - /// # Safety - /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure both: - /// - /// * `ptr` must denote a block of memory currently allocated via this allocator - /// - /// * the layout of `T` must *fit* that block of memory. - unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>) - where - Self: Sized, - { - let k = Layout::new::<T>(); - if k.size() > 0 { - self.dealloc(ptr.cast(), k); - } - } - - /// Allocates a block suitable for holding `n` instances of `T`. - /// - /// Captures a common usage pattern for allocators. - /// - /// The returned block is suitable for passing to the - /// `realloc`/`dealloc` methods of this allocator. - /// - /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` - /// must be considered "currently allocated" and must be - /// acceptable input to methods such as `realloc` or `dealloc`, - /// *even if* `T` is a zero-sized type. In other words, if your - /// `AllocRef` implementation overrides this method in a manner - /// that can return a zero-sized `ptr`, then all reallocation and - /// deallocation methods need to be similarly overridden to accept - /// such values as input. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `[T; n]` does not meet allocator's size or alignment - /// constraints. - /// - /// For zero-sized `T` or `n == 0`, may return either of `Ok` or - /// `Err`, but will *not* yield undefined behavior. - /// - /// Always returns `Err` on arithmetic overflow. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr> - where - Self: Sized, - { - match Layout::array::<T>(n) { - Ok(layout) if layout.size() > 0 => unsafe { self.alloc(layout).map(|p| p.cast()) }, - _ => Err(AllocErr), - } - } - - /// Reallocates a block previously suitable for holding `n_old` - /// instances of `T`, returning a block suitable for holding - /// `n_new` instances of `T`. - /// - /// Captures a common usage pattern for allocators. - /// - /// The returned block is suitable for passing to the - /// `realloc`/`dealloc` methods of this allocator. - /// - /// # Safety - /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure all of the following: - /// - /// * `ptr` must be currently allocated via this allocator, - /// - /// * the layout of `[T; n_old]` must *fit* that block of memory. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `[T; n_new]` does not meet allocator's size or alignment - /// constraints. - /// - /// For zero-sized `T` or `n_new == 0`, may return either of `Ok` or - /// `Err`, but will *not* yield undefined behavior. - /// - /// Always returns `Err` on arithmetic overflow. - /// - /// Clients wishing to abort computation in response to a - /// reallocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn realloc_array<T>( - &mut self, - ptr: NonNull<T>, - n_old: usize, - n_new: usize, - ) -> Result<NonNull<T>, AllocErr> - where - Self: Sized, - { - match (Layout::array::<T>(n_old), Layout::array::<T>(n_new)) { - (Ok(k_old), Ok(k_new)) if k_old.size() > 0 && k_new.size() > 0 => { - debug_assert!(k_old.align() == k_new.align()); - self.realloc(ptr.cast(), k_old, k_new.size()).map(NonNull::cast) - } - _ => Err(AllocErr), - } - } - - /// Deallocates a block suitable for holding `n` instances of `T`. - /// - /// Captures a common usage pattern for allocators. - /// - /// # Safety - /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure both: - /// - /// * `ptr` must denote a block of memory currently allocated via this allocator - /// - /// * the layout of `[T; n]` must *fit* that block of memory. - /// - /// # Errors - /// - /// Returning `Err` indicates that either `[T; n]` or the given - /// memory block does not meet allocator's size or alignment - /// constraints. - /// - /// Always returns `Err` on arithmetic overflow. - unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr> - where - Self: Sized, - { - match Layout::array::<T>(n) { - Ok(k) if k.size() > 0 => Ok(self.dealloc(ptr.cast(), k)), - _ => Err(AllocErr), - } - } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2e7e8fdd724..7d48280661a 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2,7 +2,6 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html -pub mod check_attr; pub mod exports; pub mod map; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 625d8a4670f..1a763e43d55 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -251,12 +251,6 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::def_id::DefIndex { } } -impl<'a> HashStable<StableHashingContext<'a>> for crate::middle::lang_items::LangItem { - fn hash_stable(&self, _: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - ::std::hash::Hash::hash(self, hasher); - } -} - impl<'a> HashStable<StableHashingContext<'a>> for hir::TraitCandidate { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 2bda0c0bef0..88ddd96eec8 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -1,40 +1,3 @@ -macro_rules! enum_from_u32 { - ($(#[$attr:meta])* pub enum $name:ident { - $($variant:ident = $e:expr,)* - }) => { - $(#[$attr])* - pub enum $name { - $($variant = $e),* - } - - impl $name { - pub fn from_u32(u: u32) -> Option<$name> { - $(if u == $name::$variant as u32 { - return Some($name::$variant) - })* - None - } - } - }; - ($(#[$attr:meta])* pub enum $name:ident { - $($variant:ident,)* - }) => { - $(#[$attr])* - pub enum $name { - $($variant,)* - } - - impl $name { - pub fn from_u32(u: u32) -> Option<$name> { - $(if u == $name::$variant as u32 { - return Some($name::$variant) - })* - None - } - } - } -} - #[macro_export] macro_rules! bug { () => ( bug!("impossible case reached") ); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 9e33ee8da21..c8e284be6fc 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -9,401 +9,14 @@ pub use self::LangItem::*; -use crate::hir::check_attr::Target; -use crate::middle::cstore::ExternCrate; -use crate::middle::weak_lang_items; use crate::ty::{self, TyCtxt}; -use rustc_data_structures::fx::FxHashMap; -use rustc_errors::struct_span_err; -use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_macros::HashStable; -use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -use syntax::ast; +use rustc_target::spec::PanicStrategy; -// The actual lang items defined come at the end of this file in one handy table. -// So you probably just want to nip down to the end. -macro_rules! language_item_table { - ( - $( $variant:ident, $name:expr, $method:ident, $target:path; )* - ) => { - -enum_from_u32! { - /// A representation of all the valid language items in Rust. - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] - pub enum LangItem { - $($variant,)* - } -} - -impl LangItem { - /// Returns the `name` in `#[lang = "$name"]`. - /// For example, `LangItem::EqTraitLangItem`, - /// that is `#[lang = "eq"]` would result in `"eq"`. - fn name(self) -> &'static str { - match self { - $( $variant => $name, )* - } - } -} - -#[derive(HashStable)] -pub struct LanguageItems { - /// Mappings from lang items to their possibly found `DefId`s. - /// The index corresponds to the order in `LangItem`. - pub items: Vec<Option<DefId>>, - /// Lang items that were not found during collection. - pub missing: Vec<LangItem>, -} - -impl LanguageItems { - /// Construct an empty collection of lang items and no missing ones. - pub fn new() -> Self { - fn init_none(_: LangItem) -> Option<DefId> { None } - - Self { - items: vec![$(init_none($variant)),*], - missing: Vec::new(), - } - } - - /// Returns the mappings to the possibly found `DefId`s for each lang item. - pub fn items(&self) -> &[Option<DefId>] { - &*self.items - } - - /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`. - /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`, - /// returns an error message as a string. - pub fn require(&self, it: LangItem) -> Result<DefId, String> { - self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name())) - } - - /// Returns the kind of closure that `id`, which is one of the `Fn*` traits, corresponds to. - /// If `id` is not one of the `Fn*` traits, `None` is returned. - pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> { - match Some(id) { - x if x == self.fn_trait() => Some(ty::ClosureKind::Fn), - x if x == self.fn_mut_trait() => Some(ty::ClosureKind::FnMut), - x if x == self.fn_once_trait() => Some(ty::ClosureKind::FnOnce), - _ => None - } - } - - $( - /// Returns the corresponding `DefId` for the lang item - #[doc = $name] - /// if it exists. - #[allow(dead_code)] - pub fn $method(&self) -> Option<DefId> { - self.items[$variant as usize] - } - )* -} - -struct LanguageItemCollector<'tcx> { - items: LanguageItems, - tcx: TyCtxt<'tcx>, - /// A mapping from the name of the lang item to its order and the form it must be of. - item_refs: FxHashMap<&'static str, (usize, Target)>, -} - -impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { - fn visit_item(&mut self, item: &hir::Item<'_>) { - if let Some((value, span)) = extract(&item.attrs) { - let actual_target = Target::from_item(item); - match self.item_refs.get(&*value.as_str()).cloned() { - // Known lang item with attribute on correct target. - Some((item_index, expected_target)) if actual_target == expected_target => { - let def_id = self.tcx.hir().local_def_id(item.hir_id); - self.collect_item(item_index, def_id); - }, - // Known lang item with attribute on incorrect target. - Some((_, expected_target)) => { - struct_span_err!( - self.tcx.sess, span, E0718, - "`{}` language item must be applied to a {}", - value, expected_target, - ).span_label( - span, - format!( - "attribute should be applied to a {}, not a {}", - expected_target, actual_target, - ), - ).emit(); - }, - // Unknown lang item. - _ => { - struct_span_err!( - self.tcx.sess, span, E0522, - "definition of an unknown language item: `{}`", - value - ).span_label( - span, - format!("definition of unknown language item `{}`", value) - ).emit(); - }, - } - } - } - - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) { - // At present, lang items are always items, not trait items. - } - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) { - // At present, lang items are always items, not impl items. - } -} - -impl LanguageItemCollector<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> { - let mut item_refs = FxHashMap::default(); - - $( item_refs.insert($name, ($variant as usize, $target)); )* - - LanguageItemCollector { - tcx, - items: LanguageItems::new(), - item_refs, - } - } - - fn collect_item(&mut self, item_index: usize, item_def_id: DefId) { - // Check for duplicates. - if let Some(original_def_id) = self.items.items[item_index] { - if original_def_id != item_def_id { - let name = LangItem::from_u32(item_index as u32).unwrap().name(); - let mut err = match self.tcx.hir().span_if_local(item_def_id) { - Some(span) => struct_span_err!( - self.tcx.sess, - span, - E0152, - "found duplicate lang item `{}`", - name - ), - None => { - match self.tcx.extern_crate(item_def_id) { - Some(ExternCrate {dependency_of, ..}) => { - self.tcx.sess.struct_err(&format!( - "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.", - self.tcx.crate_name(item_def_id.krate), - self.tcx.crate_name(*dependency_of), - name)) - }, - _ => { - self.tcx.sess.struct_err(&format!( - "duplicate lang item in crate `{}`: `{}`.", - self.tcx.crate_name(item_def_id.krate), - name)) - } - } - }, - }; - if let Some(span) = self.tcx.hir().span_if_local(original_def_id) { - err.span_note(span, "the lang item is first defined here"); - } else { - match self.tcx.extern_crate(original_def_id) { - Some(ExternCrate {dependency_of, ..}) => { - err.note(&format!( - "the lang item is first defined in crate `{}` (which `{}` depends on)", - self.tcx.crate_name(original_def_id.krate), - self.tcx.crate_name(*dependency_of))); - }, - _ => { - err.note(&format!("the lang item is first defined in crate `{}`.", - self.tcx.crate_name(original_def_id.krate))); - } - } - } - err.emit(); - } - } - - // Matched. - self.items.items[item_index] = Some(item_def_id); - } -} - -/// Extracts the first `lang = "$name"` out of a list of attributes. -/// The attributes `#[panic_handler]` and `#[alloc_error_handler]` -/// are also extracted out when found. -pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { - attrs.iter().find_map(|attr| Some(match attr { - _ if attr.check_name(sym::lang) => (attr.value_str()?, attr.span), - _ if attr.check_name(sym::panic_handler) => (sym::panic_impl, attr.span), - _ if attr.check_name(sym::alloc_error_handler) => (sym::oom, attr.span), - _ => return None, - })) -} - -/// Traverses and collects all the lang items in all crates. -pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { - // Initialize the collector. - let mut collector = LanguageItemCollector::new(tcx); - - // Collect lang items in other crates. - for &cnum in tcx.crates().iter() { - for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { - collector.collect_item(item_index, def_id); - } - } - - // Collect lang items in this crate. - tcx.hir().krate().visit_all_item_likes(&mut collector); - - // Extract out the found lang items. - let LanguageItemCollector { mut items, .. } = collector; - - // Find all required but not-yet-defined lang items. - weak_lang_items::check_crate(tcx, &mut items); - - items -} - -// End of the macro - } -} - -language_item_table! { -// Variant name, Name, Method name, Target; - BoolImplItem, "bool", bool_impl, Target::Impl; - CharImplItem, "char", char_impl, Target::Impl; - StrImplItem, "str", str_impl, Target::Impl; - SliceImplItem, "slice", slice_impl, Target::Impl; - SliceU8ImplItem, "slice_u8", slice_u8_impl, Target::Impl; - StrAllocImplItem, "str_alloc", str_alloc_impl, Target::Impl; - SliceAllocImplItem, "slice_alloc", slice_alloc_impl, Target::Impl; - SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl; - ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl; - MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl; - I8ImplItem, "i8", i8_impl, Target::Impl; - I16ImplItem, "i16", i16_impl, Target::Impl; - I32ImplItem, "i32", i32_impl, Target::Impl; - I64ImplItem, "i64", i64_impl, Target::Impl; - I128ImplItem, "i128", i128_impl, Target::Impl; - IsizeImplItem, "isize", isize_impl, Target::Impl; - U8ImplItem, "u8", u8_impl, Target::Impl; - U16ImplItem, "u16", u16_impl, Target::Impl; - U32ImplItem, "u32", u32_impl, Target::Impl; - U64ImplItem, "u64", u64_impl, Target::Impl; - U128ImplItem, "u128", u128_impl, Target::Impl; - UsizeImplItem, "usize", usize_impl, Target::Impl; - F32ImplItem, "f32", f32_impl, Target::Impl; - F64ImplItem, "f64", f64_impl, Target::Impl; - F32RuntimeImplItem, "f32_runtime", f32_runtime_impl, Target::Impl; - F64RuntimeImplItem, "f64_runtime", f64_runtime_impl, Target::Impl; - - SizedTraitLangItem, "sized", sized_trait, Target::Trait; - UnsizeTraitLangItem, "unsize", unsize_trait, Target::Trait; - // trait injected by #[derive(PartialEq)], (i.e. "Partial EQ"). - StructuralPeqTraitLangItem, "structural_peq", structural_peq_trait, Target::Trait; - // trait injected by #[derive(Eq)], (i.e. "Total EQ"; no, I will not apologize). - StructuralTeqTraitLangItem, "structural_teq", structural_teq_trait, Target::Trait; - CopyTraitLangItem, "copy", copy_trait, Target::Trait; - CloneTraitLangItem, "clone", clone_trait, Target::Trait; - SyncTraitLangItem, "sync", sync_trait, Target::Trait; - FreezeTraitLangItem, "freeze", freeze_trait, Target::Trait; - - DropTraitLangItem, "drop", drop_trait, Target::Trait; - - CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait; - DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait; - - AddTraitLangItem, "add", add_trait, Target::Trait; - SubTraitLangItem, "sub", sub_trait, Target::Trait; - MulTraitLangItem, "mul", mul_trait, Target::Trait; - DivTraitLangItem, "div", div_trait, Target::Trait; - RemTraitLangItem, "rem", rem_trait, Target::Trait; - NegTraitLangItem, "neg", neg_trait, Target::Trait; - NotTraitLangItem, "not", not_trait, Target::Trait; - BitXorTraitLangItem, "bitxor", bitxor_trait, Target::Trait; - BitAndTraitLangItem, "bitand", bitand_trait, Target::Trait; - BitOrTraitLangItem, "bitor", bitor_trait, Target::Trait; - ShlTraitLangItem, "shl", shl_trait, Target::Trait; - ShrTraitLangItem, "shr", shr_trait, Target::Trait; - AddAssignTraitLangItem, "add_assign", add_assign_trait, Target::Trait; - SubAssignTraitLangItem, "sub_assign", sub_assign_trait, Target::Trait; - MulAssignTraitLangItem, "mul_assign", mul_assign_trait, Target::Trait; - DivAssignTraitLangItem, "div_assign", div_assign_trait, Target::Trait; - RemAssignTraitLangItem, "rem_assign", rem_assign_trait, Target::Trait; - BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait, Target::Trait; - BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait, Target::Trait; - BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait, Target::Trait; - ShlAssignTraitLangItem, "shl_assign", shl_assign_trait, Target::Trait; - ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; - IndexTraitLangItem, "index", index_trait, Target::Trait; - IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; - - UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; - VaListTypeLangItem, "va_list", va_list, Target::Struct; - - DerefTraitLangItem, "deref", deref_trait, Target::Trait; - DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait; - ReceiverTraitLangItem, "receiver", receiver_trait, Target::Trait; - - FnTraitLangItem, "fn", fn_trait, Target::Trait; - FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait; - FnOnceTraitLangItem, "fn_once", fn_once_trait, Target::Trait; - - FutureTraitLangItem, "future_trait", future_trait, Target::Trait; - GeneratorStateLangItem, "generator_state", gen_state, Target::Enum; - GeneratorTraitLangItem, "generator", gen_trait, Target::Trait; - UnpinTraitLangItem, "unpin", unpin_trait, Target::Trait; - PinTypeLangItem, "pin", pin_type, Target::Struct; - - // Don't be fooled by the naming here: this lang item denotes `PartialEq`, not `Eq`. - EqTraitLangItem, "eq", eq_trait, Target::Trait; - PartialOrdTraitLangItem, "partial_ord", partial_ord_trait, Target::Trait; - - // A number of panic-related lang items. The `panic` item corresponds to - // divide-by-zero and various panic cases with `match`. The - // `panic_bounds_check` item is for indexing arrays. - // - // The `begin_unwind` lang item has a predefined symbol name and is sort of - // a "weak lang item" in the sense that a crate is not required to have it - // defined to use it, but a final product is required to define it - // somewhere. Additionally, there are restrictions on crates that use a weak - // lang item, but do not have it defined. - PanicFnLangItem, "panic", panic_fn, Target::Fn; - PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn; - PanicInfoLangItem, "panic_info", panic_info, Target::Struct; - PanicLocationLangItem, "panic_location", panic_location, Target::Struct; - PanicImplLangItem, "panic_impl", panic_impl, Target::Fn; - // Libstd panic entry point. Necessary for const eval to be able to catch it - BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn; - - ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn, Target::Fn; - BoxFreeFnLangItem, "box_free", box_free_fn, Target::Fn; - DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn, Target::Fn; - OomLangItem, "oom", oom, Target::Fn; - AllocLayoutLangItem, "alloc_layout", alloc_layout, Target::Struct; - - StartFnLangItem, "start", start_fn, Target::Fn; - - EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn; - EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume, Target::Fn; - EhCatchTypeinfoLangItem, "eh_catch_typeinfo", eh_catch_typeinfo, Target::Static; - - OwnedBoxLangItem, "owned_box", owned_box, Target::Struct; - - PhantomDataItem, "phantom_data", phantom_data, Target::Struct; - - ManuallyDropItem, "manually_drop", manually_drop, Target::Struct; - - MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union; - - // Align offset for stride != 1; must not panic. - AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; - - TerminationTraitLangItem, "termination", termination, Target::Trait; - - Arc, "arc", arc, Target::Struct; - Rc, "rc", rc, Target::Struct; -} +pub use rustc_hir::weak_lang_items::link_name; +pub use rustc_hir::{LangItem, LanguageItems}; impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. @@ -417,4 +30,36 @@ impl<'tcx> TyCtxt<'tcx> { } }) } + + pub fn fn_trait_kind_from_lang_item(&self, id: DefId) -> Option<ty::ClosureKind> { + let items = self.lang_items(); + match Some(id) { + x if x == items.fn_trait() => Some(ty::ClosureKind::Fn), + x if x == items.fn_mut_trait() => Some(ty::ClosureKind::FnMut), + x if x == items.fn_once_trait() => Some(ty::ClosureKind::FnOnce), + _ => None, + } + } + + pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool { + self.lang_items().is_weak_lang_item(item_def_id) + } +} + +/// Returns `true` if the specified `lang_item` doesn't actually need to be +/// present for this compilation. +/// +/// Not all lang items are always required for each compilation, particularly in +/// the case of panic=abort. In these situations some lang items are injected by +/// crates and don't actually need to be defined in libstd. +pub fn whitelisted(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool { + // If we're not compiling with unwinding, we won't actually need these + // symbols. Other panic runtimes ensure that the relevant symbols are + // available to link things together, but they're never exercised. + if tcx.sess.panic_strategy() != PanicStrategy::Unwind { + return lang_item == LangItem::EhPersonalityLangItem + || lang_item == LangItem::EhUnwindResumeLangItem; + } + + false } diff --git a/src/librustc/middle/mod.rs b/src/librustc/middle/mod.rs index c2959766c57..b20f2cf3a85 100644 --- a/src/librustc/middle/mod.rs +++ b/src/librustc/middle/mod.rs @@ -33,4 +33,3 @@ pub mod recursion_limit; pub mod region; pub mod resolve_lifetime; pub mod stability; -pub mod weak_lang_items; diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs deleted file mode 100644 index 5571f8f2313..00000000000 --- a/src/librustc/middle/weak_lang_items.rs +++ /dev/null @@ -1,167 +0,0 @@ -//! Validity checking for weak lang items - -use crate::middle::lang_items; -use crate::session::config; - -use crate::hir::map::Map; -use crate::ty::TyCtxt; -use rustc_data_structures::fx::FxHashSet; -use rustc_errors::struct_span_err; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_span::symbol::{sym, Symbol}; -use rustc_span::Span; -use rustc_target::spec::PanicStrategy; -use syntax::ast; - -macro_rules! weak_lang_items { - ($($name:ident, $item:ident, $sym:ident;)*) => ( - -struct Context<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - items: &'a mut lang_items::LanguageItems, -} - -/// Checks the crate for usage of weak lang items, returning a vector of all the -/// language items required by this crate, but not defined yet. -pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, - items: &mut lang_items::LanguageItems) { - // These are never called by user code, they're generated by the compiler. - // They will never implicitly be added to the `missing` array unless we do - // so here. - if items.eh_personality().is_none() { - items.missing.push(lang_items::EhPersonalityLangItem); - } - if tcx.sess.target.target.options.custom_unwind_resume & - items.eh_unwind_resume().is_none() { - items.missing.push(lang_items::EhUnwindResumeLangItem); - } - - { - let mut cx = Context { tcx, items }; - tcx.hir().krate().visit_all_item_likes(&mut cx.as_deep_visitor()); - } - verify(tcx, items); -} - -pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> { - lang_items::extract(attrs).and_then(|(name, _)| { - $(if name == sym::$name { - Some(sym::$sym) - } else)* { - None - } - }) -} - -/// Returns `true` if the specified `lang_item` doesn't actually need to be -/// present for this compilation. -/// -/// Not all lang items are always required for each compilation, particularly in -/// the case of panic=abort. In these situations some lang items are injected by -/// crates and don't actually need to be defined in libstd. -pub fn whitelisted(tcx: TyCtxt<'_>, lang_item: lang_items::LangItem) -> bool { - // If we're not compiling with unwinding, we won't actually need these - // symbols. Other panic runtimes ensure that the relevant symbols are - // available to link things together, but they're never exercised. - if tcx.sess.panic_strategy() != PanicStrategy::Unwind { - return lang_item == lang_items::EhPersonalityLangItem || - lang_item == lang_items::EhUnwindResumeLangItem - } - - false -} - -fn verify<'tcx>(tcx: TyCtxt<'tcx>, - items: &lang_items::LanguageItems) { - // We only need to check for the presence of weak lang items if we're - // emitting something that's not an rlib. - let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| { - match *kind { - config::CrateType::Dylib | - config::CrateType::ProcMacro | - config::CrateType::Cdylib | - config::CrateType::Executable | - config::CrateType::Staticlib => true, - config::CrateType::Rlib => false, - } - }); - if !needs_check { - return - } - - let mut missing = FxHashSet::default(); - for &cnum in tcx.crates().iter() { - for &item in tcx.missing_lang_items(cnum).iter() { - missing.insert(item); - } - } - - $( - if missing.contains(&lang_items::$item) && - !whitelisted(tcx, lang_items::$item) && - items.$name().is_none() { - if lang_items::$item == lang_items::PanicImplLangItem { - tcx.sess.err(&format!("`#[panic_handler]` function required, \ - but not found")); - } else if lang_items::$item == lang_items::OomLangItem { - tcx.sess.err(&format!("`#[alloc_error_handler]` function required, \ - but not found")); - } else { - tcx.sess.err(&format!("language item required, but not found: `{}`", - stringify!($name))); - } - } - )* -} - -impl<'a, 'tcx> Context<'a, 'tcx> { - fn register(&mut self, name: Symbol, span: Span) { - $(if name == sym::$name { - if self.items.$name().is_none() { - self.items.missing.push(lang_items::$item); - } - } else)* { - struct_span_err!( - self.tcx.sess, span, E0264, - "unknown external lang item: `{}`", - name - ) - .emit(); - } - } -} - -impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { - type Map = Map<'v>; - - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> { - NestedVisitorMap::None - } - - fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) { - if let Some((lang_item, _)) = lang_items::extract(&i.attrs) { - self.register(lang_item, i.span); - } - intravisit::walk_foreign_item(self, i) - } -} - -impl<'tcx> TyCtxt<'tcx> { - pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool { - let lang_items = self.lang_items(); - let did = Some(item_def_id); - - $(lang_items.$name() == did)||* - } -} - -) } - -weak_lang_items! { - panic_impl, PanicImplLangItem, rust_begin_unwind; - eh_personality, EhPersonalityLangItem, rust_eh_personality; - eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; - oom, OomLangItem, rust_oom; -} diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index df3971a5ac3..86e7bb28e00 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -128,10 +128,9 @@ impl<'tcx> ConstEvalErr<'tcx> { } } - /// Sets the message passed in via `message`, then adds the span labels for you, before applying - /// further modifications in `emit`. It's up to you to call emit(), stash(..), etc. within the - /// `emit` method. If you don't need to do any additional processing, just use - /// struct_generic. + /// Sets the message passed in via `message` and adds span labels before handing control back + /// to `emit` to do any final processing. It's the caller's responsibility to call emit(), + /// stash(), etc. within the `emit` function to dispose of the diagnostic properly. fn struct_generic( &self, tcx: TyCtxtAt<'tcx>, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 17337ff0c92..bf82d743c2b 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1634,7 +1634,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { - let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) { + let kind = match self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) { Some(k) => k, None => { return Ok(()); @@ -1677,7 +1677,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { // We provide impl of all fn traits for fn pointers. - if self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()).is_none() { + if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() { return Ok(()); } @@ -2889,8 +2889,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let kind = self .tcx() - .lang_items() - .fn_trait_kind(obligation.predicate.def_id()) + .fn_trait_kind_from_lang_item(obligation.predicate.def_id()) .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation)); // Okay to skip binder because the substs on closure types never diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f2ad01b3d59..2adf7086417 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2716,10 +2716,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(id, LOCAL_CRATE); tcx.crate_name }; - providers.get_lang_items = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - tcx.arena.alloc(middle::lang_items::collect(tcx)) - }; providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id); providers.maybe_unused_extern_crates = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index c7f19513f66..b5e17661c5d 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -450,7 +450,7 @@ fn resolve_associated_item<'tcx>( substs: generator_data.substs, }), traits::VtableClosure(closure_data) => { - let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap(); + let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); Some(Instance::resolve_closure( tcx, closure_data.closure_def_id, diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 0da680d1f91..274482cba64 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -724,7 +724,7 @@ pub trait PrettyPrinter<'tcx>: let mut resugared = false; // Special-case `Fn(...) -> ...` and resugar it. - let fn_trait_kind = self.tcx().lang_items().fn_trait_kind(principal.def_id); + let fn_trait_kind = self.tcx().fn_trait_kind_from_lang_item(principal.def_id); if !self.tcx().sess.verbose() && fn_trait_kind.is_some() { if let ty::Tuple(ref args) = principal.substs.type_at(0).kind { let mut projections = predicates.projection_bounds(); diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 98a3e695fa0..7aaa70d6ec4 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -32,7 +32,7 @@ use syntax::expand::allocator::AllocatorKind; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc::session::config::{OptLevel, OutputFilenames, PrintRequest}; +use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest}; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; @@ -301,7 +301,7 @@ impl CodegenBackend for LlvmCodegenBackend { let rlink_data = json::encode(&codegen_results).map_err(|err| { sess.fatal(&format!("failed to encode rlink: {}", err)); })?; - let rlink_file = outputs.with_extension("rlink"); + let rlink_file = outputs.with_extension(config::RLINK_EXT); fs::write(&rlink_file, rlink_data).map_err(|err| { sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err)); })?; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 90015091384..e9431d94863 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -28,8 +28,8 @@ use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind} use rustc::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::cstore::{self, LinkagePreference}; +use rustc::middle::lang_items; use rustc::middle::lang_items::StartFnLangItem; -use rustc::middle::weak_lang_items; use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc::session::config::{self, EntryFnType, Lto}; use rustc::session::Session; @@ -847,11 +847,8 @@ impl CrateInfo { // No need to look for lang items that are whitelisted and don't // actually need to exist. - let missing = missing - .iter() - .cloned() - .filter(|&l| !weak_lang_items::whitelisted(tcx, l)) - .collect(); + let missing = + missing.iter().cloned().filter(|&l| !lang_items::whitelisted(tcx, l)).collect(); info.missing_lang_items.insert(cnum, missing); } diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index 83e6dbedee2..67fbe3058cd 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -17,3 +17,41 @@ macro_rules! static_assert_size { const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; }; } + +#[macro_export] +macro_rules! enum_from_u32 { + ($(#[$attr:meta])* pub enum $name:ident { + $($variant:ident = $e:expr,)* + }) => { + $(#[$attr])* + pub enum $name { + $($variant = $e),* + } + + impl $name { + pub fn from_u32(u: u32) -> Option<$name> { + $(if u == $name::$variant as u32 { + return Some($name::$variant) + })* + None + } + } + }; + ($(#[$attr:meta])* pub enum $name:ident { + $($variant:ident,)* + }) => { + $(#[$attr])* + pub enum $name { + $($variant,)* + } + + impl $name { + pub fn from_u32(u: u32) -> Option<$name> { + $(if u == $name::$variant as u32 { + return Some($name::$variant) + })* + None + } + } + } +} diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 7a5966269b3..5b185f9a8b6 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -26,6 +26,7 @@ rustc_mir = { path = "../librustc_mir" } rustc_parse = { path = "../librustc_parse" } rustc_plugin_impl = { path = "../librustc_plugin_impl" } rustc_save_analysis = { path = "../librustc_save_analysis" } +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_error_codes = { path = "../librustc_error_codes" } rustc_interface = { path = "../librustc_interface" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 52c63994985..2e6dde6459a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -26,25 +26,27 @@ use rustc::session::{config, DiagnosticOutput, Session}; use rustc::session::{early_error, early_warn}; use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; +use rustc_codegen_ssa::CodegenResults; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::profiling::print_time_passes_entry; use rustc_data_structures::sync::SeqCst; use rustc_errors::{registry::Registry, PResult}; use rustc_feature::{find_gated_cfg, UnstableFeatures}; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_interface::util::get_builtin_codegen_backend; +use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; -use rustc_serialize::json::ToJson; +use rustc_serialize::json::{self, ToJson}; use std::borrow::Cow; use std::cmp::max; use std::default::Default; use std::env; use std::ffi::OsString; +use std::fs; use std::io::{self, Read, Write}; use std::mem; use std::panic::{self, catch_unwind}; @@ -281,7 +283,8 @@ pub fn run_compiler( &matches, compiler.input(), ) - }); + }) + .and_then(|| RustcDefaultCalls::try_process_rlink(sess, compiler)); if should_stop == Compilation::Stop { return sess.compile_status(); @@ -588,6 +591,34 @@ fn show_content_with_pager(content: &String) { } impl RustcDefaultCalls { + fn process_rlink(sess: &Session, compiler: &interface::Compiler) -> Result<(), ErrorReported> { + if let Input::File(file) = compiler.input() { + // FIXME: #![crate_type] and #![crate_name] support not implemented yet + let attrs = vec![]; + sess.crate_types.set(collect_crate_types(sess, &attrs)); + let outputs = compiler.build_output_filenames(&sess, &attrs); + let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| { + sess.fatal(&format!("failed to read rlink file: {}", err)); + }); + let codegen_results: CodegenResults = json::decode(&rlink_data).unwrap_or_else(|err| { + sess.fatal(&format!("failed to decode rlink: {}", err)); + }); + compiler.codegen_backend().link(&sess, Box::new(codegen_results), &outputs) + } else { + sess.fatal(&format!("rlink must be a file")) + } + } + + pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation { + if sess.opts.debugging_opts.link_only { + let result = RustcDefaultCalls::process_rlink(sess, compiler); + abort_on_err(result, sess); + Compilation::Stop + } else { + Compilation::Continue + } + } + pub fn list_metadata( sess: &Session, metadata_loader: &dyn MetadataLoader, @@ -663,7 +694,7 @@ impl RustcDefaultCalls { println!("{}", id); continue; } - let crate_types = rustc_interface::util::collect_crate_types(sess, attrs); + let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = rustc_codegen_utils::link::filename_for_input( sess, style, &id, &t_outputs, diff --git a/src/librustc_hir/Cargo.toml b/src/librustc_hir/Cargo.toml index 3ae943a4ce0..cff64132532 100644 --- a/src/librustc_hir/Cargo.toml +++ b/src/librustc_hir/Cargo.toml @@ -19,4 +19,5 @@ rustc_span = { path = "../librustc_span" } rustc_errors = { path = "../librustc_errors" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } +lazy_static = "1" smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs new file mode 100644 index 00000000000..cb5ebba4633 --- /dev/null +++ b/src/librustc_hir/lang_items.rs @@ -0,0 +1,261 @@ +//! Defines language items. +//! +//! Language items are items that represent concepts intrinsic to the language +//! itself. Examples are: +//! +//! * Traits that specify "kinds"; e.g., `Sync`, `Send`. +//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. +//! * Functions called by the compiler itself. + +pub use self::LangItem::*; + +use crate::def_id::DefId; +use crate::Target; + +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_macros::HashStable_Generic; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::Span; +use syntax::ast; + +use lazy_static::lazy_static; + +// The actual lang items defined come at the end of this file in one handy table. +// So you probably just want to nip down to the end. +macro_rules! language_item_table { + ( + $( $variant:ident, $name:expr, $method:ident, $target:path; )* + ) => { + + enum_from_u32! { + /// A representation of all the valid language items in Rust. + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] + pub enum LangItem { + $($variant,)* + } + } + + impl LangItem { + /// Returns the `name` in `#[lang = "$name"]`. + /// For example, `LangItem::EqTraitLangItem`, + /// that is `#[lang = "eq"]` would result in `"eq"`. + pub fn name(self) -> &'static str { + match self { + $( $variant => $name, )* + } + } + } + + #[derive(HashStable_Generic)] + pub struct LanguageItems { + /// Mappings from lang items to their possibly found `DefId`s. + /// The index corresponds to the order in `LangItem`. + pub items: Vec<Option<DefId>>, + /// Lang items that were not found during collection. + pub missing: Vec<LangItem>, + } + + impl LanguageItems { + /// Construct an empty collection of lang items and no missing ones. + pub fn new() -> Self { + fn init_none(_: LangItem) -> Option<DefId> { None } + + Self { + items: vec![$(init_none($variant)),*], + missing: Vec::new(), + } + } + + /// Returns the mappings to the possibly found `DefId`s for each lang item. + pub fn items(&self) -> &[Option<DefId>] { + &*self.items + } + + /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`. + /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`, + /// returns an error message as a string. + pub fn require(&self, it: LangItem) -> Result<DefId, String> { + self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name())) + } + + $( + /// Returns the corresponding `DefId` for the lang item + #[doc = $name] + /// if it exists. + #[allow(dead_code)] + pub fn $method(&self) -> Option<DefId> { + self.items[$variant as usize] + } + )* + } + + lazy_static! { + /// A mapping from the name of the lang item to its order and the form it must be of. + pub static ref ITEM_REFS: FxHashMap<&'static str, (usize, Target)> = { + let mut item_refs = FxHashMap::default(); + $( item_refs.insert($name, ($variant as usize, $target)); )* + item_refs + }; + } + +// End of the macro + } +} + +impl<CTX> HashStable<CTX> for LangItem { + fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); + } +} + +/// Extracts the first `lang = "$name"` out of a list of attributes. +/// The attributes `#[panic_handler]` and `#[alloc_error_handler]` +/// are also extracted out when found. +pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { + attrs.iter().find_map(|attr| { + Some(match attr { + _ if attr.check_name(sym::lang) => (attr.value_str()?, attr.span), + _ if attr.check_name(sym::panic_handler) => (sym::panic_impl, attr.span), + _ if attr.check_name(sym::alloc_error_handler) => (sym::oom, attr.span), + _ => return None, + }) + }) +} + +language_item_table! { +// Variant name, Name, Method name, Target; + BoolImplItem, "bool", bool_impl, Target::Impl; + CharImplItem, "char", char_impl, Target::Impl; + StrImplItem, "str", str_impl, Target::Impl; + SliceImplItem, "slice", slice_impl, Target::Impl; + SliceU8ImplItem, "slice_u8", slice_u8_impl, Target::Impl; + StrAllocImplItem, "str_alloc", str_alloc_impl, Target::Impl; + SliceAllocImplItem, "slice_alloc", slice_alloc_impl, Target::Impl; + SliceU8AllocImplItem, "slice_u8_alloc", slice_u8_alloc_impl, Target::Impl; + ConstPtrImplItem, "const_ptr", const_ptr_impl, Target::Impl; + MutPtrImplItem, "mut_ptr", mut_ptr_impl, Target::Impl; + I8ImplItem, "i8", i8_impl, Target::Impl; + I16ImplItem, "i16", i16_impl, Target::Impl; + I32ImplItem, "i32", i32_impl, Target::Impl; + I64ImplItem, "i64", i64_impl, Target::Impl; + I128ImplItem, "i128", i128_impl, Target::Impl; + IsizeImplItem, "isize", isize_impl, Target::Impl; + U8ImplItem, "u8", u8_impl, Target::Impl; + U16ImplItem, "u16", u16_impl, Target::Impl; + U32ImplItem, "u32", u32_impl, Target::Impl; + U64ImplItem, "u64", u64_impl, Target::Impl; + U128ImplItem, "u128", u128_impl, Target::Impl; + UsizeImplItem, "usize", usize_impl, Target::Impl; + F32ImplItem, "f32", f32_impl, Target::Impl; + F64ImplItem, "f64", f64_impl, Target::Impl; + F32RuntimeImplItem, "f32_runtime", f32_runtime_impl, Target::Impl; + F64RuntimeImplItem, "f64_runtime", f64_runtime_impl, Target::Impl; + + SizedTraitLangItem, "sized", sized_trait, Target::Trait; + UnsizeTraitLangItem, "unsize", unsize_trait, Target::Trait; + // trait injected by #[derive(PartialEq)], (i.e. "Partial EQ"). + StructuralPeqTraitLangItem, "structural_peq", structural_peq_trait, Target::Trait; + // trait injected by #[derive(Eq)], (i.e. "Total EQ"; no, I will not apologize). + StructuralTeqTraitLangItem, "structural_teq", structural_teq_trait, Target::Trait; + CopyTraitLangItem, "copy", copy_trait, Target::Trait; + CloneTraitLangItem, "clone", clone_trait, Target::Trait; + SyncTraitLangItem, "sync", sync_trait, Target::Trait; + FreezeTraitLangItem, "freeze", freeze_trait, Target::Trait; + + DropTraitLangItem, "drop", drop_trait, Target::Trait; + + CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait; + DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait; + + AddTraitLangItem, "add", add_trait, Target::Trait; + SubTraitLangItem, "sub", sub_trait, Target::Trait; + MulTraitLangItem, "mul", mul_trait, Target::Trait; + DivTraitLangItem, "div", div_trait, Target::Trait; + RemTraitLangItem, "rem", rem_trait, Target::Trait; + NegTraitLangItem, "neg", neg_trait, Target::Trait; + NotTraitLangItem, "not", not_trait, Target::Trait; + BitXorTraitLangItem, "bitxor", bitxor_trait, Target::Trait; + BitAndTraitLangItem, "bitand", bitand_trait, Target::Trait; + BitOrTraitLangItem, "bitor", bitor_trait, Target::Trait; + ShlTraitLangItem, "shl", shl_trait, Target::Trait; + ShrTraitLangItem, "shr", shr_trait, Target::Trait; + AddAssignTraitLangItem, "add_assign", add_assign_trait, Target::Trait; + SubAssignTraitLangItem, "sub_assign", sub_assign_trait, Target::Trait; + MulAssignTraitLangItem, "mul_assign", mul_assign_trait, Target::Trait; + DivAssignTraitLangItem, "div_assign", div_assign_trait, Target::Trait; + RemAssignTraitLangItem, "rem_assign", rem_assign_trait, Target::Trait; + BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait, Target::Trait; + BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait, Target::Trait; + BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait, Target::Trait; + ShlAssignTraitLangItem, "shl_assign", shl_assign_trait, Target::Trait; + ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; + IndexTraitLangItem, "index", index_trait, Target::Trait; + IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; + + UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; + VaListTypeLangItem, "va_list", va_list, Target::Struct; + + DerefTraitLangItem, "deref", deref_trait, Target::Trait; + DerefMutTraitLangItem, "deref_mut", deref_mut_trait, Target::Trait; + ReceiverTraitLangItem, "receiver", receiver_trait, Target::Trait; + + FnTraitLangItem, "fn", fn_trait, Target::Trait; + FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait; + FnOnceTraitLangItem, "fn_once", fn_once_trait, Target::Trait; + + FutureTraitLangItem, "future_trait", future_trait, Target::Trait; + GeneratorStateLangItem, "generator_state", gen_state, Target::Enum; + GeneratorTraitLangItem, "generator", gen_trait, Target::Trait; + UnpinTraitLangItem, "unpin", unpin_trait, Target::Trait; + PinTypeLangItem, "pin", pin_type, Target::Struct; + + // Don't be fooled by the naming here: this lang item denotes `PartialEq`, not `Eq`. + EqTraitLangItem, "eq", eq_trait, Target::Trait; + PartialOrdTraitLangItem, "partial_ord", partial_ord_trait, Target::Trait; + + // A number of panic-related lang items. The `panic` item corresponds to + // divide-by-zero and various panic cases with `match`. The + // `panic_bounds_check` item is for indexing arrays. + // + // The `begin_unwind` lang item has a predefined symbol name and is sort of + // a "weak lang item" in the sense that a crate is not required to have it + // defined to use it, but a final product is required to define it + // somewhere. Additionally, there are restrictions on crates that use a weak + // lang item, but do not have it defined. + PanicFnLangItem, "panic", panic_fn, Target::Fn; + PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn, Target::Fn; + PanicInfoLangItem, "panic_info", panic_info, Target::Struct; + PanicLocationLangItem, "panic_location", panic_location, Target::Struct; + PanicImplLangItem, "panic_impl", panic_impl, Target::Fn; + // Libstd panic entry point. Necessary for const eval to be able to catch it + BeginPanicFnLangItem, "begin_panic", begin_panic_fn, Target::Fn; + + ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn, Target::Fn; + BoxFreeFnLangItem, "box_free", box_free_fn, Target::Fn; + DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn, Target::Fn; + OomLangItem, "oom", oom, Target::Fn; + AllocLayoutLangItem, "alloc_layout", alloc_layout, Target::Struct; + + StartFnLangItem, "start", start_fn, Target::Fn; + + EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn; + EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume, Target::Fn; + EhCatchTypeinfoLangItem, "eh_catch_typeinfo", eh_catch_typeinfo, Target::Static; + + OwnedBoxLangItem, "owned_box", owned_box, Target::Struct; + + PhantomDataItem, "phantom_data", phantom_data, Target::Struct; + + ManuallyDropItem, "manually_drop", manually_drop, Target::Struct; + + MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union; + + // Align offset for stride != 1; must not panic. + AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; + + TerminationTraitLangItem, "termination", termination, Target::Trait; + + Arc, "arc", arc, Target::Struct; + Rc, "rc", rc, Target::Struct; +} diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index e4edd34bd6e..d958dfc681b 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -17,9 +17,15 @@ mod hir; pub mod hir_id; pub mod intravisit; pub mod itemlikevisit; +pub mod lang_items; pub mod pat_util; pub mod print; mod stable_hash_impls; +mod target; +pub mod weak_lang_items; + pub use hir::*; pub use hir_id::*; +pub use lang_items::{LangItem, LanguageItems}; pub use stable_hash_impls::HashStableContext; +pub use target::{MethodKind, Target}; diff --git a/src/librustc/hir/check_attr.rs b/src/librustc_hir/target.rs index db5e31981c0..501976fc3cb 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc_hir/target.rs @@ -4,8 +4,8 @@ //! conflicts between multiple such attributes attached to the same //! item. -use rustc_hir as hir; -use rustc_hir::{Item, ItemKind, TraitItem, TraitItemKind}; +use crate::hir; +use crate::{Item, ItemKind, TraitItem, TraitItemKind}; use std::fmt::{self, Display}; diff --git a/src/librustc_hir/weak_lang_items.rs b/src/librustc_hir/weak_lang_items.rs new file mode 100644 index 00000000000..79182caae8c --- /dev/null +++ b/src/librustc_hir/weak_lang_items.rs @@ -0,0 +1,48 @@ +//! Validity checking for weak lang items + +use crate::def_id::DefId; +use crate::{lang_items, LangItem, LanguageItems}; + +use rustc_data_structures::fx::FxHashMap; +use rustc_span::symbol::{sym, Symbol}; +use syntax::ast; + +use lazy_static::lazy_static; + +macro_rules! weak_lang_items { + ($($name:ident, $item:ident, $sym:ident;)*) => ( + +lazy_static! { + pub static ref WEAK_ITEMS_REFS: FxHashMap<Symbol, LangItem> = { + let mut map = FxHashMap::default(); + $(map.insert(sym::$name, lang_items::$item);)* + map + }; +} + +pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> { + lang_items::extract(attrs).and_then(|(name, _)| { + $(if name == sym::$name { + Some(sym::$sym) + } else)* { + None + } + }) +} + +impl LanguageItems { + pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool { + let did = Some(item_def_id); + + $(self.$name() == did)||* + } +} + +) } + +weak_lang_items! { + panic_impl, PanicImplLangItem, rust_begin_unwind; + eh_personality, EhPersonalityLangItem, rust_eh_personality; + eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; + oom, OomLangItem, rust_oom; +} diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 2a667541ad3..e213a4d33a6 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -2,7 +2,7 @@ pub use crate::passes::BoxedResolver; use crate::util; use rustc::lint; -use rustc::session::config::{self, ErrorOutputType, Input}; +use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames}; use rustc::session::early_error; use rustc::session::{DiagnosticOutput, Session}; use rustc::ty; @@ -20,7 +20,7 @@ use rustc_span::source_map::{FileLoader, FileName, SourceMap}; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; -use syntax::ast::MetaItemKind; +use syntax::ast::{self, MetaItemKind}; use syntax::token; pub type Result<T> = result::Result<T, ErrorReported>; @@ -61,6 +61,19 @@ impl Compiler { pub fn output_file(&self) -> &Option<PathBuf> { &self.output_file } + pub fn build_output_filenames( + &self, + sess: &Session, + attrs: &[ast::Attribute], + ) -> OutputFilenames { + util::build_output_filenames( + &self.input, + &self.output_dir, + &self.output_file, + &attrs, + &sess, + ) + } } /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. diff --git a/src/librustc_macros/Cargo.toml b/src/librustc_macros/Cargo.toml index c28fcb1a395..73eb0dd56d7 100644 --- a/src/librustc_macros/Cargo.toml +++ b/src/librustc_macros/Cargo.toml @@ -12,4 +12,3 @@ synstructure = "0.12.1" syn = { version = "1", features = ["full"] } proc-macro2 = "1" quote = "1" -itertools = "0.8" diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 6dc4f7f2515..294cdb7643f 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use proc_macro::TokenStream; use proc_macro2::{Delimiter, TokenTree}; use quote::quote; @@ -469,10 +468,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { attributes.push(quote! { eval_always }); }; - let mut attribute_stream = quote! {}; - for e in attributes.into_iter().intersperse(quote! {,}) { - attribute_stream.extend(e); - } + let attribute_stream = quote! {#(#attributes),*}; // Add the query to the group group_stream.extend(quote! { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index a8c66be359c..bfd30ff5da5 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -40,7 +40,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx ), ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); - let adjustment = match tcx.lang_items().fn_trait_kind(trait_) { + let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, Some(ty::ClosureKind::FnMut) | Some(ty::ClosureKind::Fn) => Adjustment::Deref, None => bug!("fn pointer {:?} is not an fn", ty), diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml index 9ff3ed1a935..c109e9c618e 100644 --- a/src/librustc_mir_build/Cargo.toml +++ b/src/librustc_mir_build/Cargo.toml @@ -11,7 +11,6 @@ doctest = false [dependencies] arena = { path = "../libarena" } -itertools = "0.8" log = "0.4" rustc = { path = "../librustc" } rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index 855970d9342..5cabf3c0262 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -4,7 +4,6 @@ //! conflicts between multiple such attributes attached to the same //! item. -use rustc::hir::check_attr::{MethodKind, Target}; use rustc::hir::map::Map; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; @@ -15,6 +14,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::DUMMY_HIR_ID; use rustc_hir::{self, HirId, Item, ItemKind, TraitItem}; +use rustc_hir::{MethodKind, Target}; use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; diff --git a/src/librustc_passes/lang_items.rs b/src/librustc_passes/lang_items.rs new file mode 100644 index 00000000000..5f5acc7fdf8 --- /dev/null +++ b/src/librustc_passes/lang_items.rs @@ -0,0 +1,174 @@ +//! Detecting language items. +//! +//! Language items are items that represent concepts intrinsic to the language +//! itself. Examples are: +//! +//! * Traits that specify "kinds"; e.g., `Sync`, `Send`. +//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. +//! * Functions called by the compiler itself. + +use crate::weak_lang_items; + +use rustc::middle::cstore::ExternCrate; +use rustc::ty::TyCtxt; + +use rustc_errors::struct_span_err; +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_hir::lang_items::{extract, ITEM_REFS}; +use rustc_hir::{LangItem, LanguageItems, Target}; + +use rustc::ty::query::Providers; + +struct LanguageItemCollector<'tcx> { + items: LanguageItems, + tcx: TyCtxt<'tcx>, +} + +impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { + fn visit_item(&mut self, item: &hir::Item<'_>) { + if let Some((value, span)) = extract(&item.attrs) { + let actual_target = Target::from_item(item); + match ITEM_REFS.get(&*value.as_str()).cloned() { + // Known lang item with attribute on correct target. + Some((item_index, expected_target)) if actual_target == expected_target => { + let def_id = self.tcx.hir().local_def_id(item.hir_id); + self.collect_item(item_index, def_id); + } + // Known lang item with attribute on incorrect target. + Some((_, expected_target)) => { + struct_span_err!( + self.tcx.sess, + span, + E0718, + "`{}` language item must be applied to a {}", + value, + expected_target, + ) + .span_label( + span, + format!( + "attribute should be applied to a {}, not a {}", + expected_target, actual_target, + ), + ) + .emit(); + } + // Unknown lang item. + _ => { + struct_span_err!( + self.tcx.sess, + span, + E0522, + "definition of an unknown language item: `{}`", + value + ) + .span_label(span, format!("definition of unknown language item `{}`", value)) + .emit(); + } + } + } + } + + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) { + // At present, lang items are always items, not trait items. + } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) { + // At present, lang items are always items, not impl items. + } +} + +impl LanguageItemCollector<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> { + LanguageItemCollector { tcx, items: LanguageItems::new() } + } + + fn collect_item(&mut self, item_index: usize, item_def_id: DefId) { + // Check for duplicates. + if let Some(original_def_id) = self.items.items[item_index] { + if original_def_id != item_def_id { + let name = LangItem::from_u32(item_index as u32).unwrap().name(); + let mut err = match self.tcx.hir().span_if_local(item_def_id) { + Some(span) => struct_span_err!( + self.tcx.sess, + span, + E0152, + "found duplicate lang item `{}`", + name + ), + None => match self.tcx.extern_crate(item_def_id) { + Some(ExternCrate { dependency_of, .. }) => { + self.tcx.sess.struct_err(&format!( + "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.", + self.tcx.crate_name(item_def_id.krate), + self.tcx.crate_name(*dependency_of), + name + )) + } + _ => self.tcx.sess.struct_err(&format!( + "duplicate lang item in crate `{}`: `{}`.", + self.tcx.crate_name(item_def_id.krate), + name + )), + }, + }; + if let Some(span) = self.tcx.hir().span_if_local(original_def_id) { + err.span_note(span, "the lang item is first defined here"); + } else { + match self.tcx.extern_crate(original_def_id) { + Some(ExternCrate { dependency_of, .. }) => { + err.note(&format!( + "the lang item is first defined in crate `{}` (which `{}` depends on)", + self.tcx.crate_name(original_def_id.krate), + self.tcx.crate_name(*dependency_of) + )); + } + _ => { + err.note(&format!( + "the lang item is first defined in crate `{}`.", + self.tcx.crate_name(original_def_id.krate) + )); + } + } + } + err.emit(); + } + } + + // Matched. + self.items.items[item_index] = Some(item_def_id); + } +} + +/// Traverses and collects all the lang items in all crates. +fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems { + // Initialize the collector. + let mut collector = LanguageItemCollector::new(tcx); + + // Collect lang items in other crates. + for &cnum in tcx.crates().iter() { + for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() { + collector.collect_item(item_index, def_id); + } + } + + // Collect lang items in this crate. + tcx.hir().krate().visit_all_item_likes(&mut collector); + + // Extract out the found lang items. + let LanguageItemCollector { mut items, .. } = collector; + + // Find all required but not-yet-defined lang items. + weak_lang_items::check_crate(tcx, &mut items); + + items +} + +pub fn provide(providers: &mut Providers<'_>) { + providers.get_lang_items = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + tcx.arena.alloc(collect(tcx)) + }; +} diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index c5e5bc96915..afafbacb8fa 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -23,6 +23,7 @@ mod diagnostic_items; pub mod entry; pub mod hir_stats; mod intrinsicck; +mod lang_items; pub mod layout_test; mod lib_features; mod liveness; @@ -31,12 +32,14 @@ mod reachable; mod region; pub mod stability; mod upvars; +mod weak_lang_items; pub fn provide(providers: &mut Providers<'_>) { check_attr::provide(providers); check_const::provide(providers); diagnostic_items::provide(providers); entry::provide(providers); + lang_items::provide(providers); lib_features::provide(providers); loops::provide(providers); liveness::provide(providers); diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs new file mode 100644 index 00000000000..010712c28ba --- /dev/null +++ b/src/librustc_passes/weak_lang_items.rs @@ -0,0 +1,103 @@ +//! Validity checking for weak lang items + +use rustc::middle::lang_items; +use rustc::middle::lang_items::whitelisted; +use rustc::session::config; + +use rustc::hir::map::Map; +use rustc::ty::TyCtxt; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::struct_span_err; +use rustc_hir as hir; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS; +use rustc_span::symbol::Symbol; +use rustc_span::Span; + +struct Context<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + items: &'a mut lang_items::LanguageItems, +} + +/// Checks the crate for usage of weak lang items, returning a vector of all the +/// language items required by this crate, but not defined yet. +pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItems) { + // These are never called by user code, they're generated by the compiler. + // They will never implicitly be added to the `missing` array unless we do + // so here. + if items.eh_personality().is_none() { + items.missing.push(lang_items::EhPersonalityLangItem); + } + if tcx.sess.target.target.options.custom_unwind_resume & items.eh_unwind_resume().is_none() { + items.missing.push(lang_items::EhUnwindResumeLangItem); + } + + { + let mut cx = Context { tcx, items }; + tcx.hir().krate().visit_all_item_likes(&mut cx.as_deep_visitor()); + } + verify(tcx, items); +} + +fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { + // We only need to check for the presence of weak lang items if we're + // emitting something that's not an rlib. + let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| match *kind { + config::CrateType::Dylib + | config::CrateType::ProcMacro + | config::CrateType::Cdylib + | config::CrateType::Executable + | config::CrateType::Staticlib => true, + config::CrateType::Rlib => false, + }); + if !needs_check { + return; + } + + let mut missing = FxHashSet::default(); + for &cnum in tcx.crates().iter() { + for &item in tcx.missing_lang_items(cnum).iter() { + missing.insert(item); + } + } + + for (name, &item) in WEAK_ITEMS_REFS.iter() { + if missing.contains(&item) && !whitelisted(tcx, item) && items.require(item).is_err() { + if item == lang_items::PanicImplLangItem { + tcx.sess.err(&format!("`#[panic_handler]` function required, but not found")); + } else if item == lang_items::OomLangItem { + tcx.sess.err(&format!("`#[alloc_error_handler]` function required, but not found")); + } else { + tcx.sess.err(&format!("language item required, but not found: `{}`", name)); + } + } + } +} + +impl<'a, 'tcx> Context<'a, 'tcx> { + fn register(&mut self, name: Symbol, span: Span) { + if let Some(&item) = WEAK_ITEMS_REFS.get(&name) { + if self.items.require(item).is_err() { + self.items.missing.push(item); + } + } else { + struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name) + .emit(); + } + } +} + +impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { + type Map = Map<'v>; + + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> { + NestedVisitorMap::None + } + + fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) { + if let Some((lang_item, _)) = hir::lang_items::extract(&i.attrs) { + self.register(lang_item, i.span); + } + intravisit::walk_foreign_item(self, i) + } +} diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 75b5e37b2df..aeb7e891cec 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -465,6 +465,7 @@ pub struct OutputFilenames { impl_stable_hash_via_hash!(OutputFilenames); +pub const RLINK_EXT: &str = "rlink"; pub const RUST_CGU_EXT: &str = "rcgu"; impl OutputFilenames { diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 0250c40bcdc..4b3645cce72 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -966,4 +966,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"), no_link: bool = (false, parse_bool, [TRACKED], "compile without linking"), + link_only: bool = (false, parse_bool, [TRACKED], + "link the `.rlink` file generated by `-Z no-link`"), } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 707125b3fd5..396534b3cae 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .next(); let kind = object_type .principal_def_id() - .and_then(|did| self.tcx.lang_items().fn_trait_kind(did)); + .and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did)); (sig, kind) } ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), @@ -214,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // many viable options, so pick the most restrictive. let expected_kind = self .obligations_for_self_ty(expected_vid) - .filter_map(|(tr, _)| self.tcx.lang_items().fn_trait_kind(tr.def_id())) + .filter_map(|(tr, _)| self.tcx.fn_trait_kind_from_lang_item(tr.def_id())) .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); (expected_sig, expected_kind) @@ -237,7 +237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); - let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some(); + let is_fn = tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some(); let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem, cause_span); let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b661006d1dd..ea0e4719a24 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -20,8 +20,8 @@ use crate::astconv::{AstConv, Bounds, SizedByDefault}; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::constrained_generic_params as cgp; use crate::lint; +use crate::middle::lang_items; use crate::middle::resolve_lifetime as rl; -use crate::middle::weak_lang_items; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -2977,7 +2977,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { if tcx.is_weak_lang_item(id) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } - if let Some(name) = weak_lang_items::link_name(&attrs) { + if let Some(name) = lang_items::link_name(&attrs) { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 356660763a7..ef357056504 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -138,7 +138,7 @@ pub fn external_generic_args( match trait_did { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C - Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => { + Some(did) if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() => { assert!(ty_kind.is_some()); let inputs = match ty_kind { Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(), diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 5c7ee9bded9..58f4e76cd30 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1100,10 +1100,28 @@ mod trait_keyword {} // /// A value of type [`bool`] representing logical **true**. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// Logically `true` is not equal to [`false`]. +/// +/// ## Control structures that check for **true** +/// +/// Several of Rust's control structures will check for a `bool` condition evaluating to **true**. +/// +/// * The condition in an [`if`] expression must be of type `bool`. +/// Whenever that condition evaluates to **true**, the `if` expression takes +/// on the value of the first block. If however, the condition evaluates +/// to `false`, the expression takes on value of the `else` block if there is one. /// +/// * [`while`] is another control flow construct expecting a `bool`-typed condition. +/// As long as the condition evaluates to **true**, the `while` loop will continually +/// evaluate its associated block. +/// +/// * [`match`] arms can have guard clauses on them. +/// +/// [`if`]: keyword.if.html +/// [`while`]: keyword.while.html +/// [`match`]: ../reference/expressions/match-expr.html#match-guards +/// [`false`]: keyword.false.html /// [`bool`]: primitive.bool.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod true_keyword {} #[doc(keyword = "type")] @@ -1186,12 +1204,33 @@ mod await_keyword {} #[doc(keyword = "dyn")] // -/// Name the type of a [trait object]. +/// `dyn` is a prefix of a [trait object]'s type. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The `dyn` keyword is used to highlight that calls to methods on the associated `Trait` +/// are dynamically dispatched. To use the trait this way, it must be 'object safe'. +/// +/// Unlike generic parameters or `impl Trait`, the compiler does not know the concrete type that +/// is being passed. That is, the type has been [erased]. +/// As such, a `dyn Trait` reference contains _two_ pointers. +/// One pointer goes to the data (e.g., an instance of a struct). +/// Another pointer goes to a map of method call names to function pointers +/// (known as a virtual method table or vtable). +/// +/// At run-time, when a method needs to be called on the `dyn Trait`, the vtable is consulted to get +/// the function pointer and then that function pointer is called. +/// +/// ## Trade-offs +/// +/// The above indirection is the additional runtime cost of calling a function on a `dyn Trait`. +/// Methods called by dynamic dispatch generally cannot be inlined by the compiler. +/// +/// However, `dyn Trait` is likely to produce smaller code than `impl Trait` / generic parameters as +/// the method won't be duplicated for each concrete type. +/// +/// Read more about `object safety` and [trait object]s. /// /// [trait object]: ../book/ch17-02-trait-objects.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// [erased]: https://en.wikipedia.org/wiki/Type_erasure mod dyn_keyword {} #[doc(keyword = "union")] diff --git a/src/test/ui/allocator-alloc-one.rs b/src/test/ui/allocator-alloc-one.rs deleted file mode 100644 index b821a2c5939..00000000000 --- a/src/test/ui/allocator-alloc-one.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass - -#![allow(stable_features)] - -#![feature(allocator_api, nonnull)] - -use std::alloc::{AllocRef, Global, Layout, handle_alloc_error}; - -fn main() { - unsafe { - let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| { - handle_alloc_error(Layout::new::<i32>()) - }); - *ptr.as_ptr() = 4; - assert_eq!(*ptr.as_ptr(), 4); - Global.dealloc_one(ptr); - } -} diff --git a/src/test/ui/consts/const-int-unchecked.rs b/src/test/ui/consts/const-int-unchecked.rs index 8ee029b6cc3..fb09f62854d 100644 --- a/src/test/ui/consts/const-int-unchecked.rs +++ b/src/test/ui/consts/const-int-unchecked.rs @@ -1,4 +1,5 @@ #![feature(core_intrinsics)] +#![feature(const_int_unchecked_arith)] use std::intrinsics; @@ -117,4 +118,25 @@ const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) } const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; //~^ ERROR any use of this value will cause an error +// Other arithmetic functions: + +const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; +//~^ ERROR any use of this value will cause an error + +const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; +//~^ ERROR any use of this value will cause an error + +const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; +//~^ ERROR any use of this value will cause an error + +const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) }; +//~^ ERROR any use of this value will cause an error +const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) }; +//~^ ERROR any use of this value will cause an error + +const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) }; +//~^ ERROR any use of this value will cause an error +const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) }; +//~^ ERROR any use of this value will cause an error + fn main() {} diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr index d569c6a201b..bf31e0b0732 100644 --- a/src/test/ui/consts/const-int-unchecked.stderr +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -1,5 +1,5 @@ error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:14:29 + --> $DIR/const-int-unchecked.rs:15:29 | LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -9,7 +9,7 @@ LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; = note: `#[deny(const_err)]` on by default error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:16:31 + --> $DIR/const-int-unchecked.rs:17:31 | LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -17,7 +17,7 @@ LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; | Overflowing shift by 16 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:18:31 + --> $DIR/const-int-unchecked.rs:19:31 | LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -25,7 +25,7 @@ LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; | Overflowing shift by 32 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:20:31 + --> $DIR/const-int-unchecked.rs:21:31 | LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -33,7 +33,7 @@ LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; | Overflowing shift by 64 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:22:33 + --> $DIR/const-int-unchecked.rs:23:33 | LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -41,7 +41,7 @@ LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; | Overflowing shift by 128 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:27:29 + --> $DIR/const-int-unchecked.rs:28:29 | LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -49,7 +49,7 @@ LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; | Overflowing shift by 8 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:29:31 + --> $DIR/const-int-unchecked.rs:30:31 | LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -57,7 +57,7 @@ LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; | Overflowing shift by 16 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:31:31 + --> $DIR/const-int-unchecked.rs:32:31 | LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -65,7 +65,7 @@ LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; | Overflowing shift by 32 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:33:31 + --> $DIR/const-int-unchecked.rs:34:31 | LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -73,7 +73,7 @@ LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; | Overflowing shift by 64 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:35:33 + --> $DIR/const-int-unchecked.rs:36:33 | LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -81,7 +81,7 @@ LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; | Overflowing shift by 128 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:40:33 + --> $DIR/const-int-unchecked.rs:41:33 | LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -89,7 +89,7 @@ LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; | Overflowing shift by 255 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:42:35 + --> $DIR/const-int-unchecked.rs:43:35 | LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -97,7 +97,7 @@ LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; | Overflowing shift by 65535 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:44:35 + --> $DIR/const-int-unchecked.rs:45:35 | LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -105,7 +105,7 @@ LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; | Overflowing shift by 4294967295 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:46:35 + --> $DIR/const-int-unchecked.rs:47:35 | LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -113,7 +113,7 @@ LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; | Overflowing shift by 18446744073709551615 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:48:37 + --> $DIR/const-int-unchecked.rs:49:37 | LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -121,7 +121,7 @@ LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) } | Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:54:40 + --> $DIR/const-int-unchecked.rs:55:40 | LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -129,7 +129,7 @@ LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) | Overflowing shift by 250 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:56:42 + --> $DIR/const-int-unchecked.rs:57:42 | LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -137,7 +137,7 @@ LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1 | Overflowing shift by 65523 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:58:42 + --> $DIR/const-int-unchecked.rs:59:42 | LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -145,7 +145,7 @@ LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, - | Overflowing shift by 4294967271 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:60:42 + --> $DIR/const-int-unchecked.rs:61:42 | LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -153,7 +153,7 @@ LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, - | Overflowing shift by 18446744073709551586 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:62:44 + --> $DIR/const-int-unchecked.rs:63:44 | LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -161,7 +161,7 @@ LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128 | Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:69:29 + --> $DIR/const-int-unchecked.rs:70:29 | LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -169,7 +169,7 @@ LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; | Overflowing shift by 8 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:71:31 + --> $DIR/const-int-unchecked.rs:72:31 | LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -177,7 +177,7 @@ LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; | Overflowing shift by 16 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:73:31 + --> $DIR/const-int-unchecked.rs:74:31 | LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -185,7 +185,7 @@ LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; | Overflowing shift by 32 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:75:31 + --> $DIR/const-int-unchecked.rs:76:31 | LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -193,7 +193,7 @@ LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; | Overflowing shift by 64 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:77:33 + --> $DIR/const-int-unchecked.rs:78:33 | LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -201,7 +201,7 @@ LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; | Overflowing shift by 128 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:82:29 + --> $DIR/const-int-unchecked.rs:83:29 | LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -209,7 +209,7 @@ LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; | Overflowing shift by 8 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:84:31 + --> $DIR/const-int-unchecked.rs:85:31 | LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -217,7 +217,7 @@ LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; | Overflowing shift by 16 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:86:31 + --> $DIR/const-int-unchecked.rs:87:31 | LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -225,7 +225,7 @@ LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; | Overflowing shift by 32 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:88:31 + --> $DIR/const-int-unchecked.rs:89:31 | LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -233,7 +233,7 @@ LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; | Overflowing shift by 64 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:90:33 + --> $DIR/const-int-unchecked.rs:91:33 | LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -241,7 +241,7 @@ LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; | Overflowing shift by 128 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:95:33 + --> $DIR/const-int-unchecked.rs:96:33 | LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -249,7 +249,7 @@ LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; | Overflowing shift by 255 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:97:35 + --> $DIR/const-int-unchecked.rs:98:35 | LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -257,7 +257,7 @@ LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; | Overflowing shift by 65535 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:99:35 + --> $DIR/const-int-unchecked.rs:100:35 | LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -265,7 +265,7 @@ LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; | Overflowing shift by 4294967295 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:101:35 + --> $DIR/const-int-unchecked.rs:102:35 | LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -273,7 +273,7 @@ LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; | Overflowing shift by 18446744073709551615 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:103:37 + --> $DIR/const-int-unchecked.rs:104:37 | LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -281,7 +281,7 @@ LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) } | Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:109:40 + --> $DIR/const-int-unchecked.rs:110:40 | LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -289,7 +289,7 @@ LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) | Overflowing shift by 250 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:111:42 + --> $DIR/const-int-unchecked.rs:112:42 | LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -297,7 +297,7 @@ LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1 | Overflowing shift by 65523 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:113:42 + --> $DIR/const-int-unchecked.rs:114:42 | LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -305,7 +305,7 @@ LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, - | Overflowing shift by 4294967271 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:115:42 + --> $DIR/const-int-unchecked.rs:116:42 | LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -313,12 +313,68 @@ LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, - | Overflowing shift by 18446744073709551586 in `unchecked_shr` error: any use of this value will cause an error - --> $DIR/const-int-unchecked.rs:117:44 + --> $DIR/const-int-unchecked.rs:118:44 | LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | | Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` -error: aborting due to 40 previous errors +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:123:25 + | +LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | Overflow executing `unchecked_add` + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:126:25 + | +LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | Overflow executing `unchecked_sub` + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:129:25 + | +LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | Overflow executing `unchecked_mul` + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:132:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | dividing by zero + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:134:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | Overflow executing `unchecked_div` + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:137:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | calculating the remainder with a divisor of zero + +error: any use of this value will cause an error + --> $DIR/const-int-unchecked.rs:139:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) }; + | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | Overflow executing `unchecked_rem` + +error: aborting due to 47 previous errors diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 61762ae1d9b..967333c1ace 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -1,11 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -## This script publishes the new "current" toolstate in the toolstate repo (not to be -## confused with publishing the test results, which happens in -## `src/ci/docker/x86_64-gnu-tools/checktools.sh`). -## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts -## when a new commit lands on `master` (i.e., after it passed all checks on `auto`). +# This script publishes the new "current" toolstate in the toolstate repo (not to be +# confused with publishing the test results, which happens in +# `src/ci/docker/x86_64-gnu-tools/checktools.sh`). +# It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts +# when a new commit lands on `master` (i.e., after it passed all checks on `auto`). from __future__ import print_function @@ -103,6 +103,7 @@ def validate_maintainers(repo, github_token): print("The build will fail due to this.") exit(1) + def read_current_status(current_commit, path): '''Reads build status of `current_commit` from content of `history/*.tsv` ''' @@ -113,14 +114,17 @@ def read_current_status(current_commit, path): return json.loads(status) return {} + def gh_url(): return os.environ['TOOLSTATE_ISSUES_API_URL'] + def maybe_delink(message): if os.environ.get('TOOLSTATE_SKIP_MENTIONS') is not None: return message.replace("@", "") return message + def issue( tool, status, @@ -164,6 +168,7 @@ def issue( )) response.read() + def update_latest( current_commit, relevant_pr_number, @@ -194,7 +199,7 @@ def update_latest( for status in latest: tool = status['tool'] changed = False - create_issue_for_status = None # set to the status that caused the issue + create_issue_for_status = None # set to the status that caused the issue for os, s in current_status.items(): old = status[os] |
