From 303cadfbb3addd30dafdc2bcb5db994ab3bb30ab Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Tue, 27 May 2014 15:00:22 -0700 Subject: [PATCH 01/25] vim: Add :Run and :Expand commands Define a command :Run to compile and run the current file. This supports unnamed buffers (by writing to a temporary file). See the comment above the command definition for notes on usage. Define and mappings for :Run to make it easier to invoke in MacVim. Define a command :Expand to display the --pretty expanded output for the current file. This can be configured to use different pretty types. See the comment above the command definition for notes on usage. Create an autoload file and put function definitions there to speed up load time. --- src/etc/vim/autoload/rust.vim | 192 ++++++++++++++++++++++++++++++++++ src/etc/vim/ftplugin/rust.vim | 110 ++++++++++++------- 2 files changed, 265 insertions(+), 37 deletions(-) create mode 100644 src/etc/vim/autoload/rust.vim diff --git a/src/etc/vim/autoload/rust.vim b/src/etc/vim/autoload/rust.vim new file mode 100644 index 0000000000000..688c1f690eb56 --- /dev/null +++ b/src/etc/vim/autoload/rust.vim @@ -0,0 +1,192 @@ +" Author: Kevin Ballard +" Description: Helper functions for Rust commands/mappings +" Last Modified: May 27, 2014 + +" Jump {{{1 + +function! rust#Jump(mode, function) range + let cnt = v:count1 + normal! m' + if a:mode ==# 'v' + norm! gv + endif + let foldenable = &foldenable + set nofoldenable + while cnt > 0 + execute "call Jump_" . a:function . "()" + let cnt = cnt - 1 + endwhile + let &foldenable = foldenable +endfunction + +function! s:Jump_Back() + call search('{', 'b') + keepjumps normal! w99[{ +endfunction + +function! s:Jump_Forward() + normal! j0 + call search('{', 'b') + keepjumps normal! w99[{% + call search('{') +endfunction + +" Run {{{1 + +function! rust#Run(bang, args) + if a:bang + let idx = index(a:args, '--') + if idx != -1 + let rustc_args = idx == 0 ? [] : a:args[:idx-1] + let args = a:args[idx+1:] + else + let rustc_args = a:args + let args = [] + endif + else + let rustc_args = [] + let args = a:args + endif + + let b:rust_last_rustc_args = rustc_args + let b:rust_last_args = args + + call s:WithPath(function("s:Run"), rustc_args, args) +endfunction + +function! s:Run(path, rustc_args, args) + try + let exepath = tempname() + if has('win32') + let exepath .= '.exe' + endif + + let rustc_args = [a:path, '-o', exepath] + a:rustc_args + + let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + + let output = system(shellescape(rustc) . " " . join(map(rustc_args, 'shellescape(v:val)'))) + if output != '' + echohl WarningMsg + echo output + echohl None + endif + if !v:shell_error + exe '!' . shellescape(exepath) . " " . join(map(a:args, 'shellescape(v:val)')) + endif + finally + if exists("exepath") + silent! call delete(exepath) + endif + endtry +endfunction + +" Expand {{{1 + +function! rust#Expand(bang, args) + if a:bang && !empty(a:args) + let pretty = a:args[0] + let args = a:args[1:] + else + let pretty = "expanded" + let args = a:args + endif + call s:WithPath(function("s:Expand"), pretty, args) +endfunction + +function! s:Expand(path, pretty, args) + try + let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + + let args = [a:path, '--pretty', a:pretty] + a:args + let output = system(shellescape(rustc) . " " . join(map(args, "shellescape(v:val)"))) + if v:shell_error + echohl WarningMsg + echo output + echohl None + else + new + silent put =output + 1 + d + setl filetype=rust + setl buftype=nofile + setl bufhidden=hide + setl noswapfile + endif + endtry +endfunction + +function! rust#CompleteExpand(lead, line, pos) + if a:line[: a:pos-1] =~ '^Expand!\s*\S*$' + " first argument and it has a ! + let list = ["normal", "expanded", "typed", "expanded,identified", "flowgraph="] + if !empty(a:lead) + call filter(list, "v:val[:len(a:lead)-1] == a:lead") + endif + return list + endif + + return glob(escape(a:lead, "*?[") . '*', 0, 1) +endfunction + +" Utility functions {{{1 + +function! s:WithPath(func, ...) + try + let save_write = &write + set write + let path = expand('%') + let pathisempty = empty(path) + if pathisempty || !save_write + " use a temporary file named 'unnamed.rs' inside a temporary + " directory. This produces better error messages + let tmpdir = tempname() + call mkdir(tmpdir) + + let save_cwd = getcwd() + silent exe 'lcd' tmpdir + + let path = 'unnamed.rs' + + let save_mod = &mod + set nomod + + silent exe 'keepalt write! ' . path + if pathisempty + silent keepalt 0file + endif + else + update + endif + + call call(a:func, [path] + a:000) + finally + if exists("save_mod") | let &mod = save_mod | endif + if exists("save_write") | let &write = save_write | endif + if exists("save_cwd") | silent exe 'lcd' save_cwd | endif + if exists("tmpdir") | silent call s:RmDir(tmpdir) | endif + endtry +endfunction + +function! rust#AppendCmdLine(text) + call setcmdpos(getcmdpos()) + let cmd = getcmdline() . a:text + return cmd +endfunction + +function! s:RmDir(path) + " sanity check; make sure it's not empty, /, or $HOME + if empty(a:path) + echoerr 'Attempted to delete empty path' + return 0 + elseif a:path == '/' || a:path == $HOME + echoerr 'Attempted to delete protected path: ' . a:path + return 0 + endif + silent exe "!rm -rf " . shellescape(a:path) +endfunction + +" }}}1 + +" vim: set noet sw=4 ts=4: diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim index b70cda9b998c4..fee59b5868766 100644 --- a/src/etc/vim/ftplugin/rust.vim +++ b/src/etc/vim/ftplugin/rust.vim @@ -1,13 +1,19 @@ -" Vim syntax file " Language: Rust +" Description: Vim syntax file for Rust " Maintainer: Chris Morgan -" Last Change: 2014 Feb 27 +" Maintainer: Kevin Ballard +" Last Change: May 27, 2014 if exists("b:did_ftplugin") finish endif let b:did_ftplugin = 1 +let s:save_cpo = &cpo +set cpo&vim + +" Variables {{{1 + " The rust source code at present seems to typically omit a leader on /*! " comments, so we'll use that as our default, but make it easy to switch. " This does not affect indentation at all (I tested it with and without @@ -42,22 +48,74 @@ if exists("g:loaded_delimitMate") let b:delimitMate_excluded_regions = delimitMate#Get("excluded_regions") . ',rustLifetimeCandidate,rustGenericLifetimeCandidate' endif +" Motion Commands {{{1 + " Bind motion commands to support hanging indents -nnoremap [[ :call Rust_Jump('n', 'Back') -nnoremap ]] :call Rust_Jump('n', 'Forward') -xnoremap [[ :call Rust_Jump('v', 'Back') -xnoremap ]] :call Rust_Jump('v', 'Forward') -onoremap [[ :call Rust_Jump('o', 'Back') -onoremap ]] :call Rust_Jump('o', 'Forward') +nnoremap [[ :call rust#Jump('n', 'Back') +nnoremap ]] :call rust#Jump('n', 'Forward') +xnoremap [[ :call rust#Jump('v', 'Back') +xnoremap ]] :call rust#Jump('v', 'Forward') +onoremap [[ :call rust#Jump('o', 'Back') +onoremap ]] :call rust#Jump('o', 'Forward') + +" Commands {{{1 + +" :Run will compile and run the current file. If it has unsaved changes, they +" will be saved first. If it has no path, it will be written to a temporary +" file first. The generated binary is always placed in a temporary directory, +" but run from the current directory. +" +" The arguments passed to :Run will be passed to the generated binary. +" +" If ! is specified, the arguments are given to rustc as well. A -- argument +" separates rustc args from the args passed to the binary. +" +" If g:rustc_path is defined, it is used as the path to rustc. Otherwise it is +" assumed that rustc is in $PATH. +command! -nargs=* -complete=file -bang -bar -buffer Run call rust#Run(0, []) + +" :Expand will expand the current file using --pretty. +" +" Any arguments given to :Expand will be passed to rustc. This is largely so +" you can pass various --cfg configurations. +" +" If ! is specified, the first argument will be interpreted as the --pretty +" type. Otherwise it will default to 'expanded'. +" +" If the current file has unsaved changes, it will be saved first. If it's an +" unnamed buffer, it will be written to a temporary file. +" +" If g:rustc_path is defined, it is used as the path to rustc. Otherwise it is +" assumed that rustc is in $PATH. +command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -bar -buffer Expand call rust#Expand(0, []) + +" Mappings {{{1 + +" Bind ⌘R in MacVim to :Run +nnoremap :Run +" Bind ⌘⇧R in MacVim to :Run! pre-filled with the last args +nnoremap :Run! =join(b:rust_last_rustc_args)erust#AppendCmdLine(' -- ' . join(b:rust_last_args)) + +if !exists("b:rust_last_rustc_args") || !exists("b:rust_last_args") + let b:rust_last_rustc_args = [] + let b:rust_last_args = [] +endif + +" Cleanup {{{1 let b:undo_ftplugin = " \setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd< \|if exists('b:rust_original_delimitMate_excluded_regions') \|let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions \|unlet b:rust_original_delimitMate_excluded_regions - \|elseif exists('b:delimitMate_excluded_regions') - \|unlet b:delimitMate_excluded_regions + \|else + \|unlet! b:delimitMate_excluded_regions \|endif + \|unlet! b:rust_last_rustc_args b:rust_last_args + \|delcommand Run + \|delcommand Expand + \|nunmap + \|nunmap \|nunmap [[ \|nunmap ]] \|xunmap [[ @@ -66,31 +124,9 @@ let b:undo_ftplugin = " \|ounmap ]] \" -if exists('*Rust_Jump') | finish | endif +" }}}1 -function! Rust_Jump(mode, function) range - let cnt = v:count1 - normal! m' - if a:mode ==# 'v' - norm! gv - endif - let foldenable = &foldenable - set nofoldenable - while cnt > 0 - execute "call Rust_Jump_" . a:function . "()" - let cnt = cnt - 1 - endwhile - let &foldenable = foldenable -endfunction - -function! Rust_Jump_Back() - call search('{', 'b') - keepjumps normal! w99[{ -endfunction - -function! Rust_Jump_Forward() - normal! j0 - call search('{', 'b') - keepjumps normal! w99[{% - call search('{') -endfunction +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: set noet sw=4 ts=4: From bd3bebcf60793477da390471d6d00a5523d716b4 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Thu, 29 May 2014 23:43:52 -0700 Subject: [PATCH 02/25] Rename :Run and :Expand to :RustRun and :RustExpand --- src/etc/vim/autoload/rust.vim | 2 +- src/etc/vim/ftplugin/rust.vim | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/etc/vim/autoload/rust.vim b/src/etc/vim/autoload/rust.vim index 688c1f690eb56..c5bf0c10751b2 100644 --- a/src/etc/vim/autoload/rust.vim +++ b/src/etc/vim/autoload/rust.vim @@ -118,7 +118,7 @@ function! s:Expand(path, pretty, args) endfunction function! rust#CompleteExpand(lead, line, pos) - if a:line[: a:pos-1] =~ '^Expand!\s*\S*$' + if a:line[: a:pos-1] =~ '^RustExpand!\s*\S*$' " first argument and it has a ! let list = ["normal", "expanded", "typed", "expanded,identified", "flowgraph="] if !empty(a:lead) diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim index fee59b5868766..6e373b2ddc471 100644 --- a/src/etc/vim/ftplugin/rust.vim +++ b/src/etc/vim/ftplugin/rust.vim @@ -60,24 +60,24 @@ onoremap ]] :call rust#Jump('o', 'Forward') " Commands {{{1 -" :Run will compile and run the current file. If it has unsaved changes, they -" will be saved first. If it has no path, it will be written to a temporary -" file first. The generated binary is always placed in a temporary directory, -" but run from the current directory. +" :RustRun will compile and run the current file. If it has unsaved changes, +" they will be saved first. If it has no path, it will be written to a +" temporary file first. The generated binary is always placed in a temporary +" directory, but run from the current directory. " -" The arguments passed to :Run will be passed to the generated binary. +" The arguments passed to :RustRun will be passed to the generated binary. " " If ! is specified, the arguments are given to rustc as well. A -- argument " separates rustc args from the args passed to the binary. " " If g:rustc_path is defined, it is used as the path to rustc. Otherwise it is " assumed that rustc is in $PATH. -command! -nargs=* -complete=file -bang -bar -buffer Run call rust#Run(0, []) +command! -nargs=* -complete=file -bang -bar -buffer RustRun call rust#Run(0, []) -" :Expand will expand the current file using --pretty. +" :RustExpand will expand the current file using --pretty. " -" Any arguments given to :Expand will be passed to rustc. This is largely so -" you can pass various --cfg configurations. +" Any arguments given to :RustExpand will be passed to rustc. This is largely +" so you can pass various --cfg configurations. " " If ! is specified, the first argument will be interpreted as the --pretty " type. Otherwise it will default to 'expanded'. @@ -87,14 +87,14 @@ command! -nargs=* -complete=file -bang -bar -buffer Run call rust#Run(0, [ " " If g:rustc_path is defined, it is used as the path to rustc. Otherwise it is " assumed that rustc is in $PATH. -command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -bar -buffer Expand call rust#Expand(0, []) +command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -bar -buffer RustExpand call rust#Expand(0, []) " Mappings {{{1 -" Bind ⌘R in MacVim to :Run -nnoremap :Run -" Bind ⌘⇧R in MacVim to :Run! pre-filled with the last args -nnoremap :Run! =join(b:rust_last_rustc_args)erust#AppendCmdLine(' -- ' . join(b:rust_last_args)) +" Bind ⌘R in MacVim to :RustRun +nnoremap :RustRun +" Bind ⌘⇧R in MacVim to :RustRun! pre-filled with the last args +nnoremap :RustRun! =join(b:rust_last_rustc_args)erust#AppendCmdLine(' -- ' . join(b:rust_last_args)) if !exists("b:rust_last_rustc_args") || !exists("b:rust_last_args") let b:rust_last_rustc_args = [] @@ -112,8 +112,8 @@ let b:undo_ftplugin = " \|unlet! b:delimitMate_excluded_regions \|endif \|unlet! b:rust_last_rustc_args b:rust_last_args - \|delcommand Run - \|delcommand Expand + \|delcommand RustRun + \|delcommand RustExpand \|nunmap \|nunmap \|nunmap [[ From 918eda59bee9a627919d11b7bc9f909d7a9676ff Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Fri, 30 May 2014 00:06:52 -0700 Subject: [PATCH 03/25] Write documentation for the Rust vim plugin --- src/etc/vim/doc/rust.txt | 129 ++++++++++++++++++++++++++++++++++ src/etc/vim/ftplugin/rust.vim | 27 +------ 2 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 src/etc/vim/doc/rust.txt diff --git a/src/etc/vim/doc/rust.txt b/src/etc/vim/doc/rust.txt new file mode 100644 index 0000000000000..e0a647225a9e5 --- /dev/null +++ b/src/etc/vim/doc/rust.txt @@ -0,0 +1,129 @@ +*rust.txt* Filetype plugin for Rust + +============================================================================== +CONTENTS *rust* + +1. Introduction |rust-intro| +2. Settings |rust-settings| +3. Commands |rust-commands| +4. Mappings |rust-mappings| + +============================================================================== +INTRODUCTION *rust-intro* + +This plugin provides syntax and supporting functionality for the Rust +filetype. + +============================================================================== +SETTINGS *rust-settings* + +This plugin has a few variables you can define in your vimrc that change the +behavior of the plugin. + + *g:rustc_path* +g:rustc_path~ + Set this option to the path to rustc for use in the |:RustRun| and + |:RustExpand| commands. If unset, "rustc" will be located in $PATH: > + let g:rustc_path = $HOME."/bin/rustc" +< + + *g:rustc_makeprg_no_percent* +g:rustc_makeprg_no_percent~ + Set this option to 1 to have 'makeprg' default to "rustc" instead of + "rustc %": > + let g:rustc_makeprg_no_percent = 1 +< + + *g:rust_conceal* +g:rust_conceal~ + Set this option to turn on the basic |conceal| support: > + let g:rust_conceal = 1 +< + + *g:rust_conceal_mod_path* +g:rust_conceal_mod_path~ + Set this option to turn on |conceal| for the path connecting token + "::": > + let g:rust_conceal_mod_path = 1 +< + + *g:rust_conceal_pub* +g:rust_conceal_pub~ + Set this option to turn on |conceal| for the "pub" token: > + let g:rust_conceal_pub = 1 +< + + *g:rust_bang_comment_leader* +g:rust_bang_comment_leader~ + Set this option to 1 to preserve the leader on multi-line doc comments + using the /*! syntax: > + let g:rust_bang_comment_leader = 1 +< + + *g:ftplugin_rust_source_path* +g:ftplugin_rust_source_path~ + Set this option to a path that should be prepended to 'path' for Rust + source files: > + let g:ftplugin_rust_source_path = $HOME.'/dev/rust' +< + +============================================================================== +COMMANDS *rust-commands* + +:RustRun [args] *:RustRun* +:RustRun! [rustc-args] [--] [args] + Compiles and runs the current file. If it has unsaved changes, + it will be saved first using |:update|. If the current file is + an unnamed buffer, it will be written to a temporary file + first. The compiled binary is always placed in a temporary + directory, but is run from the current directory. + + The arguments given to |:RustRun| will be passed to the + compiled binary. + + If ! is specified, the arguments are passed to rustc instead. + A "--" argument will separate the rustc arguments from the + arguments passed to the binary. + + If |g:rustc_path| is defined, it is used as the path to rustc. + Otherwise it is assumed rustc can be found in $PATH. + +:RustExpand [args] *:RustExpand* +:RustExpand! [TYPE] [args] + Expands the current file using --pretty and displays the + results in a new split. If the current file has unsaved + changes, it will be saved first using |:update|. If the + current file is an unnamed buffer, it will be written to a + temporary file first. + + The arguments given to |:RustExpand| will be passed to rustc. + This is largely intended for specifying various --cfg + configurations. + + If ! is specified, the first argument is the expansion type to + pass to rustc --pretty. Otherwise it will default to + "expanded". + + If |g:rustc_path| is defined, it is used as the path to rustc. + Otherwise it is assumed rustc can be found in $PATH. + + +============================================================================== +MAPPINGS *rust-mappings* + +This plugin defines mappings for |[[| and |]]| to support hanging indents. + +It also has a few other mappings: + + *rust_* + Executes |:RustRun| with no arguments. + Note: This binding is only available in MacVim. + + *rust_* + Populates the command line with |:RustRun|! using the + arguments given to the last invocation, but does not + execute it. + Note: This binding is only available in MacVim. + +============================================================================== + vim:tw=78:sw=4:noet:ts=8:ft=help:norl: diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim index 6e373b2ddc471..ed5d721de0859 100644 --- a/src/etc/vim/ftplugin/rust.vim +++ b/src/etc/vim/ftplugin/rust.vim @@ -60,33 +60,10 @@ onoremap ]] :call rust#Jump('o', 'Forward') " Commands {{{1 -" :RustRun will compile and run the current file. If it has unsaved changes, -" they will be saved first. If it has no path, it will be written to a -" temporary file first. The generated binary is always placed in a temporary -" directory, but run from the current directory. -" -" The arguments passed to :RustRun will be passed to the generated binary. -" -" If ! is specified, the arguments are given to rustc as well. A -- argument -" separates rustc args from the args passed to the binary. -" -" If g:rustc_path is defined, it is used as the path to rustc. Otherwise it is -" assumed that rustc is in $PATH. +" See |:RustRun| for docs command! -nargs=* -complete=file -bang -bar -buffer RustRun call rust#Run(0, []) -" :RustExpand will expand the current file using --pretty. -" -" Any arguments given to :RustExpand will be passed to rustc. This is largely -" so you can pass various --cfg configurations. -" -" If ! is specified, the first argument will be interpreted as the --pretty -" type. Otherwise it will default to 'expanded'. -" -" If the current file has unsaved changes, it will be saved first. If it's an -" unnamed buffer, it will be written to a temporary file. -" -" If g:rustc_path is defined, it is used as the path to rustc. Otherwise it is -" assumed that rustc is in $PATH. +" See |:RustExpand| for docs command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -bar -buffer RustExpand call rust#Expand(0, []) " Mappings {{{1 From 1273f94cbb19608e6a4e02c54d8543f6fe648a47 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Fri, 30 May 2014 16:35:10 -0700 Subject: [PATCH 04/25] Add commands :RustEmitIr and :RustEmitAsm --- src/etc/vim/autoload/rust.vim | 33 +++++++++++++++++++++++++++++++++ src/etc/vim/doc/rust.txt | 21 +++++++++++++++++++++ src/etc/vim/ftplugin/rust.vim | 8 ++++++++ 3 files changed, 62 insertions(+) diff --git a/src/etc/vim/autoload/rust.vim b/src/etc/vim/autoload/rust.vim index c5bf0c10751b2..c6b9b314da5c4 100644 --- a/src/etc/vim/autoload/rust.vim +++ b/src/etc/vim/autoload/rust.vim @@ -130,6 +130,39 @@ function! rust#CompleteExpand(lead, line, pos) return glob(escape(a:lead, "*?[") . '*', 0, 1) endfunction +" Emit {{{1 + +function! rust#Emit(type, args) + call s:WithPath(function("s:Emit"), a:type, a:args) +endfunction + +function! s:Emit(path, type, args) + try + let rustc = exists("g:rustc_path") ? g:rustc_path : "rustc" + + let args = [a:path, '--emit', a:type, '-o', '-'] + a:args + let output = system(shellescape(rustc) . " " . join(map(args, "shellescape(v:val)"))) + if v:shell_error + echohl WarningMsg + echo output + echohl None + else + new + silent put =output + 1 + d + if a:type == "ir" + setl filetype=llvm + elseif a:type == "asm" + setl filetype=asm + endif + setl buftype=nofile + setl bufhidden=hide + setl noswapfile + endif + endtry +endfunction + " Utility functions {{{1 function! s:WithPath(func, ...) diff --git a/src/etc/vim/doc/rust.txt b/src/etc/vim/doc/rust.txt index e0a647225a9e5..96ed69db63529 100644 --- a/src/etc/vim/doc/rust.txt +++ b/src/etc/vim/doc/rust.txt @@ -107,6 +107,27 @@ COMMANDS *rust-commands* If |g:rustc_path| is defined, it is used as the path to rustc. Otherwise it is assumed rustc can be found in $PATH. +:RustEmitIr [args] *:RustEmitIr* + Compiles the current file to LLVM IR and displays the results + in a new split. If the current file has unsaved changes, it + will be saved first using |:update|. If the current file is an + unnamed buffer, it will be written to a temporary file first. + + The arguments given to |:RustEmitIr| will be passed to rustc. + + If |g:rustc_path| is defined, it is used as the path to rustc. + Otherwise it is assumed rustc can be found in $PATH. + +:RustEmitAsm [args] *:RustEmitAsm* + Compiles the current file to assembly and displays the results + in a new split. If the current file has unsaved changes, it + will be saved first using |:update|. If the current file is an + unnamed buffer, it will be written to a temporary file first. + + The arguments given to |:RustEmitAsm| will be passed to rustc. + + If |g:rustc_path| is defined, it is used as the path to rustc. + Otherwise it is assumed rustc can be found in $PATH. ============================================================================== MAPPINGS *rust-mappings* diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim index ed5d721de0859..65f9f4105ad8f 100644 --- a/src/etc/vim/ftplugin/rust.vim +++ b/src/etc/vim/ftplugin/rust.vim @@ -66,6 +66,12 @@ command! -nargs=* -complete=file -bang -bar -buffer RustRun call rust#Run( " See |:RustExpand| for docs command! -nargs=* -complete=customlist,rust#CompleteExpand -bang -bar -buffer RustExpand call rust#Expand(0, []) +" See |:RustEmitIr| for docs +command! -nargs=* -bar -buffer RustEmitIr call rust#Emit("ir", []) + +" See |:RustEmitAsm| for docs +command! -nargs=* -bar -buffer RustEmitAsm call rust#Emit("asm", []) + " Mappings {{{1 " Bind ⌘R in MacVim to :RustRun @@ -91,6 +97,8 @@ let b:undo_ftplugin = " \|unlet! b:rust_last_rustc_args b:rust_last_args \|delcommand RustRun \|delcommand RustExpand + \|delcommand RustEmitIr + \|delcommand RustEmitAsm \|nunmap \|nunmap \|nunmap [[ From 87c529c43a41e0c04a468cd2b301013df629b040 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Jun 2014 22:53:55 -0700 Subject: [PATCH 05/25] Add a ByteOrder trait for abstracting over endian conversions The `Bitwise::swap_bytes` method was also moved into the `ByteOrder` trait. This was because it works on the byte level rather than the bit level. --- src/libcore/mem.rs | 336 +++++++++++++++++++++++---------- src/libcore/num/int_macros.rs | 11 -- src/libcore/num/mod.rs | 72 +++---- src/libcore/num/uint_macros.rs | 11 -- 4 files changed, 263 insertions(+), 167 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 237efcd0096d0..6b08a32944c96 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -13,6 +13,7 @@ //! This module contains functions for querying the size and alignment of //! types, initializing and manipulating memory. +use clone::Clone; use ptr; use intrinsics; use intrinsics::{bswap16, bswap32, bswap64}; @@ -169,151 +170,238 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { ptr::write(dst, src) } -/// Convert an u16 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: u16) -> u16 { x } +/// A type that can have its bytes re-ordered. +pub trait ByteOrder: Clone { + /// Reverses the byte order of the value. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + fn swap_bytes(&self) -> Self; + + /// Convert a value from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(ByteOrder::from_big_endian(n), n) + /// } else { + /// assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_big_endian(x: Self) -> Self { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } -/// Convert an u16 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_le16(x: u16) -> u16 { unsafe { bswap16(x) } } + /// Convert a value from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(ByteOrder::from_little_endian(n), n) + /// } else { + /// assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_little_endian(x: Self) -> Self { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } -/// Convert an u32 to little endian from the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_le32(x: u32) -> u32 { x } + /// Convert the value to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_big_endian(), n) + /// } else { + /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_big_endian(&self) -> Self { + if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() } + } -/// Convert an u32 to little endian from the target's endianness. + /// Convert the value to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// use std::mem::ByteOrder; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_little_endian(), n) + /// } else { + /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_little_endian(&self) -> Self { + if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() } + } +} + +impl ByteOrder for u8 { + #[inline] + fn swap_bytes(&self) -> u8 { + *self // swapping a single byte does nothing + } +} + +impl ByteOrder for u16 { + #[inline] + fn swap_bytes(&self) -> u16 { + unsafe { intrinsics::bswap16(*self) } + } +} + +impl ByteOrder for u32 { + #[inline] + fn swap_bytes(&self) -> u32 { + unsafe { intrinsics::bswap32(*self) } + } +} + +impl ByteOrder for u64 { + #[inline] + fn swap_bytes(&self) -> u64 { + unsafe { intrinsics::bswap64(*self) } + } +} + +#[cfg(target_word_size = "32")] +impl ByteOrder for uint { + #[inline] + fn swap_bytes(&self) -> uint { + (*self as u32).swap_bytes() as uint + } +} + +#[cfg(target_word_size = "64")] +impl ByteOrder for uint { + #[inline] + fn swap_bytes(&self) -> uint { + (*self as u64).swap_bytes() as uint + } +} + +/// Convert an u16 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_le32(x: u32) -> u32 { unsafe { bswap32(x) } } +#[inline] +#[stable] +pub fn to_le16(x: u16) -> u16 { x.to_little_endian() } -/// Convert an u64 to little endian from the target's endianness. +/// Convert an u32 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_le64(x: u64) -> u64 { x } +#[inline] +#[stable] +pub fn to_le32(x: u32) -> u32 { x.to_little_endian() } /// Convert an u64 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_le64(x: u64) -> u64 { unsafe { bswap64(x) } } - - -/// Convert an u16 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_be16(x: u16) -> u16 { unsafe { bswap16(x) } } +#[inline] +#[stable] +pub fn to_le64(x: u64) -> u64 { x.to_little_endian() } /// Convert an u16 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_be16(x: u16) -> u16 { x } - -/// Convert an u32 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_be32(x: u32) -> u32 { unsafe { bswap32(x) } } +#[inline] +#[stable] +pub fn to_be16(x: u16) -> u16 { x.to_big_endian() } /// Convert an u32 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_be32(x: u32) -> u32 { x } - -/// Convert an u64 to big endian from the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn to_be64(x: u64) -> u64 { unsafe { bswap64(x) } } +#[inline] +#[stable] +pub fn to_be32(x: u32) -> u32 { x.to_big_endian() } /// Convert an u64 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn to_be64(x: u64) -> u64 { x } - - -/// Convert an u16 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { x } +#[inline] +#[stable] +pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// Convert an u16 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { unsafe { bswap16(x) } } - -/// Convert an u32 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { x } +#[inline] +#[stable] +pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { unsafe { bswap32(x) } } - -/// Convert an u64 from little endian to the target's endianness. -/// -/// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { x } +#[inline] +#[stable] +pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { unsafe { bswap64(x) } } - - -/// Convert an u16 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { unsafe { bswap16(x) } } +#[inline] +#[stable] +pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { x } - -/// Convert an u32 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { unsafe { bswap32(x) } } +#[inline] +#[stable] +pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { x } - -/// Convert an u64 from big endian to the target's endianness. -/// -/// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "little")] #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { unsafe { bswap64(x) } } +#[inline] +#[stable] +pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. -#[cfg(target_endian = "big")] #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { x } +#[inline] +#[stable] +pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } /** * Swap the values at two mutable locations of the same type, without @@ -558,6 +646,60 @@ mod tests { assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); } } + + macro_rules! test_byte_order { + ($T:ident) => { + mod $T { + use mem::ByteOrder; + + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A); + assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B); + assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C); + assert_eq!(ByteOrder::from_little_endian(_0), _0); + assert_eq!(ByteOrder::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A); + assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B); + assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C); + assert_eq!(ByteOrder::from_big_endian(_0), _0); + assert_eq!(ByteOrder::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); + } + } + } + } + + test_byte_order!(u8) + test_byte_order!(u16) + test_byte_order!(u32) + test_byte_order!(u64) + test_byte_order!(uint) } // FIXME #13642 (these benchmarks should be in another place) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 20bb12db694c0..8a1bd66aa1acc 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -113,17 +113,6 @@ mod tests { assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); } - #[test] - fn test_swap_bytes() { - let n: $T = 0b0101100; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b0100001; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b1111001; assert_eq!(n.swap_bytes().swap_bytes(), n); - - // Swapping these should make no difference - let n: $T = 0; assert_eq!(n.swap_bytes(), n); - let n: $T = -1; assert_eq!(n.swap_bytes(), n); - } - #[test] fn test_rotate() { let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index eaa632be6d04c..696abc05ed275 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -437,19 +437,6 @@ pub trait Bitwise: Bounded /// ``` fn trailing_zeros(&self) -> Self; - /// Reverses the byte order of a binary number. - /// - /// # Example - /// - /// ```rust - /// use std::num::Bitwise; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xEFCDAB8967452301u64; - /// assert_eq!(n.swap_bytes(), m); - /// ``` - fn swap_bytes(&self) -> Self; - /// Shifts the bits to the left by a specified amount amount, `r`, wrapping /// the truncated bits to the end of the resulting value. /// @@ -479,25 +466,17 @@ pub trait Bitwise: Bounded fn rotate_right(&self, r: uint) -> Self; } -/// Swapping a single byte does nothing. This is unsafe to be consistent with -/// the other `bswap` intrinsics. -#[inline] -unsafe fn bswap8(x: u8) -> u8 { x } - -macro_rules! bitwise_impl( - ($t:ty, $bits:expr, $co:ident, $lz:ident, $tz:ident, $bs:path) => { +macro_rules! bitwise_impl { + ($t:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { impl Bitwise for $t { #[inline] - fn count_ones(&self) -> $t { unsafe { intrinsics::$co(*self) } } - - #[inline] - fn leading_zeros(&self) -> $t { unsafe { intrinsics::$lz(*self) } } + fn count_ones(&self) -> $t { unsafe { $co(*self) } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { intrinsics::$tz(*self) } } + fn leading_zeros(&self) -> $t { unsafe { $lz(*self) } } #[inline] - fn swap_bytes(&self) -> $t { unsafe { $bs(*self) } } + fn trailing_zeros(&self) -> $t { unsafe { $tz(*self) } } #[inline] fn rotate_left(&self, r: uint) -> $t { @@ -514,22 +493,19 @@ macro_rules! bitwise_impl( } } } -) +} -macro_rules! bitwise_cast_impl( - ($t:ty, $t_cast:ty, $bits:expr, $co:ident, $lz:ident, $tz:ident, $bs:path) => { +macro_rules! bitwise_cast_impl { + ($t:ty, $t_cast:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { impl Bitwise for $t { #[inline] - fn count_ones(&self) -> $t { unsafe { intrinsics::$co(*self as $t_cast) as $t } } + fn count_ones(&self) -> $t { unsafe { $co(*self as $t_cast) as $t } } #[inline] - fn leading_zeros(&self) -> $t { unsafe { intrinsics::$lz(*self as $t_cast) as $t } } + fn leading_zeros(&self) -> $t { unsafe { $lz(*self as $t_cast) as $t } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { intrinsics::$tz(*self as $t_cast) as $t } } - - #[inline] - fn swap_bytes(&self) -> $t { unsafe { $bs(*self as $t_cast) as $t } } + fn trailing_zeros(&self) -> $t { unsafe { $tz(*self as $t_cast) as $t } } #[inline] fn rotate_left(&self, r: uint) -> $t { @@ -544,27 +520,27 @@ macro_rules! bitwise_cast_impl( } } } -) +} #[cfg(target_word_size = "32")] -bitwise_cast_impl!(uint, u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) +bitwise_cast_impl!(uint, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) #[cfg(target_word_size = "64")] -bitwise_cast_impl!(uint, u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_cast_impl!(uint, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) -bitwise_impl!(u8, 8, ctpop8, ctlz8, cttz8, bswap8) -bitwise_impl!(u16, 16, ctpop16, ctlz16, cttz16, intrinsics::bswap16) -bitwise_impl!(u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) -bitwise_impl!(u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_impl!(u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) +bitwise_impl!(u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) +bitwise_impl!(u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) +bitwise_impl!(u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) #[cfg(target_word_size = "32")] -bitwise_cast_impl!(int, u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) +bitwise_cast_impl!(int, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) #[cfg(target_word_size = "64")] -bitwise_cast_impl!(int, u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_cast_impl!(int, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) -bitwise_cast_impl!(i8, u8, 8, ctpop8, ctlz8, cttz8, bswap8) -bitwise_cast_impl!(i16, u16, 16, ctpop16, ctlz16, cttz16, intrinsics::bswap16) -bitwise_cast_impl!(i32, u32, 32, ctpop32, ctlz32, cttz32, intrinsics::bswap32) -bitwise_cast_impl!(i64, u64, 64, ctpop64, ctlz64, cttz64, intrinsics::bswap64) +bitwise_cast_impl!(i8, u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) +bitwise_cast_impl!(i16, u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) +bitwise_cast_impl!(i32, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) +bitwise_cast_impl!(i64, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) /// Specifies the available operations common to all of Rust's core numeric primitives. /// These may not always make sense from a purely mathematical point of view, but diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 8e4ba10154244..8548b14105394 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -64,17 +64,6 @@ mod tests { assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); } - #[test] - fn test_swap_bytes() { - let n: $T = 0b0101100; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b0100001; assert_eq!(n.swap_bytes().swap_bytes(), n); - let n: $T = 0b1111001; assert_eq!(n.swap_bytes().swap_bytes(), n); - - // Swapping these should make no difference - let n: $T = 0; assert_eq!(n.swap_bytes(), n); - let n: $T = MAX; assert_eq!(n.swap_bytes(), n); - } - #[test] fn test_rotate() { let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); From b84d17d4d77b04e1b7784d95e0c3cb2dca16f344 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 14 Jun 2014 23:11:33 -0700 Subject: [PATCH 06/25] Use ByteOrder methods instead of free-standing functions --- src/libcollections/hash/mod.rs | 61 +++++++++++++--------------------- src/libnative/io/net.rs | 9 ++--- src/librustuv/net.rs | 10 +++--- src/libserialize/ebml.rs | 4 +-- src/libuuid/lib.rs | 16 ++++----- 5 files changed, 44 insertions(+), 56 deletions(-) diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index bd7bab456ba01..80417e2a57986 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -98,46 +98,31 @@ pub trait Writer { ////////////////////////////////////////////////////////////////////////////// -fn id(t: T) -> T { t } - -macro_rules! impl_hash( - ( $($ty:ident, $uty:ident, $f:path;)* ) => ( - $( - impl Hash for $ty { - #[inline] - fn hash(&self, state: &mut S) { - let a: [u8, ..::core::$ty::BYTES] = unsafe { - mem::transmute($f(*self as $uty) as $ty) - }; - state.write(a.as_slice()) - } +macro_rules! impl_hash { + ($ty:ident, $uty:ident) => { + impl Hash for $ty { + #[inline] + fn hash(&self, state: &mut S) { + use core::mem::ByteOrder; + let a: [u8, ..::core::$ty::BYTES] = unsafe { + mem::transmute((*self as $uty).to_little_endian() as $ty) + }; + state.write(a.as_slice()) } - )* - ) -) - -impl_hash!( - u8, u8, id; - u16, u16, mem::to_le16; - u32, u32, mem::to_le32; - u64, u64, mem::to_le64; - i8, u8, id; - i16, u16, mem::to_le16; - i32, u32, mem::to_le32; - i64, u64, mem::to_le64; -) - -#[cfg(target_word_size = "32")] -impl_hash!( - uint, u32, mem::to_le32; - int, u32, mem::to_le32; -) + } + } +} -#[cfg(target_word_size = "64")] -impl_hash!( - uint, u64, mem::to_le64; - int, u64, mem::to_le64; -) +impl_hash!(u8, u8) +impl_hash!(u16, u16) +impl_hash!(u32, u32) +impl_hash!(u64, u64) +impl_hash!(uint, uint) +impl_hash!(i8, u8) +impl_hash!(i16, u16) +impl_hash!(i32, u32) +impl_hash!(i64, u64) +impl_hash!(int, uint) impl Hash for bool { #[inline] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 8cf0c3bf0620f..f0cd2d966cb36 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -11,6 +11,7 @@ use alloc::arc::Arc; use libc; use std::mem; +use std::mem::ByteOrder; use std::rt::mutex; use std::rt::rtio; use std::rt::rtio::{IoResult, IoError}; @@ -27,10 +28,10 @@ use super::util; #[cfg(unix)] pub type sock_t = super::file::fd_t; pub fn htons(u: u16) -> u16 { - mem::to_be16(u) + u.to_big_endian() } pub fn ntohs(u: u16) -> u16 { - mem::from_be16(u) + ByteOrder::from_big_endian(u) } enum InAddr { @@ -46,7 +47,7 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr { (c as u32 << 8) | (d as u32 << 0); InAddr(libc::in_addr { - s_addr: mem::from_be32(ip) + s_addr: ByteOrder::from_big_endian(ip) }) } rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => { @@ -180,7 +181,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = mem::to_be32(storage.sin_addr.s_addr as u32); + let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index c8fb0f496dcb7..83beeceb8de3e 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -11,6 +11,7 @@ use libc::{size_t, ssize_t, c_int, c_void, c_uint}; use libc; use std::mem; +use std::mem::ByteOrder; use std::ptr; use std::rt::rtio; use std::rt::rtio::IoError; @@ -30,8 +31,8 @@ use uvll; /// Generic functions related to dealing with sockaddr things //////////////////////////////////////////////////////////////////////////////// -pub fn htons(u: u16) -> u16 { mem::to_be16(u) } -pub fn ntohs(u: u16) -> u16 { mem::from_be16(u) } +pub fn htons(u: u16) -> u16 { u.to_big_endian() } +pub fn ntohs(u: u16) -> u16 { ByteOrder::from_big_endian(u) } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: uint) -> rtio::SocketAddr { @@ -41,7 +42,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = mem::to_be32(storage.sin_addr.s_addr as u32); + let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; @@ -89,7 +90,8 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) { (*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_port = htons(addr.port); (*storage).sin_addr = libc::in_addr { - s_addr: mem::from_be32(ip) + s_addr: ByteOrder::from_big_endian(ip), + }; mem::size_of::() } diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index 9ba2c2cd258ed..a1c79bc0b757c 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -154,7 +154,7 @@ pub mod reader { } pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult { - use std::mem::from_be32; + use std::mem::ByteOrder; if data.len() - start < 4 { return vuint_at_slow(data, start); @@ -185,7 +185,7 @@ pub mod reader { unsafe { let ptr = data.as_ptr().offset(start as int) as *u32; - let val = from_be32(*ptr); + let val = ByteOrder::from_big_endian(*ptr); let i = (val >> 28u) as uint; let (shift, mask) = SHIFT_MASK_TABLE[i]; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index bace30e3f6ffd..1140f023d43fd 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -209,7 +209,7 @@ impl Uuid { /// * `d3` A 16-bit word /// * `d4` Array of 8 octets pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8]) -> Uuid { - use std::mem::{to_be16, to_be32}; + use std::mem::ByteOrder; // First construct a temporary field-based struct let mut fields = UuidFields { @@ -219,9 +219,9 @@ impl Uuid { data4: [0, ..8] }; - fields.data1 = to_be32(d1); - fields.data2 = to_be16(d2); - fields.data3 = to_be16(d3); + fields.data1 = d1.to_big_endian(); + fields.data2 = d2.to_big_endian(); + fields.data3 = d3.to_big_endian(); slice::bytes::copy_memory(fields.data4, d4); unsafe { @@ -335,16 +335,16 @@ impl Uuid { /// /// Example: `550e8400-e29b-41d4-a716-446655440000` pub fn to_hyphenated_str(&self) -> String { - use std::mem::{to_be16, to_be32}; + use std::mem::ByteOrder; // Convert to field-based struct as it matches groups in output. // Ensure fields are in network byte order, as per RFC. let mut uf: UuidFields; unsafe { uf = transmute_copy(&self.bytes); } - uf.data1 = to_be32(uf.data1); - uf.data2 = to_be16(uf.data2); - uf.data3 = to_be16(uf.data3); + uf.data1 = uf.data1.to_big_endian(); + uf.data2 = uf.data2.to_big_endian(); + uf.data3 = uf.data3.to_big_endian(); let s = format!("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-\ {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", uf.data1, From 4c0f8f49f6fe860efa268efa2f4fa0b5f00a4b07 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 16 Jun 2014 00:22:51 -0700 Subject: [PATCH 07/25] Fix comment formatting --- src/libcore/mem.rs | 76 ++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 6b08a32944c96..b64ee9bf4f702 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -403,10 +403,8 @@ pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } #[stable] pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } -/** - * Swap the values at two mutable locations of the same type, without - * deinitialising or copying either one. - */ +/// Swap the values at two mutable locations of the same type, without +/// deinitialising or copying either one. #[inline] #[stable] pub fn swap(x: &mut T, y: &mut T) { @@ -425,42 +423,40 @@ pub fn swap(x: &mut T, y: &mut T) { } } -/** - * Replace the value at a mutable location with a new one, returning the old - * value, without deinitialising or copying either one. - * - * This is primarily used for transferring and swapping ownership of a value - * in a mutable location. For example, this function allows consumption of - * one field of a struct by replacing it with another value. The normal approach - * doesn't always work: - * - * ```rust,ignore - * struct Buffer { buf: Vec } - * - * impl Buffer { - * fn get_and_reset(&mut self) -> Vec { - * // error: cannot move out of dereference of `&mut`-pointer - * let buf = self.buf; - * self.buf = Vec::new(); - * buf - * } - * } - * ``` - * - * Note that `T` does not necessarily implement `Clone`, so it can't even - * clone and reset `self.buf`. But `replace` can be used to disassociate - * the original value of `self.buf` from `self`, allowing it to be returned: - * - * ```rust - * # struct Buffer { buf: Vec } - * impl Buffer { - * fn get_and_reset(&mut self) -> Vec { - * use std::mem::replace; - * replace(&mut self.buf, Vec::new()) - * } - * } - * ``` - */ +/// Replace the value at a mutable location with a new one, returning the old +/// value, without deinitialising or copying either one. +/// +/// This is primarily used for transferring and swapping ownership of a value +/// in a mutable location. For example, this function allows consumption of +/// one field of a struct by replacing it with another value. The normal approach +/// doesn't always work: +/// +/// ```rust,ignore +/// struct Buffer { buf: Vec } +/// +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// // error: cannot move out of dereference of `&mut`-pointer +/// let buf = self.buf; +/// self.buf = Vec::new(); +/// buf +/// } +/// } +/// ``` +/// +/// Note that `T` does not necessarily implement `Clone`, so it can't even +/// clone and reset `self.buf`. But `replace` can be used to disassociate +/// the original value of `self.buf` from `self`, allowing it to be returned: +/// +/// ```rust +/// # struct Buffer { buf: Vec } +/// impl Buffer { +/// fn get_and_reset(&mut self) -> Vec { +/// use std::mem::replace; +/// replace(&mut self.buf, Vec::new()) +/// } +/// } +/// ``` #[inline] #[stable] pub fn replace(dest: &mut T, mut src: T) -> T { From ff9f92ce5224f5e27b8dc39ffc02eb9481f7cff1 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 16 Jun 2014 11:25:47 -0700 Subject: [PATCH 08/25] Merge the Bitwise and ByteOrder traits into the Int trait This reduces the complexity of the trait hierarchy. --- src/libcollections/enum_set.rs | 2 - src/libcollections/hash/mod.rs | 1 - src/libcore/mem.rs | 220 +--------------------- src/libcore/num/int_macros.rs | 69 +++++-- src/libcore/num/mod.rs | 305 ++++++++++++++++++++----------- src/libcore/num/uint_macros.rs | 69 +++++-- src/libnative/io/net.rs | 5 +- src/libnum/bigint.rs | 2 +- src/librustc/middle/trans/adt.rs | 1 - src/librustuv/net.rs | 5 +- src/libserialize/ebml.rs | 4 +- src/libstd/num/mod.rs | 2 +- src/libuuid/lib.rs | 3 - src/test/bench/sudoku.rs | 1 - 14 files changed, 325 insertions(+), 364 deletions(-) diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 34514fde9dbd1..1360b412c2370 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -15,8 +15,6 @@ use core::prelude::*; -use core::num::Bitwise; - #[deriving(Clone, PartialEq, Eq, Hash, Show)] /// A specialized Set implementation to use enum types. pub struct EnumSet { diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index 80417e2a57986..07c768d0c7916 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -103,7 +103,6 @@ macro_rules! impl_hash { impl Hash for $ty { #[inline] fn hash(&self, state: &mut S) { - use core::mem::ByteOrder; let a: [u8, ..::core::$ty::BYTES] = unsafe { mem::transmute((*self as $uty).to_little_endian() as $ty) }; diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index b64ee9bf4f702..eab344ac7a701 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -13,10 +13,9 @@ //! This module contains functions for querying the size and alignment of //! types, initializing and manipulating memory. -use clone::Clone; -use ptr; use intrinsics; -use intrinsics::{bswap16, bswap32, bswap64}; +use num::Int; +use ptr; pub use intrinsics::transmute; @@ -170,155 +169,6 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { ptr::write(dst, src) } -/// A type that can have its bytes re-ordered. -pub trait ByteOrder: Clone { - /// Reverses the byte order of the value. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// let m = 0xEFCDAB8967452301u64; - /// - /// assert_eq!(n.swap_bytes(), m); - /// ``` - fn swap_bytes(&self) -> Self; - - /// Convert a value from big endian to the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(ByteOrder::from_big_endian(n), n) - /// } else { - /// assert_eq!(ByteOrder::from_big_endian(n), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn from_big_endian(x: Self) -> Self { - if cfg!(target_endian = "big") { x } else { x.swap_bytes() } - } - - /// Convert a value from little endian to the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(ByteOrder::from_little_endian(n), n) - /// } else { - /// assert_eq!(ByteOrder::from_little_endian(n), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn from_little_endian(x: Self) -> Self { - if cfg!(target_endian = "little") { x } else { x.swap_bytes() } - } - - /// Convert the value to big endian from the target's endianness. - /// - /// On big endian this is a no-op. On little endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_big_endian(), n) - /// } else { - /// assert_eq!(n.to_big_endian(), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn to_big_endian(&self) -> Self { - if cfg!(target_endian = "big") { self.clone() } else { self.swap_bytes() } - } - - /// Convert the value to little endian from the target's endianness. - /// - /// On little endian this is a no-op. On big endian the bytes are swapped. - /// - /// # Example - /// - /// ```rust - /// use std::mem::ByteOrder; - /// - /// let n = 0x0123456789ABCDEFu64; - /// - /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_little_endian(), n) - /// } else { - /// assert_eq!(n.to_little_endian(), n.swap_bytes()) - /// } - /// ``` - #[inline] - fn to_little_endian(&self) -> Self { - if cfg!(target_endian = "little") { self.clone() } else { self.swap_bytes() } - } -} - -impl ByteOrder for u8 { - #[inline] - fn swap_bytes(&self) -> u8 { - *self // swapping a single byte does nothing - } -} - -impl ByteOrder for u16 { - #[inline] - fn swap_bytes(&self) -> u16 { - unsafe { intrinsics::bswap16(*self) } - } -} - -impl ByteOrder for u32 { - #[inline] - fn swap_bytes(&self) -> u32 { - unsafe { intrinsics::bswap32(*self) } - } -} - -impl ByteOrder for u64 { - #[inline] - fn swap_bytes(&self) -> u64 { - unsafe { intrinsics::bswap64(*self) } - } -} - -#[cfg(target_word_size = "32")] -impl ByteOrder for uint { - #[inline] - fn swap_bytes(&self) -> uint { - (*self as u32).swap_bytes() as uint - } -} - -#[cfg(target_word_size = "64")] -impl ByteOrder for uint { - #[inline] - fn swap_bytes(&self) -> uint { - (*self as u64).swap_bytes() as uint - } -} - /// Convert an u16 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. @@ -366,42 +216,42 @@ pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le16(x: u16) -> u16 { ByteOrder::from_little_endian(x) } +pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le32(x: u32) -> u32 { ByteOrder::from_little_endian(x) } +pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] #[stable] -pub fn from_le64(x: u64) -> u64 { ByteOrder::from_little_endian(x) } +pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be16(x: u16) -> u16 { ByteOrder::from_big_endian(x) } +pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be32(x: u32) -> u32 { ByteOrder::from_big_endian(x) } +pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] #[stable] -pub fn from_be64(x: u64) -> u64 { ByteOrder::from_big_endian(x) } +pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } /// Swap the values at two mutable locations of the same type, without /// deinitialising or copying either one. @@ -642,60 +492,6 @@ mod tests { assert!(Vec::from_slice([76u8]) == transmute("L".to_string())); } } - - macro_rules! test_byte_order { - ($T:ident) => { - mod $T { - use mem::ByteOrder; - - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; - - static _0: $T = 0; - static _1: $T = !0; - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_little_endian() { - assert_eq!(ByteOrder::from_little_endian(A.to_little_endian()), A); - assert_eq!(ByteOrder::from_little_endian(B.to_little_endian()), B); - assert_eq!(ByteOrder::from_little_endian(C.to_little_endian()), C); - assert_eq!(ByteOrder::from_little_endian(_0), _0); - assert_eq!(ByteOrder::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); - } - - #[test] - fn test_big_endian() { - assert_eq!(ByteOrder::from_big_endian(A.to_big_endian()), A); - assert_eq!(ByteOrder::from_big_endian(B.to_big_endian()), B); - assert_eq!(ByteOrder::from_big_endian(C.to_big_endian()), C); - assert_eq!(ByteOrder::from_big_endian(_0), _0); - assert_eq!(ByteOrder::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); - } - } - } - } - - test_byte_order!(u8) - test_byte_order!(u16) - test_byte_order!(u32) - test_byte_order!(u64) - test_byte_order!(uint) } // FIXME #13642 (these benchmarks should be in another place) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 8a1bd66aa1acc..84744b3f5d701 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -35,7 +35,6 @@ mod tests { use int; use num; - use num::Bitwise; use num::CheckedDiv; #[test] @@ -90,7 +89,7 @@ mod tests { } #[test] - fn test_bitwise() { + fn test_bitwise_operators() { assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); @@ -99,34 +98,74 @@ mod tests { assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not()); } + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + #[test] fn test_count_ones() { - assert!((0b0101100 as $T).count_ones() == 3); - assert!((0b0100001 as $T).count_ones() == 2); - assert!((0b1111001 as $T).count_ones() == 5); + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); } #[test] fn test_count_zeros() { - assert!((0b0101100 as $T).count_zeros() == BITS as $T - 3); - assert!((0b0100001 as $T).count_zeros() == BITS as $T - 2); - assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); } #[test] fn test_rotate() { - let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); - let n: $T = 0b0100001; assert_eq!(n.rotate_left(3).rotate_left(2).rotate_right(5), n); - let n: $T = 0b1111001; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behaviour. See #10183. - let n: $T = 0; assert_eq!(n.rotate_left(124), n); - let n: $T = -1; assert_eq!(n.rotate_left(124), n); - let n: $T = 0; assert_eq!(n.rotate_right(124), n); - let n: $T = -1; assert_eq!(n.rotate_right(124), n); + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(Int::from_little_endian(A.to_little_endian()), A); + assert_eq!(Int::from_little_endian(B.to_little_endian()), B); + assert_eq!(Int::from_little_endian(C.to_little_endian()), C); + assert_eq!(Int::from_little_endian(_0), _0); + assert_eq!(Int::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(Int::from_big_endian(A.to_big_endian()), A); + assert_eq!(Int::from_big_endian(B.to_big_endian()), B); + assert_eq!(Int::from_big_endian(C.to_big_endian()), C); + assert_eq!(Int::from_big_endian(_0), _0); + assert_eq!(Int::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); } #[test] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 696abc05ed275..ed0c24e7fa008 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -376,193 +376,292 @@ bounded_impl!(i64, i64::MIN, i64::MAX) bounded_impl!(f32, f32::MIN_VALUE, f32::MAX_VALUE) bounded_impl!(f64, f64::MIN_VALUE, f64::MAX_VALUE) -/// Numbers with a fixed binary representation. -pub trait Bitwise: Bounded - + Not - + BitAnd - + BitOr - + BitXor - + Shl - + Shr { - /// Returns the number of ones in the binary representation of the number. +/// Specifies the available operations common to all of Rust's core numeric primitives. +/// These may not always make sense from a purely mathematical point of view, but +/// may be useful for systems programming. +pub trait Primitive: Copy + + Clone + + Num + + NumCast + + PartialOrd + + Bounded {} + +trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) + +/// A collection of traits relevant to primitive signed and unsigned integers +pub trait Int: Primitive + + CheckedAdd + + CheckedSub + + CheckedMul + + CheckedDiv + + Bounded + + Not + + BitAnd + + BitOr + + BitXor + + Shl + + Shr { + /// Returns the number of ones in the binary representation of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b01001100u8; + /// /// assert_eq!(n.count_ones(), 3); /// ``` - fn count_ones(&self) -> Self; + fn count_ones(self) -> Self; - /// Returns the number of zeros in the binary representation of the number. + /// Returns the number of zeros in the binary representation of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b01001100u8; + /// /// assert_eq!(n.count_zeros(), 5); /// ``` #[inline] - fn count_zeros(&self) -> Self { - (!*self).count_ones() + fn count_zeros(self) -> Self { + (!self).count_ones() } /// Returns the number of leading zeros in the in the binary representation - /// of the number. + /// of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b0101000u16; + /// /// assert_eq!(n.leading_zeros(), 10); /// ``` - fn leading_zeros(&self) -> Self; + fn leading_zeros(self) -> Self; /// Returns the number of trailing zeros in the in the binary representation - /// of the number. + /// of the integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0b0101000u16; + /// /// assert_eq!(n.trailing_zeros(), 3); /// ``` - fn trailing_zeros(&self) -> Self; + fn trailing_zeros(self) -> Self; - /// Shifts the bits to the left by a specified amount amount, `r`, wrapping - /// the truncated bits to the end of the resulting value. + /// Shifts the bits to the left by a specified amount amount, `n`, wrapping + /// the truncated bits to the end of the resulting integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0x3456789ABCDEF012u64; + /// /// assert_eq!(n.rotate_left(12), m); /// ``` - fn rotate_left(&self, r: uint) -> Self; + fn rotate_left(self, n: uint) -> Self; - /// Shifts the bits to the right by a specified amount amount, `r`, wrapping - /// the truncated bits to the beginning of the resulting value. + /// Shifts the bits to the right by a specified amount amount, `n`, wrapping + /// the truncated bits to the beginning of the resulting integer. /// /// # Example /// /// ```rust - /// use std::num::Bitwise; - /// /// let n = 0x0123456789ABCDEFu64; /// let m = 0xDEF0123456789ABCu64; + /// /// assert_eq!(n.rotate_right(12), m); /// ``` - fn rotate_right(&self, r: uint) -> Self; + fn rotate_right(self, n: uint) -> Self; + + /// Reverses the byte order of the integer. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + fn swap_bytes(self) -> Self; + + /// Convert a integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_big_endian(n), n) + /// } else { + /// assert_eq!(Int::from_big_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_big_endian(x: Self) -> Self { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert a integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_little_endian(n), n) + /// } else { + /// assert_eq!(Int::from_little_endian(n), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn from_little_endian(x: Self) -> Self { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert the integer to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_big_endian(), n) + /// } else { + /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_big_endian(self) -> Self { + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert the integer to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Example + /// + /// ```rust + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_little_endian(), n) + /// } else { + /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// } + /// ``` + #[inline] + fn to_little_endian(self) -> Self { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } } -macro_rules! bitwise_impl { - ($t:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { - impl Bitwise for $t { +macro_rules! int_impl { + ($T:ty, $BITS:expr, $ctpop:path, $ctlz:path, $cttz:path, $bswap:path) => { + impl Int for $T { #[inline] - fn count_ones(&self) -> $t { unsafe { $co(*self) } } + fn count_ones(self) -> $T { unsafe { $ctpop(self) } } #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self) } } + fn leading_zeros(self) -> $T { unsafe { $ctlz(self) } } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self) } } + fn trailing_zeros(self) -> $T { unsafe { $cttz(self) } } #[inline] - fn rotate_left(&self, r: uint) -> $t { - // Protect against undefined behaviour for overlong bit shifts - let r = r % $bits; - (*self << r) | (*self >> ($bits - r)) + fn rotate_left(self, n: uint) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> ($BITS - n)) } #[inline] - fn rotate_right(&self, r: uint) -> $t { - // Protect against undefined behaviour for overlong bit shifts - let r = r % $bits; - (*self >> r) | (*self << ($bits - r)) + fn rotate_right(self, n: uint) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << ($BITS - n)) } + + #[inline] + fn swap_bytes(self) -> $T { unsafe { $bswap(self) } } } } } -macro_rules! bitwise_cast_impl { - ($t:ty, $t_cast:ty, $bits:expr, $co:path, $lz:path, $tz:path) => { - impl Bitwise for $t { +/// Swapping a single byte is a no-op. This is marked as `unsafe` for +/// consistency with the other `bswap` intrinsics. +unsafe fn bswap8(x: u8) -> u8 { x } + +int_impl!(u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8) + +int_impl!(u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16) + +int_impl!(u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32) + +int_impl!(u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64) + +macro_rules! int_cast_impl { + ($T:ty, $U:ty) => { + impl Int for $T { #[inline] - fn count_ones(&self) -> $t { unsafe { $co(*self as $t_cast) as $t } } + fn count_ones(self) -> $T { (self as $U).count_ones() as $T } #[inline] - fn leading_zeros(&self) -> $t { unsafe { $lz(*self as $t_cast) as $t } } + fn leading_zeros(self) -> $T { (self as $U).leading_zeros() as $T } #[inline] - fn trailing_zeros(&self) -> $t { unsafe { $tz(*self as $t_cast) as $t } } + fn trailing_zeros(self) -> $T { (self as $U).trailing_zeros() as $T } #[inline] - fn rotate_left(&self, r: uint) -> $t { - // cast to prevent the sign bit from being corrupted - (*self as $t_cast).rotate_left(r) as $t - } + fn rotate_left(self, n: uint) -> $T { (self as $U).rotate_left(n) as $T } #[inline] - fn rotate_right(&self, r: uint) -> $t { - // cast to prevent the sign bit from being corrupted - (*self as $t_cast).rotate_right(r) as $t - } + fn rotate_right(self, n: uint) -> $T { (self as $U).rotate_right(n) as $T } + + #[inline] + fn swap_bytes(self) -> $T { (self as $U).swap_bytes() as $T } } } } -#[cfg(target_word_size = "32")] -bitwise_cast_impl!(uint, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -#[cfg(target_word_size = "64")] -bitwise_cast_impl!(uint, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -bitwise_impl!(u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) -bitwise_impl!(u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) -bitwise_impl!(u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -bitwise_impl!(u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -#[cfg(target_word_size = "32")] -bitwise_cast_impl!(int, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -#[cfg(target_word_size = "64")] -bitwise_cast_impl!(int, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -bitwise_cast_impl!(i8, u8, 8, intrinsics::ctpop8, intrinsics::ctlz8, intrinsics::cttz8) -bitwise_cast_impl!(i16, u16, 16, intrinsics::ctpop16, intrinsics::ctlz16, intrinsics::cttz16) -bitwise_cast_impl!(i32, u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32) -bitwise_cast_impl!(i64, u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64) - -/// Specifies the available operations common to all of Rust's core numeric primitives. -/// These may not always make sense from a purely mathematical point of view, but -/// may be useful for systems programming. -pub trait Primitive: Copy - + Clone - + Num - + NumCast - + PartialOrd - + Bounded {} - -trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) - -/// A collection of traits relevant to primitive signed and unsigned integers -pub trait Int: Primitive - + Bitwise - + CheckedAdd - + CheckedSub - + CheckedMul - + CheckedDiv {} +int_cast_impl!(i8, u8) +int_cast_impl!(i16, u16) +int_cast_impl!(i32, u32) +int_cast_impl!(i64, u64) -trait_impl!(Int for uint u8 u16 u32 u64 int i8 i16 i32 i64) +#[cfg(target_word_size = "32")] int_cast_impl!(uint, u32) +#[cfg(target_word_size = "64")] int_cast_impl!(uint, u64) +#[cfg(target_word_size = "32")] int_cast_impl!(int, u32) +#[cfg(target_word_size = "64")] int_cast_impl!(int, u64) /// Returns the smallest power of 2 greater than or equal to `n`. #[inline] diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 8548b14105394..1fe3c4cf1f1cf 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -26,7 +26,6 @@ mod tests { use num; use num::CheckedDiv; - use num::Bitwise; #[test] fn test_overflows() { @@ -41,7 +40,7 @@ mod tests { } #[test] - fn test_bitwise() { + fn test_bitwise_operators() { assert!(0b1110 as $T == (0b1100 as $T).bitor(&(0b1010 as $T))); assert!(0b1000 as $T == (0b1100 as $T).bitand(&(0b1010 as $T))); assert!(0b0110 as $T == (0b1100 as $T).bitxor(&(0b1010 as $T))); @@ -50,34 +49,74 @@ mod tests { assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); } + static A: $T = 0b0101100; + static B: $T = 0b0100001; + static C: $T = 0b1111001; + + static _0: $T = 0; + static _1: $T = !0; + #[test] fn test_count_ones() { - assert!((0b0101100 as $T).count_ones() == 3); - assert!((0b0100001 as $T).count_ones() == 2); - assert!((0b1111001 as $T).count_ones() == 5); + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); } #[test] fn test_count_zeros() { - assert!((0b0101100 as $T).count_zeros() == BITS as $T - 3); - assert!((0b0100001 as $T).count_zeros() == BITS as $T - 2); - assert!((0b1111001 as $T).count_zeros() == BITS as $T - 5); + assert!(A.count_zeros() == BITS as $T - 3); + assert!(B.count_zeros() == BITS as $T - 2); + assert!(C.count_zeros() == BITS as $T - 5); } #[test] fn test_rotate() { - let n: $T = 0b0101100; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); - let n: $T = 0b0100001; assert_eq!(n.rotate_left(3).rotate_left(2).rotate_right(5), n); - let n: $T = 0b1111001; assert_eq!(n.rotate_left(6).rotate_right(2).rotate_right(4), n); + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behaviour. See #10183. - let n: $T = 0; assert_eq!(n.rotate_left(124), n); - let n: $T = MAX; assert_eq!(n.rotate_left(124), n); - let n: $T = 0; assert_eq!(n.rotate_right(124), n); - let n: $T = MAX; assert_eq!(n.rotate_right(124), n); + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_little_endian() { + assert_eq!(Int::from_little_endian(A.to_little_endian()), A); + assert_eq!(Int::from_little_endian(B.to_little_endian()), B); + assert_eq!(Int::from_little_endian(C.to_little_endian()), C); + assert_eq!(Int::from_little_endian(_0), _0); + assert_eq!(Int::from_little_endian(_1), _1); + assert_eq!(_0.to_little_endian(), _0); + assert_eq!(_1.to_little_endian(), _1); + } + + #[test] + fn test_big_endian() { + assert_eq!(Int::from_big_endian(A.to_big_endian()), A); + assert_eq!(Int::from_big_endian(B.to_big_endian()), B); + assert_eq!(Int::from_big_endian(C.to_big_endian()), C); + assert_eq!(Int::from_big_endian(_0), _0); + assert_eq!(Int::from_big_endian(_1), _1); + assert_eq!(_0.to_big_endian(), _0); + assert_eq!(_1.to_big_endian(), _1); } #[test] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index f0cd2d966cb36..23fd607aafeef 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -11,7 +11,6 @@ use alloc::arc::Arc; use libc; use std::mem; -use std::mem::ByteOrder; use std::rt::mutex; use std::rt::rtio; use std::rt::rtio::{IoResult, IoError}; @@ -31,7 +30,7 @@ pub fn htons(u: u16) -> u16 { u.to_big_endian() } pub fn ntohs(u: u16) -> u16 { - ByteOrder::from_big_endian(u) + Int::from_big_endian(u) } enum InAddr { @@ -47,7 +46,7 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr { (c as u32 << 8) | (d as u32 << 0); InAddr(libc::in_addr { - s_addr: ByteOrder::from_big_endian(ip) + s_addr: Int::from_big_endian(ip) }) } rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => { diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index 0933301970d19..e9153f89e04ee 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -23,7 +23,7 @@ use std::{cmp, fmt}; use std::default::Default; use std::from_str::FromStr; use std::num::CheckedDiv; -use std::num::{Bitwise, ToPrimitive, FromPrimitive}; +use std::num::{ToPrimitive, FromPrimitive}; use std::num::{Zero, One, ToStrRadix, FromStrRadix}; use std::string::String; use std::{uint, i64, u64}; diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 9f4b11116dbb7..e4b28dc7aa7c2 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -46,7 +46,6 @@ #![allow(unsigned_negate)] use libc::c_ulonglong; -use std::num::{Bitwise}; use std::rc::Rc; use lib::llvm::{ValueRef, True, IntEQ, IntNE}; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 83beeceb8de3e..aa7fab2565d8c 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -11,7 +11,6 @@ use libc::{size_t, ssize_t, c_int, c_void, c_uint}; use libc; use std::mem; -use std::mem::ByteOrder; use std::ptr; use std::rt::rtio; use std::rt::rtio::IoError; @@ -32,7 +31,7 @@ use uvll; //////////////////////////////////////////////////////////////////////////////// pub fn htons(u: u16) -> u16 { u.to_big_endian() } -pub fn ntohs(u: u16) -> u16 { ByteOrder::from_big_endian(u) } +pub fn ntohs(u: u16) -> u16 { Int::from_big_endian(u) } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: uint) -> rtio::SocketAddr { @@ -90,7 +89,7 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) { (*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_port = htons(addr.port); (*storage).sin_addr = libc::in_addr { - s_addr: ByteOrder::from_big_endian(ip), + s_addr: Int::from_big_endian(ip), }; mem::size_of::() diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index a1c79bc0b757c..7d0c82fc9a2d5 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -154,8 +154,6 @@ pub mod reader { } pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult { - use std::mem::ByteOrder; - if data.len() - start < 4 { return vuint_at_slow(data, start); } @@ -185,7 +183,7 @@ pub mod reader { unsafe { let ptr = data.as_ptr().offset(start as int) as *u32; - let val = ByteOrder::from_big_endian(*ptr); + let val = Int::from_big_endian(*ptr); let i = (val >> 28u) as uint; let (shift, mask) = SHIFT_MASK_TABLE[i]; diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 602a2240f3908..7301f9b08e9dc 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -22,7 +22,7 @@ use string::String; pub use core::num::{Num, div_rem, Zero, zero, One, one}; pub use core::num::{Signed, abs, abs_sub, signum}; -pub use core::num::{Unsigned, pow, Bounded, Bitwise}; +pub use core::num::{Unsigned, pow, Bounded}; pub use core::num::{Primitive, Int, Saturating}; pub use core::num::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv}; pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 1140f023d43fd..bbd461e3dde0d 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -209,8 +209,6 @@ impl Uuid { /// * `d3` A 16-bit word /// * `d4` Array of 8 octets pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8]) -> Uuid { - use std::mem::ByteOrder; - // First construct a temporary field-based struct let mut fields = UuidFields { data1: 0, @@ -335,7 +333,6 @@ impl Uuid { /// /// Example: `550e8400-e29b-41d4-a716-446655440000` pub fn to_hyphenated_str(&self) -> String { - use std::mem::ByteOrder; // Convert to field-based struct as it matches groups in output. // Ensure fields are in network byte order, as per RFC. let mut uf: UuidFields; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index c0ea6f8617d87..af51157bba564 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -16,7 +16,6 @@ use std::io; use std::io::stdio::StdReader; use std::io::BufferedReader; -use std::num::Bitwise; use std::os; // Computes a single solution to a given 9x9 sudoku From 779ca97525176bc1d764f1b88906363290fcf851 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 16 Jun 2014 14:33:45 -0700 Subject: [PATCH 09/25] Remove `#[stable]` attribute from free-standing endian conversions and mark them as deprecated --- src/libcore/mem.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index eab344ac7a701..1032b820b2751 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -173,84 +173,84 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_little_endian` instead"] pub fn to_le16(x: u16) -> u16 { x.to_little_endian() } /// Convert an u32 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_little_endian` instead"] pub fn to_le32(x: u32) -> u32 { x.to_little_endian() } /// Convert an u64 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_little_endian` instead"] pub fn to_le64(x: u64) -> u64 { x.to_little_endian() } /// Convert an u16 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_big_endian` instead"] pub fn to_be16(x: u16) -> u16 { x.to_big_endian() } /// Convert an u32 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_big_endian` instead"] pub fn to_be32(x: u32) -> u32 { x.to_big_endian() } /// Convert an u64 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::to_big_endian` instead"] pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } /// Convert an u16 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_little_endian` instead"] pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_little_endian` instead"] pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_little_endian` instead"] pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_big_endian` instead"] pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_big_endian` instead"] pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[stable] +#[deprecated = "use `Int::from_big_endian` instead"] pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } /// Swap the values at two mutable locations of the same type, without From cb8ca2dafdbcdedcaeb2573dccd3b3e4a26cae44 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 17 Jun 2014 15:47:31 -0700 Subject: [PATCH 10/25] Shorten endian conversion method names The consensus on #14917 was that the proposed names were too long. --- src/libcollections/hash/mod.rs | 2 +- src/libcore/mem.rs | 48 +++++++++++++++++----------------- src/libcore/num/int_macros.rs | 32 +++++++++++------------ src/libcore/num/mod.rs | 24 ++++++++--------- src/libcore/num/uint_macros.rs | 32 +++++++++++------------ src/libnative/io/net.rs | 8 +++--- src/librustuv/net.rs | 8 +++--- src/libserialize/ebml.rs | 2 +- src/libuuid/lib.rs | 12 ++++----- 9 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/libcollections/hash/mod.rs b/src/libcollections/hash/mod.rs index 07c768d0c7916..a0c0c9f973578 100644 --- a/src/libcollections/hash/mod.rs +++ b/src/libcollections/hash/mod.rs @@ -104,7 +104,7 @@ macro_rules! impl_hash { #[inline] fn hash(&self, state: &mut S) { let a: [u8, ..::core::$ty::BYTES] = unsafe { - mem::transmute((*self as $uty).to_little_endian() as $ty) + mem::transmute((*self as $uty).to_le() as $ty) }; state.write(a.as_slice()) } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 1032b820b2751..5280ac0d64fb2 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -173,85 +173,85 @@ pub unsafe fn move_val_init(dst: &mut T, src: T) { /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_little_endian` instead"] -pub fn to_le16(x: u16) -> u16 { x.to_little_endian() } +#[deprecated = "use `Int::to_le` instead"] +pub fn to_le16(x: u16) -> u16 { x.to_le() } /// Convert an u32 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_little_endian` instead"] -pub fn to_le32(x: u32) -> u32 { x.to_little_endian() } +#[deprecated = "use `Int::to_le` instead"] +pub fn to_le32(x: u32) -> u32 { x.to_le() } /// Convert an u64 to little endian from the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_little_endian` instead"] -pub fn to_le64(x: u64) -> u64 { x.to_little_endian() } +#[deprecated = "use `Int::to_le` instead"] +pub fn to_le64(x: u64) -> u64 { x.to_le() } /// Convert an u16 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_big_endian` instead"] -pub fn to_be16(x: u16) -> u16 { x.to_big_endian() } +#[deprecated = "use `Int::to_be` instead"] +pub fn to_be16(x: u16) -> u16 { x.to_be() } /// Convert an u32 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_big_endian` instead"] -pub fn to_be32(x: u32) -> u32 { x.to_big_endian() } +#[deprecated = "use `Int::to_be` instead"] +pub fn to_be32(x: u32) -> u32 { x.to_be() } /// Convert an u64 to big endian from the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::to_big_endian` instead"] -pub fn to_be64(x: u64) -> u64 { x.to_big_endian() } +#[deprecated = "use `Int::to_be` instead"] +pub fn to_be64(x: u64) -> u64 { x.to_be() } /// Convert an u16 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_little_endian` instead"] -pub fn from_le16(x: u16) -> u16 { Int::from_little_endian(x) } +#[deprecated = "use `Int::from_le` instead"] +pub fn from_le16(x: u16) -> u16 { Int::from_le(x) } /// Convert an u32 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_little_endian` instead"] -pub fn from_le32(x: u32) -> u32 { Int::from_little_endian(x) } +#[deprecated = "use `Int::from_le` instead"] +pub fn from_le32(x: u32) -> u32 { Int::from_le(x) } /// Convert an u64 from little endian to the target's endianness. /// /// On little endian, this is a no-op. On big endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_little_endian` instead"] -pub fn from_le64(x: u64) -> u64 { Int::from_little_endian(x) } +#[deprecated = "use `Int::from_le` instead"] +pub fn from_le64(x: u64) -> u64 { Int::from_le(x) } /// Convert an u16 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_big_endian` instead"] -pub fn from_be16(x: u16) -> u16 { Int::from_big_endian(x) } +#[deprecated = "use `Int::from_be` instead"] +pub fn from_be16(x: u16) -> u16 { Int::from_be(x) } /// Convert an u32 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_big_endian` instead"] -pub fn from_be32(x: u32) -> u32 { Int::from_big_endian(x) } +#[deprecated = "use `Int::from_be` instead"] +pub fn from_be32(x: u32) -> u32 { Int::from_be(x) } /// Convert an u64 from big endian to the target's endianness. /// /// On big endian, this is a no-op. On little endian, the bytes are swapped. #[inline] -#[deprecated = "use `Int::from_big_endian` instead"] -pub fn from_be64(x: u64) -> u64 { Int::from_big_endian(x) } +#[deprecated = "use `Int::from_be` instead"] +pub fn from_be64(x: u64) -> u64 { Int::from_be(x) } /// Swap the values at two mutable locations of the same type, without /// deinitialising or copying either one. diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 84744b3f5d701..79734324706b2 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -147,25 +147,25 @@ mod tests { } #[test] - fn test_little_endian() { - assert_eq!(Int::from_little_endian(A.to_little_endian()), A); - assert_eq!(Int::from_little_endian(B.to_little_endian()), B); - assert_eq!(Int::from_little_endian(C.to_little_endian()), C); - assert_eq!(Int::from_little_endian(_0), _0); - assert_eq!(Int::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); + fn test_le() { + assert_eq!(Int::from_le(A.to_le()), A); + assert_eq!(Int::from_le(B.to_le()), B); + assert_eq!(Int::from_le(C.to_le()), C); + assert_eq!(Int::from_le(_0), _0); + assert_eq!(Int::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); } #[test] - fn test_big_endian() { - assert_eq!(Int::from_big_endian(A.to_big_endian()), A); - assert_eq!(Int::from_big_endian(B.to_big_endian()), B); - assert_eq!(Int::from_big_endian(C.to_big_endian()), C); - assert_eq!(Int::from_big_endian(_0), _0); - assert_eq!(Int::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); + fn test_be() { + assert_eq!(Int::from_be(A.to_be()), A); + assert_eq!(Int::from_be(B.to_be()), B); + assert_eq!(Int::from_be(C.to_be()), C); + assert_eq!(Int::from_be(_0), _0); + assert_eq!(Int::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); } #[test] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ed0c24e7fa008..dd32a6da1063b 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -498,13 +498,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { - /// assert_eq!(Int::from_big_endian(n), n) + /// assert_eq!(Int::from_be(n), n) /// } else { - /// assert_eq!(Int::from_big_endian(n), n.swap_bytes()) + /// assert_eq!(Int::from_be(n), n.swap_bytes()) /// } /// ``` #[inline] - fn from_big_endian(x: Self) -> Self { + fn from_be(x: Self) -> Self { if cfg!(target_endian = "big") { x } else { x.swap_bytes() } } @@ -518,13 +518,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { - /// assert_eq!(Int::from_little_endian(n), n) + /// assert_eq!(Int::from_le(n), n) /// } else { - /// assert_eq!(Int::from_little_endian(n), n.swap_bytes()) + /// assert_eq!(Int::from_le(n), n.swap_bytes()) /// } /// ``` #[inline] - fn from_little_endian(x: Self) -> Self { + fn from_le(x: Self) -> Self { if cfg!(target_endian = "little") { x } else { x.swap_bytes() } } @@ -538,13 +538,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "big") { - /// assert_eq!(n.to_big_endian(), n) + /// assert_eq!(n.to_be(), n) /// } else { - /// assert_eq!(n.to_big_endian(), n.swap_bytes()) + /// assert_eq!(n.to_be(), n.swap_bytes()) /// } /// ``` #[inline] - fn to_big_endian(self) -> Self { + fn to_be(self) -> Self { // or not to be? if cfg!(target_endian = "big") { self } else { self.swap_bytes() } } @@ -558,13 +558,13 @@ pub trait Int: Primitive /// let n = 0x0123456789ABCDEFu64; /// /// if cfg!(target_endian = "little") { - /// assert_eq!(n.to_little_endian(), n) + /// assert_eq!(n.to_le(), n) /// } else { - /// assert_eq!(n.to_little_endian(), n.swap_bytes()) + /// assert_eq!(n.to_le(), n.swap_bytes()) /// } /// ``` #[inline] - fn to_little_endian(self) -> Self { + fn to_le(self) -> Self { if cfg!(target_endian = "little") { self } else { self.swap_bytes() } } } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 1fe3c4cf1f1cf..be1f960bcc3df 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -98,25 +98,25 @@ mod tests { } #[test] - fn test_little_endian() { - assert_eq!(Int::from_little_endian(A.to_little_endian()), A); - assert_eq!(Int::from_little_endian(B.to_little_endian()), B); - assert_eq!(Int::from_little_endian(C.to_little_endian()), C); - assert_eq!(Int::from_little_endian(_0), _0); - assert_eq!(Int::from_little_endian(_1), _1); - assert_eq!(_0.to_little_endian(), _0); - assert_eq!(_1.to_little_endian(), _1); + fn test_le() { + assert_eq!(Int::from_le(A.to_le()), A); + assert_eq!(Int::from_le(B.to_le()), B); + assert_eq!(Int::from_le(C.to_le()), C); + assert_eq!(Int::from_le(_0), _0); + assert_eq!(Int::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); } #[test] - fn test_big_endian() { - assert_eq!(Int::from_big_endian(A.to_big_endian()), A); - assert_eq!(Int::from_big_endian(B.to_big_endian()), B); - assert_eq!(Int::from_big_endian(C.to_big_endian()), C); - assert_eq!(Int::from_big_endian(_0), _0); - assert_eq!(Int::from_big_endian(_1), _1); - assert_eq!(_0.to_big_endian(), _0); - assert_eq!(_1.to_big_endian(), _1); + fn test_be() { + assert_eq!(Int::from_be(A.to_be()), A); + assert_eq!(Int::from_be(B.to_be()), B); + assert_eq!(Int::from_be(C.to_be()), C); + assert_eq!(Int::from_be(_0), _0); + assert_eq!(Int::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); } #[test] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 23fd607aafeef..5dfae8d9efe64 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -27,10 +27,10 @@ use super::util; #[cfg(unix)] pub type sock_t = super::file::fd_t; pub fn htons(u: u16) -> u16 { - u.to_big_endian() + u.to_be() } pub fn ntohs(u: u16) -> u16 { - Int::from_big_endian(u) + Int::from_be(u) } enum InAddr { @@ -46,7 +46,7 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr { (c as u32 << 8) | (d as u32 << 0); InAddr(libc::in_addr { - s_addr: Int::from_big_endian(ip) + s_addr: Int::from_be(ip) }) } rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => { @@ -180,7 +180,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); + let ip = (storage.sin_addr.s_addr as u32).to_be(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index aa7fab2565d8c..82693acb1e9dc 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -30,8 +30,8 @@ use uvll; /// Generic functions related to dealing with sockaddr things //////////////////////////////////////////////////////////////////////////////// -pub fn htons(u: u16) -> u16 { u.to_big_endian() } -pub fn ntohs(u: u16) -> u16 { Int::from_big_endian(u) } +pub fn htons(u: u16) -> u16 { u.to_be() } +pub fn ntohs(u: u16) -> u16 { Int::from_be(u) } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: uint) -> rtio::SocketAddr { @@ -41,7 +41,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; - let ip = (storage.sin_addr.s_addr as u32).to_big_endian(); + let ip = (storage.sin_addr.s_addr as u32).to_be(); let a = (ip >> 24) as u8; let b = (ip >> 16) as u8; let c = (ip >> 8) as u8; @@ -89,7 +89,7 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) { (*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_port = htons(addr.port); (*storage).sin_addr = libc::in_addr { - s_addr: Int::from_big_endian(ip), + s_addr: Int::from_be(ip), }; mem::size_of::() diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index 7d0c82fc9a2d5..12c5a3493c17b 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -183,7 +183,7 @@ pub mod reader { unsafe { let ptr = data.as_ptr().offset(start as int) as *u32; - let val = Int::from_big_endian(*ptr); + let val = Int::from_be(*ptr); let i = (val >> 28u) as uint; let (shift, mask) = SHIFT_MASK_TABLE[i]; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index bbd461e3dde0d..b68b435da4bb0 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -217,9 +217,9 @@ impl Uuid { data4: [0, ..8] }; - fields.data1 = d1.to_big_endian(); - fields.data2 = d2.to_big_endian(); - fields.data3 = d3.to_big_endian(); + fields.data1 = d1.to_be(); + fields.data2 = d2.to_be(); + fields.data3 = d3.to_be(); slice::bytes::copy_memory(fields.data4, d4); unsafe { @@ -339,9 +339,9 @@ impl Uuid { unsafe { uf = transmute_copy(&self.bytes); } - uf.data1 = uf.data1.to_big_endian(); - uf.data2 = uf.data2.to_big_endian(); - uf.data3 = uf.data3.to_big_endian(); + uf.data1 = uf.data1.to_be(); + uf.data2 = uf.data2.to_be(); + uf.data3 = uf.data3.to_be(); let s = format!("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-\ {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", uf.data1, From ae7006e373e458eaf0464761a6b492181c47100e Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 17 Jun 2014 11:09:20 -0700 Subject: [PATCH 11/25] Update doc comment for Int trait --- src/libcore/num/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index dd32a6da1063b..573470c29bcf4 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -388,7 +388,8 @@ pub trait Primitive: Copy trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64) -/// A collection of traits relevant to primitive signed and unsigned integers +/// A primitive signed or unsigned integer equipped with various bitwise +/// operators, bit counting methods, and endian conversion functions. pub trait Int: Primitive + CheckedAdd + CheckedSub From 8e9e17d188c2b59813b5a7d8f6ebb0c22e26ce93 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Tue, 17 Jun 2014 15:21:28 -0400 Subject: [PATCH 12/25] librustc: Use expr_ty_adjusted in trans_overloaded_call. --- src/librustc/middle/trans/expr.rs | 2 +- src/test/run-pass/issue-14958.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-14958.rs diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 42c7a71bab84d..599b45aafe20d 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1463,7 +1463,7 @@ fn trans_overloaded_call<'a>( // Evaluate and tuple the arguments. let tuple_type = ty::mk_tup(bcx.tcx(), args.iter() - .map(|e| expr_ty(bcx, &**e)) + .map(|e| ty::expr_ty_adjusted(bcx.tcx(), &**e)) .collect()); let repr = adt::represent_type(bcx.ccx(), tuple_type); let numbered_fields: Vec<(uint, Gc)> = diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs new file mode 100644 index 0000000000000..045d3cc0458f7 --- /dev/null +++ b/src/test/run-pass/issue-14958.rs @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(overloaded_calls)] + +trait Foo {} + +struct Bar; + +impl<'a> std::ops::Fn<(&'a Foo,), ()> for Bar { + fn call(&self, _: (&'a Foo,)) {} +} + +struct Baz; + +impl Foo for Baz {} + +fn main() { + let bar = Bar; + let baz = &Baz; + bar(baz); +} From a23511a65de7cce47aa12541de60df72b10eb2eb Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 17 Jun 2014 14:48:54 -0700 Subject: [PATCH 13/25] Revamp TaskBuilder API This patch consolidates and cleans up the task spawning APIs: * Removes the problematic `future_result` method from `std::task::TaskBuilder`, and adds a `try_future` that both spawns the task and returns a future representing its eventual result (or failure). * Removes the public `opts` field from `TaskBuilder`, instead adding appropriate builder methods to configure the task. * Adds extension traits to libgreen and libnative that add methods to `TaskBuilder` for spawning the task as a green or native thread. Previously, there was no way to benefit from the `TaskBuilder` functionality and also set the scheduler to spawn within. With this change, all task spawning scenarios are supported through the `TaskBuilder` interface. Closes #3725. [breaking-change] --- src/libgreen/lib.rs | 78 ++- src/libnative/lib.rs | 10 +- src/libnative/task.rs | 34 +- src/libstd/task.rs | 841 +++++++++++++++++-------------- src/test/run-pass/task-stderr.rs | 26 + 5 files changed, 594 insertions(+), 395 deletions(-) create mode 100644 src/test/run-pass/task-stderr.rs diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 6c3ad8a6ef961..ee25d19e324cc 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -159,16 +159,19 @@ //! //! # Using a scheduler pool //! +//! This library adds a `GreenTaskBuilder` trait that extends the methods +//! available on `std::task::TaskBuilder` to allow spawning a green task, +//! possibly pinned to a particular scheduler thread: +//! //! ```rust -//! use std::rt::task::TaskOpts; -//! use green::{SchedPool, PoolConfig}; -//! use green::sched::{PinnedTask, TaskFromFriend}; +//! use std::task::TaskBuilder; +//! use green::{SchedPool, PoolConfig, GreenTaskBuilder}; //! //! let config = PoolConfig::new(); //! let mut pool = SchedPool::new(config); //! //! // Spawn tasks into the pool of schedulers -//! pool.spawn(TaskOpts::new(), proc() { +//! TaskBuilder::new().green(&mut pool).spawn(proc() { //! // this code is running inside the pool of schedulers //! //! spawn(proc() { @@ -181,12 +184,9 @@ //! let mut handle = pool.spawn_sched(); //! //! // Pin a task to the spawned scheduler -//! let task = pool.task(TaskOpts::new(), proc() { /* ... */ }); -//! handle.send(PinnedTask(task)); -//! -//! // Schedule a task on this new scheduler -//! let task = pool.task(TaskOpts::new(), proc() { /* ... */ }); -//! handle.send(TaskFromFriend(task)); +//! TaskBuilder::new().green_pinned(&mut pool, &mut handle).spawn(proc() { +//! /* ... */ +//! }); //! //! // Handles keep schedulers alive, so be sure to drop all handles before //! // destroying the sched pool @@ -209,6 +209,8 @@ // NB this does *not* include globs, please keep it that way. #![feature(macro_rules, phase)] #![allow(visible_private_types)] +#![allow(deprecated)] +#![feature(default_type_params)] #[cfg(test)] #[phase(plugin, link)] extern crate log; #[cfg(test)] extern crate rustuv; @@ -224,8 +226,9 @@ use std::rt::task::TaskOpts; use std::rt; use std::sync::atomics::{SeqCst, AtomicUint, INIT_ATOMIC_UINT}; use std::sync::deque; +use std::task::{TaskBuilder, Spawner}; -use sched::{Shutdown, Scheduler, SchedHandle, TaskFromFriend, NewNeighbor}; +use sched::{Shutdown, Scheduler, SchedHandle, TaskFromFriend, PinnedTask, NewNeighbor}; use sleeper_list::SleeperList; use stack::StackPool; use task::GreenTask; @@ -444,6 +447,7 @@ impl SchedPool { /// This is useful to create a task which can then be sent to a specific /// scheduler created by `spawn_sched` (and possibly pin it to that /// scheduler). + #[deprecated = "use the green and green_pinned methods of GreenTaskBuilder instead"] pub fn task(&mut self, opts: TaskOpts, f: proc():Send) -> Box { GreenTask::configure(&mut self.stack_pool, opts, f) } @@ -454,6 +458,7 @@ impl SchedPool { /// New tasks are spawned in a round-robin fashion to the schedulers in this /// pool, but tasks can certainly migrate among schedulers once they're in /// the pool. + #[deprecated = "use the green and green_pinned methods of GreenTaskBuilder instead"] pub fn spawn(&mut self, opts: TaskOpts, f: proc():Send) { let task = self.task(opts, f); @@ -563,3 +568,54 @@ impl Drop for SchedPool { } } } + +/// A spawner for green tasks +pub struct GreenSpawner<'a>{ + pool: &'a mut SchedPool, + handle: Option<&'a mut SchedHandle> +} + +impl<'a> Spawner for GreenSpawner<'a> { + #[inline] + fn spawn(self, opts: TaskOpts, f: proc():Send) { + let GreenSpawner { pool, handle } = self; + match handle { + None => pool.spawn(opts, f), + Some(h) => h.send(PinnedTask(pool.task(opts, f))) + } + } +} + +/// An extension trait adding `green` configuration methods to `TaskBuilder`. +pub trait GreenTaskBuilder { + fn green<'a>(self, &'a mut SchedPool) -> TaskBuilder>; + fn green_pinned<'a>(self, &'a mut SchedPool, &'a mut SchedHandle) + -> TaskBuilder>; +} + +impl GreenTaskBuilder for TaskBuilder { + fn green<'a>(self, pool: &'a mut SchedPool) -> TaskBuilder> { + self.spawner(GreenSpawner {pool: pool, handle: None}) + } + + fn green_pinned<'a>(self, pool: &'a mut SchedPool, handle: &'a mut SchedHandle) + -> TaskBuilder> { + self.spawner(GreenSpawner {pool: pool, handle: Some(handle)}) + } +} + +#[cfg(test)] +mod test { + use std::task::TaskBuilder; + use super::{SchedPool, PoolConfig, GreenTaskBuilder}; + + #[test] + fn test_green_builder() { + let mut pool = SchedPool::new(PoolConfig::new()); + let res = TaskBuilder::new().green(&mut pool).try(proc() { + "Success!".to_string() + }); + assert_eq!(res.ok().unwrap(), "Success!".to_string()); + pool.shutdown(); + } +} diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index f04dfac80ccfe..40b99c5bbdb1d 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -32,10 +32,13 @@ //! ```rust //! extern crate native; //! +//! use std::task::TaskBuilder; +//! use native::NativeTaskBuilder; +//! //! fn main() { //! // We're not sure whether this main function is run in 1:1 or M:N mode. //! -//! native::task::spawn(proc() { +//! TaskBuilder::new().native().spawn(proc() { //! // this code is guaranteed to be run on a native thread //! }); //! } @@ -50,7 +53,8 @@ html_root_url = "http://doc.rust-lang.org/")] #![deny(unused_result, unused_must_use)] #![allow(non_camel_case_types)] -#![feature(macro_rules)] +#![allow(deprecated)] +#![feature(default_type_params)] // NB this crate explicitly does *not* allow glob imports, please seriously // consider whether they're needed before adding that feature here (the @@ -65,6 +69,8 @@ use std::os; use std::rt; use std::str; +pub use task::NativeTaskBuilder; + pub mod io; pub mod task; diff --git a/src/libnative/task.rs b/src/libnative/task.rs index b073c2c7fbf02..88e581a479136 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -27,6 +27,7 @@ use std::rt; use io; use task; +use std::task::{TaskBuilder, Spawner}; /// Creates a new Task which is ready to execute as a 1:1 task. pub fn new(stack_bounds: (uint, uint)) -> Box { @@ -48,12 +49,14 @@ fn ops() -> Box { } /// Spawns a function with the default configuration +#[deprecated = "use the native method of NativeTaskBuilder instead"] pub fn spawn(f: proc():Send) { spawn_opts(TaskOpts { name: None, stack_size: None, on_exit: None }, f) } /// Spawns a new task given the configuration options and a procedure to run /// inside the task. +#[deprecated = "use the native method of NativeTaskBuilder instead"] pub fn spawn_opts(opts: TaskOpts, f: proc():Send) { let TaskOpts { name, stack_size, on_exit } = opts; @@ -95,6 +98,26 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) { }) } +/// A spawner for native tasks +pub struct NativeSpawner; + +impl Spawner for NativeSpawner { + fn spawn(self, opts: TaskOpts, f: proc():Send) { + spawn_opts(opts, f) + } +} + +/// An extension trait adding a `native` configuration method to `TaskBuilder`. +pub trait NativeTaskBuilder { + fn native(self) -> TaskBuilder; +} + +impl NativeTaskBuilder for TaskBuilder { + fn native(self) -> TaskBuilder { + self.spawner(NativeSpawner) + } +} + // This structure is the glue between channels and the 1:1 scheduling mode. This // structure is allocated once per task. struct Ops { @@ -259,7 +282,8 @@ mod tests { use std::rt::local::Local; use std::rt::task::{Task, TaskOpts}; use std::task; - use super::{spawn, spawn_opts, Ops}; + use std::task::TaskBuilder; + use super::{spawn, spawn_opts, Ops, NativeTaskBuilder}; #[test] fn smoke() { @@ -347,4 +371,12 @@ mod tests { }); rx.recv(); } + + #[test] + fn test_native_builder() { + let res = TaskBuilder::new().native().try(proc() { + "Success!".to_string() + }); + assert_eq!(res.ok().unwrap(), "Success!".to_string()); + } } diff --git a/src/libstd/task.rs b/src/libstd/task.rs index f543188af4295..0ead8fa6c0c83 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -8,71 +8,110 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * Utilities for managing and scheduling tasks - * - * An executing Rust program consists of a collection of tasks, each with their - * own stack, and sole ownership of their allocated heap data. Tasks communicate - * with each other using channels (see `std::comm` for more info about how - * communication works). - * - * Failure in one task does not propagate to any others (not to parent, not to - * child). Failure propagation is instead handled by using the channel send() - * and recv() methods which will fail if the other end has hung up already. - * - * Task Scheduling: - * - * By default, every task is created with the same "flavor" as the calling task. - * This flavor refers to the scheduling mode, with two possibilities currently - * being 1:1 and M:N modes. Green (M:N) tasks are cooperatively scheduled and - * native (1:1) tasks are scheduled by the OS kernel. - * - * # Example - * - * ```rust - * spawn(proc() { - * println!("Hello, World!"); - * }) - * ``` - */ +//! Utilities for managing and scheduling tasks +//! +//! An executing Rust program consists of a collection of lightweight tasks, +//! each with their own stack. Tasks communicate with each other using channels +//! (see `std::comm`) or other forms of synchronization (see `std::sync`) that +//! ensure data-race freedom. +//! +//! Failure in one task does immediately propagate to any others (not to parent, +//! not to child). Failure propagation is instead handled as part of task +//! synchronization. For example, the channel `send()` and `recv()` methods will +//! fail if the other end has hung up already. +//! +//! # Basic task scheduling +//! +//! By default, every task is created with the same "flavor" as the calling task. +//! This flavor refers to the scheduling mode, with two possibilities currently +//! being 1:1 and M:N modes. Green (M:N) tasks are cooperatively scheduled and +//! native (1:1) tasks are scheduled by the OS kernel. +//! +//! ## Example +//! +//! ```rust +//! spawn(proc() { +//! println!("Hello, World!"); +//! }) +//! ``` +//! +//! # Advanced task scheduling +//! +//! Task spawning can also be configured to use a particular scheduler, to +//! redirect the new task's output, or to yield a `future` representing the +//! task's final result. The configuration is established using the +//! `TaskBuilder` API: +//! +//! ## Example +//! +//! ```rust +//! extern crate green; +//! extern crate native; +//! +//! use std::task::TaskBuilder; +//! use green::{SchedPool, PoolConfig, GreenTaskBuilder}; +//! use native::NativeTaskBuilder; +//! +//! # fn main() { +//! // Create a green scheduler pool with the default configuration +//! let mut pool = SchedPool::new(PoolConfig::new()); +//! +//! // Spawn a task in the green pool +//! let mut fut_green = TaskBuilder::new().green(&mut pool).try_future(proc() { +//! /* ... */ +//! }); +//! +//! // Spawn a native task +//! let mut fut_native = TaskBuilder::new().native().try_future(proc() { +//! /* ... */ +//! }); +//! +//! // Wait for both tasks to finish, recording their outcome +//! let res_green = fut_green.unwrap(); +//! let res_native = fut_native.unwrap(); +//! +//! // Shut down the green scheduler pool +//! pool.shutdown(); +//! # } +//! ``` use any::Any; -use comm::{Sender, Receiver, channel}; +use comm::channel; use io::{Writer, stdio}; use kinds::{Send, marker}; use option::{None, Some, Option}; use owned::Box; -use result::{Result, Ok, Err}; +use result::Result; use rt::local::Local; use rt::task; use rt::task::Task; use str::{Str, SendStr, IntoMaybeOwned}; +use sync::Future; -#[cfg(test)] use any::AnyRefExt; -#[cfg(test)] use owned::AnyOwnExt; -#[cfg(test)] use result; -#[cfg(test)] use str::StrAllocating; -#[cfg(test)] use string::String; - -/// Task configuration options -pub struct TaskOpts { - /// Enable lifecycle notifications on the given channel - pub notify_chan: Option>, - /// A name for the task-to-be, for identification in failure messages - pub name: Option, - /// The size of the stack for the spawned task - pub stack_size: Option, - /// Task-local stdout - pub stdout: Option>, - /// Task-local stderr - pub stderr: Option>, +/// A means of spawning a task +pub trait Spawner { + /// Spawn a task, given low-level task options. + fn spawn(self, opts: task::TaskOpts, f: proc():Send); } -/** - * The task builder type. - * - * Provides detailed control over the properties and behavior of new tasks. - */ +/// The default task spawner, which spawns siblings to the current task. +pub struct SiblingSpawner; + +impl Spawner for SiblingSpawner { + fn spawn(self, opts: task::TaskOpts, f: proc():Send) { + // bind tb to provide type annotation + let tb: Option> = Local::try_take(); + match tb { + Some(t) => t.spawn_sibling(opts, f), + None => fail!("need a local task to spawn a sibling task"), + }; + } +} + +/// The task builder type. +/// +/// Provides detailed control over the properties and behavior of new tasks. + // NB: Builders are designed to be single-use because they do stateful // things that get weird when reusing - e.g. if you create a result future // it only applies to a single task, so then you have to maintain Some @@ -80,75 +119,102 @@ pub struct TaskOpts { // when you try to reuse the builder to spawn a new task. We'll just // sidestep that whole issue by making builders uncopyable and making // the run function move them in. -pub struct TaskBuilder { - /// Options to spawn the new task with - pub opts: TaskOpts, - gen_body: Option proc(): Send>, +pub struct TaskBuilder { + // A name for the task-to-be, for identification in failure messages + name: Option, + // The size of the stack for the spawned task + stack_size: Option, + // Task-local stdout + stdout: Option>, + // Task-local stderr + stderr: Option>, + // The mechanics of actually spawning the task (i.e.: green or native) + spawner: S, + // Optionally wrap the eventual task body + gen_body: Option proc():Send>, nocopy: marker::NoCopy, } -impl TaskBuilder { - /// Generate the base configuration for spawning a task, off of which more - /// configuration methods can be chained. - pub fn new() -> TaskBuilder { +impl TaskBuilder { + /// Generate the base configuration for spawning a task, off of which more + /// configuration methods can be chained. + pub fn new() -> TaskBuilder { TaskBuilder { - opts: TaskOpts::new(), + name: None, + stack_size: None, + stdout: None, + stderr: None, + spawner: SiblingSpawner, gen_body: None, nocopy: marker::NoCopy, } } +} - /// Get a future representing the exit status of the task. - /// - /// Taking the value of the future will block until the child task - /// terminates. The future result return value will be created *before* the task is - /// spawned; as such, do not invoke .get() on it directly; - /// rather, store it in an outer variable/list for later use. - /// - /// # Failure - /// Fails if a future_result was already set for this task. - pub fn future_result(&mut self) -> Receiver { - // FIXME (#3725): Once linked failure and notification are - // handled in the library, I can imagine implementing this by just - // registering an arbitrary number of task::on_exit handlers and - // sending out messages. - - if self.opts.notify_chan.is_some() { - fail!("Can't set multiple future_results for one task!"); - } - - // Construct the future and give it to the caller. - let (tx, rx) = channel(); +impl TaskBuilder { + /// Name the task-to-be. Currently the name is used for identification + /// only in failure messages. + pub fn named>(mut self, name: T) -> TaskBuilder { + self.name = Some(name.into_maybe_owned()); + self + } - // Reconfigure self to use a notify channel. - self.opts.notify_chan = Some(tx); + /// Set the size of the stack for the new task. + pub fn stack_size(mut self, size: uint) -> TaskBuilder { + self.stack_size = Some(size); + self + } - rx + /// Redirect task-local stdout. + pub fn stdout(mut self, stdout: Box) -> TaskBuilder { + self.stdout = Some(stdout); + self } - /// Name the task-to-be. Currently the name is used for identification - /// only in failure messages. - pub fn named>(mut self, name: S) -> TaskBuilder { - self.opts.name = Some(name.into_maybe_owned()); + /// Redirect task-local stderr. + pub fn stderr(mut self, stderr: Box) -> TaskBuilder { + self.stderr = Some(stderr); self } - /** - * Add a wrapper to the body of the spawned task. - * - * Before the task is spawned it is passed through a 'body generator' - * function that may perform local setup operations as well as wrap - * the task body in remote setup operations. With this the behavior - * of tasks can be extended in simple ways. - * - * This function augments the current body generator with a new body - * generator by applying the task body which results from the - * existing body generator to the new body generator. - */ - pub fn with_wrapper(mut self, - wrapper: proc(v: proc(): Send): Send -> proc(): Send) - -> TaskBuilder - { + /// Set the spawning mechanism for the task. + /// + /// The `TaskBuilder` API configures a task to be spawned, but defers to the + /// "spawner" to actually create and spawn the task. The `spawner` method + /// should not be called directly by `TaskBuiler` clients. It is intended + /// for use by downstream crates (like `native` and `green`) that implement + /// tasks. These downstream crates then add extension methods to the + /// builder, like `.native()` and `.green(pool)`, that actually set the + /// spawner. + pub fn spawner(self, spawner: T) -> TaskBuilder { + // repackage the entire TaskBuilder since its type is changing. + let TaskBuilder { + name, stack_size, stdout, stderr, spawner: _, gen_body, nocopy + } = self; + TaskBuilder { + name: name, + stack_size: stack_size, + stdout: stdout, + stderr: stderr, + spawner: spawner, + gen_body: gen_body, + nocopy: nocopy, + } + } + + /// Add a wrapper to the body of the spawned task. + /// + /// Before the task is spawned it is passed through a 'body generator' + /// function that may perform local setup operations as well as wrap + /// the task body in remote setup operations. With this the behavior + /// of tasks can be extended in simple ways. + /// + /// This function augments the current body generator with a new body + /// generator by applying the task body which results from the + /// existing body generator to the new body generator. + #[deprecated = "this function will be removed soon"] + pub fn with_wrapper(mut self, wrapper: proc(v: proc():Send):Send -> proc():Send) + -> TaskBuilder { self.gen_body = match self.gen_body.take() { Some(prev) => Some(proc(body) { wrapper(prev(body)) }), None => Some(wrapper) @@ -156,90 +222,80 @@ impl TaskBuilder { self } - /** - * Creates and executes a new child task - * - * Sets up a new task with its own call stack and schedules it to run - * the provided unique closure. The task has the properties and behavior - * specified by the task_builder. - */ - pub fn spawn(mut self, f: proc(): Send) { - let gen_body = self.gen_body.take(); - let f = match gen_body { + // Where spawning actually happens (whether yielding a future or not) + fn spawn_internal(self, f: proc():Send, + on_exit: Option>):Send>) { + let TaskBuilder { + name, stack_size, stdout, stderr, spawner, mut gen_body, nocopy: _ + } = self; + let f = match gen_body.take() { Some(gen) => gen(f), None => f }; - let t: Box = match Local::try_take() { - Some(t) => t, - None => fail!("need a local task to spawn a new task"), - }; - let TaskOpts { notify_chan, name, stack_size, stdout, stderr } = self.opts; - let opts = task::TaskOpts { - on_exit: notify_chan.map(|c| proc(r) c.send(r)), + on_exit: on_exit, name: name, stack_size: stack_size, }; if stdout.is_some() || stderr.is_some() { - t.spawn_sibling(opts, proc() { + spawner.spawn(opts, proc() { let _ = stdout.map(stdio::set_stdout); let _ = stderr.map(stdio::set_stderr); f(); - }); + }) } else { - t.spawn_sibling(opts, f); + spawner.spawn(opts, f) } } - /** - * Execute a function in another task and return either the return value - * of the function or result::err. - * - * # Return value - * - * If the function executed successfully then try returns result::ok - * containing the value returned by the function. If the function fails - * then try returns result::err containing nil. - * - * # Failure - * Fails if a future_result was already set for this task. - */ - pub fn try(mut self, f: proc(): Send -> T) - -> Result> { - let (tx, rx) = channel(); - - let result = self.future_result(); - - self.spawn(proc() { - tx.send(f()); - }); - - match result.recv() { - Ok(()) => Ok(rx.recv()), - Err(cause) => Err(cause) - } + /// Creates and executes a new child task. + /// + /// Sets up a new task with its own call stack and schedules it to run + /// the provided proc. The task has the properties and behavior + /// specified by the `TaskBuilder`. + pub fn spawn(self, f: proc():Send) { + self.spawn_internal(f, None) } -} - -/* Task construction */ -impl TaskOpts { - pub fn new() -> TaskOpts { - /*! - * The default task options - */ + /// Execute a proc in a newly-spawned task and return a future representing + /// the task's result. The task has the properties and behavior + /// specified by the `TaskBuilder`. + /// + /// Taking the value of the future will block until the child task + /// terminates. + /// + /// # Return value + /// + /// If the child task executes successfully (without failing) then the + /// future returns `result::Ok` containing the value returned by the + /// function. If the child task fails then the future returns `result::Err` + /// containing the argument to `fail!(...)` as an `Any` trait object. + pub fn try_future(self, f: proc():Send -> T) + -> Future>> { + // currently, the on_exit proc provided by librustrt only works for unit + // results, so we use an additional side-channel to communicate the + // result. + + let (tx_done, rx_done) = channel(); // signal that task has exited + let (tx_retv, rx_retv) = channel(); // return value from task + + let on_exit = proc(res) { tx_done.send(res) }; + self.spawn_internal(proc() { tx_retv.send(f()) }, + Some(on_exit)); + + Future::from_fn(proc() { + rx_done.recv().map(|_| rx_retv.recv()) + }) + } - TaskOpts { - notify_chan: None, - name: None, - stack_size: None, - stdout: None, - stderr: None, - } + /// Execute a function in a newly-spawnedtask and block until the task + /// completes or fails. Equivalent to `.try_future(f).unwrap()`. + pub fn try(self, f: proc():Send -> T) -> Result> { + self.try_future(f).unwrap() } } -/* Spawn convenience functions */ +/* Convenience functions */ /// Creates and executes a new child task /// @@ -251,14 +307,22 @@ pub fn spawn(f: proc(): Send) { TaskBuilder::new().spawn(f) } -/// Execute a function in another task and return either the return value of -/// the function or an error if the task failed +/// Execute a function in a newly-spawned task and return either the return +/// value of the function or an error if the task failed. /// -/// This is equivalent to TaskBuilder::new().try +/// This is equivalent to `TaskBuilder::new().try`. pub fn try(f: proc(): Send -> T) -> Result> { TaskBuilder::new().try(f) } +/// Execute a function in another task and return a future representing the +/// task's result. +/// +/// This is equivalent to `TaskBuilder::new().try_future`. +pub fn try_future(f: proc():Send -> T) -> Future>> { + TaskBuilder::new().try_future(f) +} + /* Lifecycle functions */ @@ -273,9 +337,8 @@ pub fn with_task_name(blk: |Option<&str>| -> U) -> U { } } +/// Yield control to the task scheduler. pub fn deschedule() { - //! Yield control to the task scheduler - use rt::local::Local; // FIXME(#7544): Optimize this, since we know we won't block. @@ -283,266 +346,282 @@ pub fn deschedule() { task.yield_now(); } +/// True if the running task is currently failing (e.g. will return `true` inside a +/// destructor that is run while unwinding the stack after a call to `fail!()`). pub fn failing() -> bool { - //! True if the running task has failed use rt::task::Task; Local::borrow(None::).unwinder.unwinding() } -// The following 8 tests test the following 2^3 combinations: -// {un,}linked {un,}supervised failure propagation {up,down}wards. - -// !!! These tests are dangerous. If Something is buggy, they will hang, !!! -// !!! instead of exiting cleanly. This might wedge the buildbots. !!! - -#[test] -fn test_unnamed_task() { - spawn(proc() { - with_task_name(|name| { - assert!(name.is_none()); +#[cfg(test)] +mod test { + use any::{Any, AnyRefExt}; + use owned::AnyOwnExt; + use result; + use result::{Ok, Err}; + use str::StrAllocating; + use string::String; + use std::io::{ChanReader, ChanWriter}; + use prelude::*; + use super::*; + + // !!! These tests are dangerous. If something is buggy, they will hang, !!! + // !!! instead of exiting cleanly. This might wedge the buildbots. !!! + + #[test] + fn test_unnamed_task() { + spawn(proc() { + with_task_name(|name| { + assert!(name.is_none()); + }) }) - }) -} + } -#[test] -fn test_owned_named_task() { - TaskBuilder::new().named("ada lovelace".to_string()).spawn(proc() { - with_task_name(|name| { - assert!(name.unwrap() == "ada lovelace"); + #[test] + fn test_owned_named_task() { + TaskBuilder::new().named("ada lovelace".to_string()).spawn(proc() { + with_task_name(|name| { + assert!(name.unwrap() == "ada lovelace"); + }) }) - }) -} + } -#[test] -fn test_static_named_task() { - TaskBuilder::new().named("ada lovelace").spawn(proc() { - with_task_name(|name| { - assert!(name.unwrap() == "ada lovelace"); + #[test] + fn test_static_named_task() { + TaskBuilder::new().named("ada lovelace").spawn(proc() { + with_task_name(|name| { + assert!(name.unwrap() == "ada lovelace"); + }) }) - }) -} + } -#[test] -fn test_send_named_task() { - TaskBuilder::new().named("ada lovelace".into_maybe_owned()).spawn(proc() { - with_task_name(|name| { - assert!(name.unwrap() == "ada lovelace"); + #[test] + fn test_send_named_task() { + TaskBuilder::new().named("ada lovelace".into_maybe_owned()).spawn(proc() { + with_task_name(|name| { + assert!(name.unwrap() == "ada lovelace"); + }) }) - }) -} - -#[test] -fn test_run_basic() { - let (tx, rx) = channel(); - TaskBuilder::new().spawn(proc() { - tx.send(()); - }); - rx.recv(); -} + } -#[test] -fn test_with_wrapper() { - let (tx, rx) = channel(); - TaskBuilder::new().with_wrapper(proc(body) { - let result: proc(): Send = proc() { - body(); + #[test] + fn test_run_basic() { + let (tx, rx) = channel(); + TaskBuilder::new().spawn(proc() { tx.send(()); - }; - result - }).spawn(proc() { }); - rx.recv(); -} + }); + rx.recv(); + } -#[test] -fn test_future_result() { - let mut builder = TaskBuilder::new(); - let result = builder.future_result(); - builder.spawn(proc() {}); - assert!(result.recv().is_ok()); - - let mut builder = TaskBuilder::new(); - let result = builder.future_result(); - builder.spawn(proc() { - fail!(); - }); - assert!(result.recv().is_err()); -} + #[test] + fn test_with_wrapper() { + let (tx, rx) = channel(); + TaskBuilder::new().with_wrapper(proc(body) { + let result: proc():Send = proc() { + body(); + tx.send(()); + }; + result + }).spawn(proc() { }); + rx.recv(); + } -#[test] #[should_fail] -fn test_back_to_the_future_result() { - let mut builder = TaskBuilder::new(); - builder.future_result(); - builder.future_result(); -} + #[test] + fn test_try_future() { + let result = TaskBuilder::new().try_future(proc() {}); + assert!(result.unwrap().is_ok()); -#[test] -fn test_try_success() { - match try(proc() { - "Success!".to_string() - }).as_ref().map(|s| s.as_slice()) { - result::Ok("Success!") => (), - _ => fail!() + let result = TaskBuilder::new().try_future(proc() -> () { + fail!(); + }); + assert!(result.unwrap().is_err()); } -} -#[test] -fn test_try_fail() { - match try(proc() { - fail!() - }) { - result::Err(_) => (), - result::Ok(()) => fail!() + #[test] + fn test_try_success() { + match try(proc() { + "Success!".to_string() + }).as_ref().map(|s| s.as_slice()) { + result::Ok("Success!") => (), + _ => fail!() + } } -} -#[test] -fn test_spawn_sched() { - use clone::Clone; + #[test] + fn test_try_fail() { + match try(proc() { + fail!() + }) { + result::Err(_) => (), + result::Ok(()) => fail!() + } + } - let (tx, rx) = channel(); + #[test] + fn test_spawn_sched() { + use clone::Clone; - fn f(i: int, tx: Sender<()>) { - let tx = tx.clone(); - spawn(proc() { - if i == 0 { - tx.send(()); - } else { - f(i - 1, tx); - } - }); + let (tx, rx) = channel(); + fn f(i: int, tx: Sender<()>) { + let tx = tx.clone(); + spawn(proc() { + if i == 0 { + tx.send(()); + } else { + f(i - 1, tx); + } + }); + + } + f(10, tx); + rx.recv(); } - f(10, tx); - rx.recv(); -} -#[test] -fn test_spawn_sched_childs_on_default_sched() { - let (tx, rx) = channel(); + #[test] + fn test_spawn_sched_childs_on_default_sched() { + let (tx, rx) = channel(); - spawn(proc() { spawn(proc() { - tx.send(()); + spawn(proc() { + tx.send(()); + }); }); - }); - rx.recv(); -} + rx.recv(); + } -#[cfg(test)] -fn avoid_copying_the_body(spawnfn: |v: proc(): Send|) { - let (tx, rx) = channel::(); + fn avoid_copying_the_body(spawnfn: |v: proc():Send|) { + let (tx, rx) = channel::(); - let x = box 1; - let x_in_parent = (&*x) as *int as uint; + let x = box 1; + let x_in_parent = (&*x) as *int as uint; - spawnfn(proc() { - let x_in_child = (&*x) as *int as uint; - tx.send(x_in_child); - }); + spawnfn(proc() { + let x_in_child = (&*x) as *int as uint; + tx.send(x_in_child); + }); - let x_in_child = rx.recv(); - assert_eq!(x_in_parent, x_in_child); -} + let x_in_child = rx.recv(); + assert_eq!(x_in_parent, x_in_child); + } -#[test] -fn test_avoid_copying_the_body_spawn() { - avoid_copying_the_body(spawn); -} + #[test] + fn test_avoid_copying_the_body_spawn() { + avoid_copying_the_body(spawn); + } -#[test] -fn test_avoid_copying_the_body_task_spawn() { - avoid_copying_the_body(|f| { - let builder = TaskBuilder::new(); - builder.spawn(proc() { - f(); - }); - }) -} + #[test] + fn test_avoid_copying_the_body_task_spawn() { + avoid_copying_the_body(|f| { + let builder = TaskBuilder::new(); + builder.spawn(proc() { + f(); + }); + }) + } -#[test] -fn test_avoid_copying_the_body_try() { - avoid_copying_the_body(|f| { - let _ = try(proc() { - f() - }); - }) -} + #[test] + fn test_avoid_copying_the_body_try() { + avoid_copying_the_body(|f| { + let _ = try(proc() { + f() + }); + }) + } -#[test] -fn test_child_doesnt_ref_parent() { - // If the child refcounts the parent task, this will stack overflow when - // climbing the task tree to dereference each ancestor. (See #1789) - // (well, it would if the constant were 8000+ - I lowered it to be more - // valgrind-friendly. try this at home, instead..!) - static generations: uint = 16; - fn child_no(x: uint) -> proc(): Send { - return proc() { - if x < generations { - TaskBuilder::new().spawn(child_no(x+1)); + #[test] + fn test_child_doesnt_ref_parent() { + // If the child refcounts the parent task, this will stack overflow when + // climbing the task tree to dereference each ancestor. (See #1789) + // (well, it would if the constant were 8000+ - I lowered it to be more + // valgrind-friendly. try this at home, instead..!) + static generations: uint = 16; + fn child_no(x: uint) -> proc(): Send { + return proc() { + if x < generations { + TaskBuilder::new().spawn(child_no(x+1)); + } } } + TaskBuilder::new().spawn(child_no(0)); } - TaskBuilder::new().spawn(child_no(0)); -} -#[test] -fn test_simple_newsched_spawn() { - spawn(proc()()) -} + #[test] + fn test_simple_newsched_spawn() { + spawn(proc()()) + } -#[test] -fn test_try_fail_message_static_str() { - match try(proc() { - fail!("static string"); - }) { - Err(e) => { - type T = &'static str; - assert!(e.is::()); - assert_eq!(*e.move::().unwrap(), "static string"); + #[test] + fn test_try_fail_message_static_str() { + match try(proc() { + fail!("static string"); + }) { + Err(e) => { + type T = &'static str; + assert!(e.is::()); + assert_eq!(*e.move::().unwrap(), "static string"); + } + Ok(()) => fail!() } - Ok(()) => fail!() } -} -#[test] -fn test_try_fail_message_owned_str() { - match try(proc() { - fail!("owned string".to_string()); - }) { - Err(e) => { - type T = String; - assert!(e.is::()); - assert_eq!(*e.move::().unwrap(), "owned string".to_string()); + #[test] + fn test_try_fail_message_owned_str() { + match try(proc() { + fail!("owned string".to_string()); + }) { + Err(e) => { + type T = String; + assert!(e.is::()); + assert_eq!(*e.move::().unwrap(), "owned string".to_string()); + } + Ok(()) => fail!() } - Ok(()) => fail!() } -} -#[test] -fn test_try_fail_message_any() { - match try(proc() { - fail!(box 413u16 as Box); - }) { - Err(e) => { - type T = Box; - assert!(e.is::()); - let any = e.move::().unwrap(); - assert!(any.is::()); - assert_eq!(*any.move::().unwrap(), 413u16); + #[test] + fn test_try_fail_message_any() { + match try(proc() { + fail!(box 413u16 as Box); + }) { + Err(e) => { + type T = Box; + assert!(e.is::()); + let any = e.move::().unwrap(); + assert!(any.is::()); + assert_eq!(*any.move::().unwrap(), 413u16); + } + Ok(()) => fail!() } - Ok(()) => fail!() } -} -#[test] -fn test_try_fail_message_unit_struct() { - struct Juju; + #[test] + fn test_try_fail_message_unit_struct() { + struct Juju; + + match try(proc() { + fail!(Juju) + }) { + Err(ref e) if e.is::() => {} + Err(_) | Ok(()) => fail!() + } + } + + #[test] + fn test_stdout() { + let (tx, rx) = channel(); + let mut reader = ChanReader::new(rx); + let stdout = ChanWriter::new(tx); + + TaskBuilder::new().stdout(box stdout as Box).try(proc() { + print!("Hello, world!"); + }).unwrap(); - match try(proc() { - fail!(Juju) - }) { - Err(ref e) if e.is::() => {} - Err(_) | Ok(()) => fail!() + let output = reader.read_to_str().unwrap(); + assert_eq!(output, "Hello, world!".to_string()); } + + // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due + // to the test harness apparently interfering with stderr configuration. } diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs new file mode 100644 index 0000000000000..b3cbdb3c4c382 --- /dev/null +++ b/src/test/run-pass/task-stderr.rs @@ -0,0 +1,26 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io::{ChanReader, ChanWriter}; +use std::task::build; + +fn main() { + let (tx, rx) = channel(); + let mut reader = ChanReader::new(rx); + let stderr = ChanWriter::new(tx); + + let res = build().stderr(box stderr as Box).try(proc() -> () { + fail!("Hello, world!") + }); + assert!(res.is_err()); + + let output = reader.read_to_str().unwrap(); + assert!(output.as_slice().contains("Hello, world!")); +} From f99349556014f9f2cb86814477248d46931b3048 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 16 Jun 2014 16:17:59 -0700 Subject: [PATCH 14/25] Fallout from TaskBuilder changes This commit brings code downstream of libstd up to date with the new TaskBuilder API. --- src/librustc/driver/mod.rs | 17 +++++++---------- src/libsync/lock.rs | 10 ++++------ src/libtest/lib.rs | 9 ++++----- src/test/bench/msgsend-pipes-shared.rs | 11 ++++------- src/test/bench/msgsend-pipes.rs | 17 ++++++----------- src/test/bench/shootout-pfib.rs | 11 ++++------- src/test/run-pass/issue-2190-1.rs | 4 +--- src/test/run-pass/task-comm-12.rs | 7 ++----- src/test/run-pass/task-comm-3.rs | 10 ++++------ src/test/run-pass/task-comm-9.rs | 8 +++----- src/test/run-pass/task-stderr.rs | 4 ++-- src/test/run-pass/tcp-stress.rs | 4 +--- src/test/run-pass/yield.rs | 7 ++----- src/test/run-pass/yield1.rs | 7 ++----- 14 files changed, 46 insertions(+), 80 deletions(-) diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index ada65394e1923..f55fd78762c5d 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -366,22 +366,19 @@ fn monitor(f: proc():Send) { #[cfg(not(rtopt))] static STACK_SIZE: uint = 20000000; // 20MB - let mut task_builder = TaskBuilder::new().named("rustc"); + let (tx, rx) = channel(); + let w = io::ChanWriter::new(tx); + let mut r = io::ChanReader::new(rx); + + let mut task = TaskBuilder::new().named("rustc").stderr(box w); // FIXME: Hacks on hacks. If the env is trying to override the stack size // then *don't* set it explicitly. if os::getenv("RUST_MIN_STACK").is_none() { - task_builder.opts.stack_size = Some(STACK_SIZE); + task = task.stack_size(STACK_SIZE); } - let (tx, rx) = channel(); - let w = io::ChanWriter::new(tx); - let mut r = io::ChanReader::new(rx); - - match task_builder.try(proc() { - io::stdio::set_stderr(box w); - f() - }) { + match task.try(f) { Ok(()) => { /* fallthrough */ } Err(value) => { // Task failed without emitting a fatal diagnostic diff --git a/src/libsync/lock.rs b/src/libsync/lock.rs index d7990068d5eb7..1fe8e8fc0db34 100644 --- a/src/libsync/lock.rs +++ b/src/libsync/lock.rs @@ -459,7 +459,7 @@ mod tests { use std::prelude::*; use std::comm::Empty; use std::task; - use std::task::TaskBuilder; + use std::task::try_future; use Arc; use super::{Mutex, Barrier, RWLock}; @@ -629,17 +629,15 @@ mod tests { let mut children = Vec::new(); for _ in range(0, 5) { let arc3 = arc.clone(); - let mut builder = TaskBuilder::new(); - children.push(builder.future_result()); - builder.spawn(proc() { + children.push(try_future(proc() { let lock = arc3.read(); assert!(*lock >= 0); - }); + })); } // Wait for children to pass their asserts for r in children.mut_iter() { - assert!(r.recv().is_ok()); + assert!(r.get_ref().is_ok()); } // Wait for writer to finish diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index e7c35fb59eee5..112ffd7c1a4a4 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1049,14 +1049,13 @@ pub fn run_test(opts: &TestOpts, if nocapture { drop((stdout, stderr)); } else { - task.opts.stdout = Some(box stdout as Box); - task.opts.stderr = Some(box stderr as Box); + task = task.stdout(box stdout as Box); + task = task.stderr(box stderr as Box); } - let result_future = task.future_result(); - task.spawn(testfn); + let result_future = task.try_future(testfn); let stdout = reader.read_to_end().unwrap().move_iter().collect(); - let task_result = result_future.recv(); + let task_result = result_future.unwrap(); let test_result = calc_result(&desc, task_result.is_ok()); monitor_ch.send((desc.clone(), test_result, stdout)); }) diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index 03d91cf3aaa7a..14155d54d73cc 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -24,7 +24,6 @@ extern crate debug; use std::comm; use std::os; use std::task; -use std::task::TaskBuilder; use std::uint; fn move_out(_x: T) {} @@ -64,22 +63,20 @@ fn run(args: &[String]) { let mut worker_results = Vec::new(); for _ in range(0u, workers) { let to_child = to_child.clone(); - let mut builder = TaskBuilder::new(); - worker_results.push(builder.future_result()); - builder.spawn(proc() { + worker_results.push(task::try_future(proc() { for _ in range(0u, size / workers) { //println!("worker {:?}: sending {:?} bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //println!("worker {:?} exiting", i); - }); + })); } task::spawn(proc() { server(&from_parent, &to_parent); }); - for r in worker_results.iter() { - r.recv(); + for r in worker_results.move_iter() { + r.unwrap(); } //println!("sending stop message"); diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index 4de51c3ab4b8e..7ec2796b230a7 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -19,7 +19,6 @@ extern crate debug; use std::os; use std::task; -use std::task::TaskBuilder; use std::uint; fn move_out(_x: T) {} @@ -58,29 +57,25 @@ fn run(args: &[String]) { let mut worker_results = Vec::new(); let from_parent = if workers == 1 { let (to_child, from_parent) = channel(); - let mut builder = TaskBuilder::new(); - worker_results.push(builder.future_result()); - builder.spawn(proc() { + worker_results.push(task::try_future(proc() { for _ in range(0u, size / workers) { //println!("worker {:?}: sending {:?} bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //println!("worker {:?} exiting", i); - }); + })); from_parent } else { let (to_child, from_parent) = channel(); for _ in range(0u, workers) { let to_child = to_child.clone(); - let mut builder = TaskBuilder::new(); - worker_results.push(builder.future_result()); - builder.spawn(proc() { + worker_results.push(task::try_future(proc() { for _ in range(0u, size / workers) { //println!("worker {:?}: sending {:?} bytes", i, num_bytes); to_child.send(bytes(num_bytes)); } //println!("worker {:?} exiting", i); - }); + })); } from_parent }; @@ -88,8 +83,8 @@ fn run(args: &[String]) { server(&from_parent, &to_parent); }); - for r in worker_results.iter() { - r.recv(); + for r in worker_results.move_iter() { + r.unwrap(); } //println!("sending stop message"); diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index 33853a91b7608..57a6d0e7c523d 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -24,7 +24,6 @@ extern crate time; use std::os; use std::result::{Ok, Err}; use std::task; -use std::task::TaskBuilder; use std::uint; fn fib(n: int) -> int { @@ -79,14 +78,12 @@ fn stress_task(id: int) { fn stress(num_tasks: int) { let mut results = Vec::new(); for i in range(0, num_tasks) { - let mut builder = TaskBuilder::new(); - results.push(builder.future_result()); - builder.spawn(proc() { + results.push(task::try_future(proc() { stress_task(i); - }); + })); } - for r in results.iter() { - r.recv(); + for r in results.move_iter() { + r.unwrap(); } } diff --git a/src/test/run-pass/issue-2190-1.rs b/src/test/run-pass/issue-2190-1.rs index f1217be3484fe..4ff735708b5ab 100644 --- a/src/test/run-pass/issue-2190-1.rs +++ b/src/test/run-pass/issue-2190-1.rs @@ -13,9 +13,7 @@ use std::task::TaskBuilder; static generations: uint = 1024+256+128+49; fn spawn(f: proc():Send) { - let mut t = TaskBuilder::new(); - t.opts.stack_size = Some(32 * 1024); - t.spawn(f); + TaskBuilder::new().stack_size(32 * 1024).spawn(f) } fn child_no(x: uint) -> proc():Send { diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index a78bbefed44db..851f87adfc20d 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::task; -use std::task::TaskBuilder; pub fn main() { test00(); } @@ -17,9 +16,7 @@ fn start(_task_number: int) { println!("Started / Finished task."); } fn test00() { let i: int = 0; - let mut builder = TaskBuilder::new(); - let mut result = builder.future_result(); - builder.spawn(proc() { + let mut result = task::try_future(proc() { start(i) }); @@ -31,7 +28,7 @@ fn test00() { } // Try joining tasks that have already finished. - result.recv(); + result.unwrap(); println!("Joined task."); } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 217bab5c1dea6..cd31d15db1092 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -10,7 +10,7 @@ extern crate debug; -use std::task::TaskBuilder; +use std::task; pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } @@ -39,14 +39,12 @@ fn test00() { let mut results = Vec::new(); while i < number_of_tasks { let tx = tx.clone(); - let mut builder = TaskBuilder::new(); - results.push(builder.future_result()); - builder.spawn({ + results.push(task::try_future({ let i = i; proc() { test00_start(&tx, i, number_of_messages) } - }); + })); i = i + 1; } @@ -62,7 +60,7 @@ fn test00() { } // Join spawned tasks... - for r in results.iter() { r.recv(); } + for r in results.mut_iter() { r.get_ref(); } println!("Completed: Final number is: "); println!("{:?}", sum); diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index ab6498c00279b..a46b4513c5dee 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -10,7 +10,7 @@ extern crate debug; -use std::task::TaskBuilder; +use std::task; pub fn main() { test00(); } @@ -25,9 +25,7 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: int = 10; - let mut builder = TaskBuilder::new(); - let result = builder.future_result(); - builder.spawn(proc() { + let result = task::try_future(proc() { test00_start(&tx, number_of_messages); }); @@ -38,7 +36,7 @@ fn test00() { i += 1; } - result.recv(); + result.unwrap(); assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index b3cbdb3c4c382..6a71f9df6e45e 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -9,14 +9,14 @@ // except according to those terms. use std::io::{ChanReader, ChanWriter}; -use std::task::build; +use std::task::TaskBuilder; fn main() { let (tx, rx) = channel(); let mut reader = ChanReader::new(rx); let stderr = ChanWriter::new(tx); - let res = build().stderr(box stderr as Box).try(proc() -> () { + let res = TaskBuilder::new().stderr(box stderr as Box).try(proc() -> () { fail!("Hello, world!") }); assert!(res.is_err()); diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index 9c4716e5f4d38..99bf247229e05 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -60,9 +60,7 @@ fn main() { let (tx, rx) = channel(); for _ in range(0, 1000) { let tx = tx.clone(); - let mut builder = TaskBuilder::new(); - builder.opts.stack_size = Some(64 * 1024); - builder.spawn(proc() { + TaskBuilder::new().stack_size(64 * 1024).spawn(proc() { let host = addr.ip.to_str(); let port = addr.port; match TcpStream::connect(host.as_slice(), port) { diff --git a/src/test/run-pass/yield.rs b/src/test/run-pass/yield.rs index 2662a6c6568b9..89d204dcecbdb 100644 --- a/src/test/run-pass/yield.rs +++ b/src/test/run-pass/yield.rs @@ -9,18 +9,15 @@ // except according to those terms. use std::task; -use std::task::TaskBuilder; pub fn main() { - let mut builder = TaskBuilder::new(); - let mut result = builder.future_result(); - builder.spawn(child); + let mut result = task::try_future(child); println!("1"); task::deschedule(); println!("2"); task::deschedule(); println!("3"); - result.recv(); + result.unwrap(); } fn child() { diff --git a/src/test/run-pass/yield1.rs b/src/test/run-pass/yield1.rs index 8c5504725bb48..d882b1abd295d 100644 --- a/src/test/run-pass/yield1.rs +++ b/src/test/run-pass/yield1.rs @@ -9,15 +9,12 @@ // except according to those terms. use std::task; -use std::task::TaskBuilder; pub fn main() { - let mut builder = TaskBuilder::new(); - let mut result = builder.future_result(); - builder.spawn(child); + let mut result = task::try_future(child); println!("1"); task::deschedule(); - result.recv(); + result.unwrap(); } fn child() { println!("2"); } From 90f7e3a644c9795d9a7dce87d8c6b0cf369a7503 Mon Sep 17 00:00:00 2001 From: Cameron Zwarich Date: Wed, 18 Jun 2014 00:06:39 -0700 Subject: [PATCH 15/25] Reject double moves out of array elements Fixes #14986. --- src/librustc/middle/borrowck/move_data.rs | 32 ++++++++++++++++--- .../borrowck-array-double-move.rs | 21 ++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/borrowck-array-double-move.rs diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index bb92043b1ea6a..9c2194c74f4a4 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -25,6 +25,7 @@ use middle::dataflow::DataFlowContext; use middle::dataflow::BitwiseOperator; use middle::dataflow::DataFlowOperator; use euv = middle::expr_use_visitor; +use mc = middle::mem_categorization; use middle::ty; use syntax::ast; use syntax::ast_util; @@ -160,6 +161,22 @@ pub struct AssignDataFlowOperator; pub type AssignDataFlow<'a> = DataFlowContext<'a, AssignDataFlowOperator>; +fn loan_path_is_precise(loan_path: &LoanPath) -> bool { + match *loan_path { + LpVar(_) => { + true + } + LpExtend(_, _, LpInterior(mc::InteriorElement(_))) => { + // Paths involving element accesses do not refer to a unique + // location, as there is no accurate tracking of the indices. + false + } + LpExtend(ref lp_base, _, _) => { + loan_path_is_precise(&**lp_base) + } + } +} + impl MoveData { pub fn new() -> MoveData { MoveData { @@ -500,10 +517,17 @@ impl MoveData { path: MovePathIndex, kill_id: ast::NodeId, dfcx_moves: &mut MoveDataFlow) { - self.each_applicable_move(path, |move_index| { - dfcx_moves.add_kill(kill_id, move_index.get()); - true - }); + // We can only perform kills for paths that refer to a unique location, + // since otherwise we may kill a move from one location with an + // assignment referring to another location. + + let loan_path = self.path_loan_path(path); + if loan_path_is_precise(&*loan_path) { + self.each_applicable_move(path, |move_index| { + dfcx_moves.add_kill(kill_id, move_index.get()); + true + }); + } } } diff --git a/src/test/compile-fail/borrowck-array-double-move.rs b/src/test/compile-fail/borrowck-array-double-move.rs new file mode 100644 index 0000000000000..c7fb646f585b9 --- /dev/null +++ b/src/test/compile-fail/borrowck-array-double-move.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() { + let mut a = [box 0, box 1]; + drop(a[0]); + a[1] = box 2; + drop(a[0]); //~ ERROR use of moved value: `a[..]` +} + +fn main() { + f(); +} + From 31dfcf9dc1e449fbf084485a1dc196695cab680e Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Wed, 18 Jun 2014 17:39:18 +1000 Subject: [PATCH 16/25] Vim: highlight escapes for byte literals. --- src/etc/vim/syntax/rust.vim | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 77348335eb346..b7901277ada17 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -145,11 +145,13 @@ syn match rustOperator display "&&\|||" syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustFail syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustFail -syn match rustSpecialError display contained /\\./ -syn match rustSpecial display contained /\\\([nrt0\\'"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)/ +syn match rustEscapeError display contained /\\./ +syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/ +syn match rustEscapeUnicode display contained /\\\(u\x\{4}\|U\x\{8}\)/ syn match rustStringContinuation display contained /\\\n\s*/ -syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustSpecial,rustSpecialError,rustStringContinuation,@Spell -syn region rustString start='r\z(#*\)"' end='"\z1' contains=@Spell +syn region rustString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation +syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell +syn region rustString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell syn region rustAttribute start="#!\?\[" end="\]" contains=rustString,rustDeriving syn region rustDeriving start="deriving(" end=")" contained contains=rustTrait @@ -177,7 +179,8 @@ syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[ "rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" -syn match rustCharacter /'\([^'\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'/ contains=rustSpecial,rustSpecialError +syn match rustCharacter /b'\([^'\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError +syn match rustCharacter /'\([^'\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell @@ -215,8 +218,9 @@ hi def link rustIdentifierPrime rustIdentifier hi def link rustTrait rustType hi def link rustSigil StorageClass -hi def link rustSpecial Special -hi def link rustSpecialError Error +hi def link rustEscape Special +hi def link rustEscapeUnicode rustEscape +hi def link rustEscapeError Error hi def link rustStringContinuation Special hi def link rustString String hi def link rustCharacter Character From b0dff7a19142b7d52d80ed62a14c1a6cb07cb647 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Wed, 18 Jun 2014 19:58:04 +1000 Subject: [PATCH 17/25] Vim: highlight invalid characters in char literals. --- src/etc/vim/syntax/rust.vim | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index b7901277ada17..a0488cdb05ab4 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -179,8 +179,11 @@ syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[ "rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" -syn match rustCharacter /b'\([^'\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError -syn match rustCharacter /'\([^'\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError +syn match rustCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/ +" The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII). +syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/ +syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode +syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell @@ -223,6 +226,8 @@ hi def link rustEscapeUnicode rustEscape hi def link rustEscapeError Error hi def link rustStringContinuation Special hi def link rustString String +hi def link rustCharacterInvalid Error +hi def link rustCharacterInvalidUnicode rustCharacterInvalid hi def link rustCharacter Character hi def link rustNumber Number hi def link rustBoolean Boolean From bde851e969d327397ac1ab4bca05692069ff62a5 Mon Sep 17 00:00:00 2001 From: Piotr Jawniak Date: Wed, 18 Jun 2014 11:40:41 +0200 Subject: [PATCH 18/25] Fix FIXME #5275 Issue #5275 was closed, but there still was a FIXME for it. --- src/librustc/middle/liveness.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index cd876113807a9..8cd840582ba99 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -701,17 +701,12 @@ impl<'a> Liveness<'a> { if self.loop_scope.len() == 0 { self.ir.tcx.sess.span_bug(sp, "break outside loop"); } else { - // FIXME(#5275): this shouldn't have to be a method... - self.last_loop_scope() + *self.loop_scope.last().unwrap() } } } } - fn last_loop_scope(&self) -> NodeId { - *self.loop_scope.last().unwrap() - } - #[allow(unused_must_use)] fn ln_str(&self, ln: LiveNode) -> String { let mut wr = io::MemWriter::new(); From b1df9aa16fe0f801f2f56afdddd6faa0461a3b0e Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Wed, 18 Jun 2014 22:33:58 +0800 Subject: [PATCH 19/25] Fix #14865 Fixes a codegen bug which generates illegal non-terminated LLVM block when there are wildcard pattern with guard and enum patterns in a match expression. Also refactors the code a little. Closes #14865 --- src/librustc/middle/trans/_match.rs | 54 +++++++---------------------- src/test/run-pass/issue-14865.rs | 30 ++++++++++++++++ 2 files changed, 42 insertions(+), 42 deletions(-) create mode 100644 src/test/run-pass/issue-14865.rs diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 808d894be4386..ffd29ffeb8fb4 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -518,8 +518,7 @@ fn enter_default<'a, 'b>( dm: &DefMap, m: &'a [Match<'a, 'b>], col: uint, - val: ValueRef, - chk: &FailureHandler) + val: ValueRef) -> Vec> { debug!("enter_default(bcx={}, m={}, col={}, val={})", bcx.to_str(), @@ -529,35 +528,13 @@ fn enter_default<'a, 'b>( let _indenter = indenter(); // Collect all of the matches that can match against anything. - let matches = enter_match(bcx, dm, m, col, val, |p| { + enter_match(bcx, dm, m, col, val, |p| { match p.node { ast::PatWild | ast::PatWildMulti => Some(Vec::new()), ast::PatIdent(_, _, None) if pat_is_binding(dm, &*p) => Some(Vec::new()), _ => None } - }); - - // Ok, now, this is pretty subtle. A "default" match is a match - // that needs to be considered if none of the actual checks on the - // value being considered succeed. The subtlety lies in that sometimes - // identifier/wildcard matches are *not* default matches. Consider: - // "match x { _ if something => foo, true => bar, false => baz }". - // There is a wildcard match, but it is *not* a default case. The boolean - // case on the value being considered is exhaustive. If the case is - // exhaustive, then there are no defaults. - // - // We detect whether the case is exhaustive in the following - // somewhat kludgy way: if the last wildcard/binding match has a - // guard, then by non-redundancy, we know that there aren't any - // non guarded matches, and thus by exhaustiveness, we know that - // we don't need any default cases. If the check *isn't* nonexhaustive - // (because chk is Some), then we need the defaults anyways. - let is_exhaustive = match matches.last() { - Some(m) if m.data.arm.guard.is_some() && chk.is_infallible() => true, - _ => false - }; - - if is_exhaustive { Vec::new() } else { matches } + }) } // nmatsakis: what does enter_opt do? @@ -1448,15 +1425,12 @@ fn compile_submatch<'a, 'b>( m.repr(bcx.tcx()), vec_map_to_str(vals, |v| bcx.val_to_str(*v))); let _indenter = indenter(); - - /* - For an empty match, a fall-through case must exist - */ - assert!((m.len() > 0u || chk.is_fallible())); let _icx = push_ctxt("match::compile_submatch"); let mut bcx = bcx; if m.len() == 0u { - Br(bcx, chk.handle_fail()); + if chk.is_fallible() { + Br(bcx, chk.handle_fail()); + } return; } if m[0].pats.len() == 0u { @@ -1658,7 +1632,7 @@ fn compile_submatch_continue<'a, 'b>( C_int(ccx, 0) // Placeholder for when not using a switch }; - let defaults = enter_default(else_cx, dm, m, col, val, chk); + let defaults = enter_default(else_cx, dm, m, col, val); let exhaustive = chk.is_infallible() && defaults.len() == 0u; let len = opts.len(); @@ -1947,18 +1921,14 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>, // `compile_submatch` works one column of arm patterns a time and // then peels that column off. So as we progress, it may become - // impossible to know whether we have a genuine default arm, i.e. + // impossible to tell whether we have a genuine default arm, i.e. // `_ => foo` or not. Sometimes it is important to know that in order // to decide whether moving on to the next condition or falling back // to the default arm. - let has_default = arms.len() > 0 && { - let ref pats = arms.last().unwrap().pats; - - pats.len() == 1 - && match pats.last().unwrap().node { - ast::PatWild => true, _ => false - } - }; + let has_default = arms.last().map_or(false, |arm| { + arm.pats.len() == 1 + && arm.pats.last().unwrap().node == ast::PatWild + }); compile_submatch(bcx, matches.as_slice(), [discr_datum.val], &chk, has_default); diff --git a/src/test/run-pass/issue-14865.rs b/src/test/run-pass/issue-14865.rs new file mode 100644 index 0000000000000..7fa88a7653ac4 --- /dev/null +++ b/src/test/run-pass/issue-14865.rs @@ -0,0 +1,30 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum X { + Foo(uint), + Bar(bool) +} + +fn main() { + let x = match Foo(42) { + Foo(..) => 1, + _ if true => 0, + Bar(..) => fail!("Oh dear") + }; + assert_eq!(x, 1); + + let x = match Foo(42) { + _ if true => 0, + Foo(..) => 1, + Bar(..) => fail!("Oh dear") + }; + assert_eq!(x, 0); +} From 7cfdfa6ef6d8d7bdf2cc942750cf55bb50b21148 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 18 Jun 2014 17:56:21 +0200 Subject: [PATCH 20/25] debuginfo: Add test case for issue 14411. --- src/test/debuginfo/issue14411.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/debuginfo/issue14411.rs diff --git a/src/test/debuginfo/issue14411.rs b/src/test/debuginfo/issue14411.rs new file mode 100644 index 0000000000000..16c7dcc34ff60 --- /dev/null +++ b/src/test/debuginfo/issue14411.rs @@ -0,0 +1,25 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android: FIXME(#10381) + +// compile-flags:-g + +// No debugger interaction required: just make sure it compiles without +// crashing. + +fn test(a: &Vec) { + print!("{}", a.len()); +} + +pub fn main() { + let data = vec!(); + test(&data); +} From ba863c81672549693a863822bf2600e5362a2927 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 18 Jun 2014 11:25:04 -0700 Subject: [PATCH 21/25] (doc) Change search placeholder text. Update placeholder text to make keyboard shortcuts more apparent. --- src/librustdoc/html/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index f48a93574e7e7..0304a1d690ef5 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -63,7 +63,7 @@ r##"
From abf7e933df0c732f14b5b8906161e74e72cd26ca Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Wed, 18 Jun 2014 14:51:15 -0400 Subject: [PATCH 22/25] Update compiler-rt to work for non-v7 arm. --- src/compiler-rt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler-rt b/src/compiler-rt index 7b97b8468f061..62a4ca6055ad6 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit 7b97b8468f0614072cf3299fa8c51e85f609316f +Subproject commit 62a4ca6055ad6fda8faf767b93b5736dcdfb7013 From 108b8b6dc707775bd54aeea7820e0d473f556718 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 18 Jun 2014 20:25:36 +0200 Subject: [PATCH 23/25] Deprecate the bytes!() macro. Replace its usage with byte string literals, except in `bytes!()` tests. Also add a new snapshot, to be able to use the new b"foo" syntax. The src/etc/2014-06-rewrite-bytes-macros.py script automatically rewrites `bytes!()` invocations into byte string literals. Pass it filenames as arguments to generate a diff that you can inspect, or `--apply` followed by filenames to apply the changes in place. Diffs can be piped into `tip` or `pygmentize -l diff` for coloring. --- src/compiletest/runtest.rs | 4 +- src/doc/complement-cheatsheet.md | 2 +- src/doc/rust.md | 13 + src/etc/2014-06-rewrite-bytes-macros.py | 138 +++++++++ src/libcollections/slice.rs | 32 +-- src/libcollections/str.rs | 52 ++-- src/libdebug/repr.rs | 6 +- src/libnative/io/file_unix.rs | 6 +- src/libnative/io/file_win32.rs | 2 +- src/librand/lib.rs | 6 +- src/librustc/metadata/filesearch.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 2 +- src/librustdoc/html/render.rs | 4 +- src/librustrt/args.rs | 4 +- src/librustrt/c_str.rs | 22 +- src/libserialize/base64.rs | 14 +- src/libserialize/hex.rs | 2 +- src/libstd/io/buffered.rs | 4 +- src/libstd/io/fs.rs | 30 +- src/libstd/io/mem.rs | 4 +- src/libstd/io/mod.rs | 28 +- src/libstd/io/pipe.rs | 2 +- src/libstd/io/stdio.rs | 2 +- src/libstd/macros.rs | 2 +- src/libstd/path/mod.rs | 4 +- src/libstd/path/posix.rs | 265 +++++++++--------- src/libstd/path/windows.rs | 107 +++---- src/libsyntax/ext/bytes.rs | 8 + src/libterm/terminfo/parm.rs | 54 ++-- src/libterm/terminfo/parser/compiled.rs | 8 +- src/snapshots.txt | 8 + .../compile-fail/macros-nonfatal-errors.rs | 3 +- ...-extension-bytes-non-ascii-char-literal.rs | 1 + .../syntax-extension-bytes-non-literal.rs | 1 + ...tension-bytes-too-large-integer-literal.rs | 1 + ...ax-extension-bytes-too-large-u8-literal.rs | 1 + ...tension-bytes-too-small-integer-literal.rs | 1 + ...ax-extension-bytes-too-small-u8-literal.rs | 1 + ...tax-extension-bytes-unsupported-literal.rs | 1 + src/test/run-pass/issue-4333.rs | 2 +- src/test/run-pass/tempfile.rs | 2 +- src/test/run-pass/trait-coercion.rs | 2 +- 42 files changed, 498 insertions(+), 355 deletions(-) create mode 100755 src/etc/2014-06-rewrite-bytes-macros.py diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 1e07068dd6f62..ce3c2d7de8095 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -1269,7 +1269,7 @@ fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> Path { fn aux_output_dir_name(config: &Config, testfile: &Path) -> Path { let mut f = output_base_name(config, testfile); - match f.filename().map(|s| Vec::from_slice(s).append(bytes!(".libaux"))) { + match f.filename().map(|s| Vec::from_slice(s).append(b".libaux")) { Some(v) => f.set_filename(v), None => () } @@ -1490,7 +1490,7 @@ fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path { (*p).clone() } else { let stem = p.filestem().unwrap(); - p.with_filename(Vec::from_slice(stem).append(bytes!("-")).append(suffix.as_bytes())) + p.with_filename(Vec::from_slice(stem).append(b"-").append(suffix.as_bytes())) } } diff --git a/src/doc/complement-cheatsheet.md b/src/doc/complement-cheatsheet.md index 9797284a65b7d..84fd140a23af4 100644 --- a/src/doc/complement-cheatsheet.md +++ b/src/doc/complement-cheatsheet.md @@ -76,7 +76,7 @@ character. ~~~ use std::str; -let x = bytes!(72u8,"ello ",0xF0,0x90,0x80,"World!"); +let x = b"Hello \xF0\x90\x80World!"; let y = str::from_utf8_lossy(x); ~~~ diff --git a/src/doc/rust.md b/src/doc/rust.md index cc41b8edfbf8d..7e5e5b2e67a43 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -378,6 +378,19 @@ the characters `U+0022` (double-quote) (except when followed by at least as many `U+0023` (`#`) characters as were used to start the raw string literal) or `U+005C` (`\`) do not have any special meaning. +Examples for byte string literals: + +~~~~ +b"foo"; br"foo"; // foo +b"\"foo\""; br#""foo""#; // "foo" + +b"foo #\"# bar"; +br##"foo #"# bar"##; // foo #"# bar + +b"\x52"; b"R"; br"R"; // R +b"\\x52"; br"\x52"; // \x52 +~~~~ + #### Number literals ~~~~ {.ebnf .gram} diff --git a/src/etc/2014-06-rewrite-bytes-macros.py b/src/etc/2014-06-rewrite-bytes-macros.py new file mode 100755 index 0000000000000..ceda4bf6fe253 --- /dev/null +++ b/src/etc/2014-06-rewrite-bytes-macros.py @@ -0,0 +1,138 @@ +#!/bin/env python +# +# Copyright 2014 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import sys +import subprocess +import re + + +def main(): + if len(sys.argv) <= 1: + print('Usage: %s [ --apply ] filename1.rs filename2.rs ...' + % sys.argv[0]) + elif sys.argv[1] == '--apply': + for filename in sys.argv[2:]: + patch(filename) + else: + for filename in sys.argv[1:]: + diff(filename) + + +def patch(filename): + source = read(filename) + rewritten = rewrite_bytes_macros(source) + if rewritten is not None and rewritten != source: + write(filename, rewritten) + + +def diff(filename): + rewritten = rewrite_bytes_macros(read(filename)) + if rewritten is not None: + p = subprocess.Popen(['diff', '-u', filename, '-'], + stdin=subprocess.PIPE) + p.stdin.write(rewritten) + p.stdin.close() + p.wait() + + +def read(filename): + with open(filename, 'rb') as f: + return f.read() + + +def write(filename, content): + with open(filename, 'wb') as f: + f.write(content) + + +def rewrite_bytes_macros(source): + rewritten, num_occurrences = BYTES_MACRO_RE.subn(rewrite_one_macro, source) + if num_occurrences > 0: + return rewritten + + +BYTES_MACRO_RE = re.compile(br'bytes!\( (?P [^)]* ) \)', re.VERBOSE) + + +def rewrite_one_macro(match): + try: + bytes = parse_bytes(split_args(match.group('args'))) + return b'b"' + b''.join(map(escape, bytes)) + b'"' + except SkipThisRewrite: + print('Skipped: %s' % match.group(0).decode('utf8', 'replace')) + return match.group(0) + + +class SkipThisRewrite(Exception): + pass + + +def split_args(args): + previous = b'' + for arg in args.split(b','): + if previous: + arg = previous + b',' + arg + if arg.count(b'"') % 2 == 0: + yield arg + previous = b'' + else: + previous = arg + if previous: + yield previous + + +def parse_bytes(args): + for arg in args: + arg = arg.strip() + if (arg.startswith(b'"') and arg.endswith(b'"')) or ( + arg.startswith(b"'") and arg.endswith(b"'")): + # Escaped newline means something different in Rust and Python. + if b'\\\n' in arg: + raise SkipThisRewrite + for byte in eval(b'u' + arg).encode('utf8'): + yield ord(byte) + else: + if arg.endswith(b'u8'): + arg = arg[:-2] + # Assume that all Rust integer literals + # are valid Python integer literals + value = int(eval(arg)) + assert value <= 0xFF + yield value + + +def escape(byte): + c = chr(byte) + escaped = { + b'\0': br'\0', + b'\t': br'\t', + b'\n': br'\n', + b'\r': br'\r', + b'\'': b'\\\'', + b'\\': br'\\', + }.get(c) + if escaped is not None: + return escaped + elif b' ' <= c <= b'~': + return chr(byte) + else: + return ('\\x%02X' % byte).encode('ascii') + + +if str is not bytes: + # Python 3.x + ord = lambda x: x + chr = lambda x: bytes([x]) + + +if __name__ == '__main__': + main() diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index ff00ca58e8c76..f9826fcd2287f 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1957,30 +1957,30 @@ mod tests { #[test] fn test_starts_with() { - assert!(bytes!("foobar").starts_with(bytes!("foo"))); - assert!(!bytes!("foobar").starts_with(bytes!("oob"))); - assert!(!bytes!("foobar").starts_with(bytes!("bar"))); - assert!(!bytes!("foo").starts_with(bytes!("foobar"))); - assert!(!bytes!("bar").starts_with(bytes!("foobar"))); - assert!(bytes!("foobar").starts_with(bytes!("foobar"))); + assert!(b"foobar".starts_with(b"foo")); + assert!(!b"foobar".starts_with(b"oob")); + assert!(!b"foobar".starts_with(b"bar")); + assert!(!b"foo".starts_with(b"foobar")); + assert!(!b"bar".starts_with(b"foobar")); + assert!(b"foobar".starts_with(b"foobar")); let empty: &[u8] = []; assert!(empty.starts_with(empty)); - assert!(!empty.starts_with(bytes!("foo"))); - assert!(bytes!("foobar").starts_with(empty)); + assert!(!empty.starts_with(b"foo")); + assert!(b"foobar".starts_with(empty)); } #[test] fn test_ends_with() { - assert!(bytes!("foobar").ends_with(bytes!("bar"))); - assert!(!bytes!("foobar").ends_with(bytes!("oba"))); - assert!(!bytes!("foobar").ends_with(bytes!("foo"))); - assert!(!bytes!("foo").ends_with(bytes!("foobar"))); - assert!(!bytes!("bar").ends_with(bytes!("foobar"))); - assert!(bytes!("foobar").ends_with(bytes!("foobar"))); + assert!(b"foobar".ends_with(b"bar")); + assert!(!b"foobar".ends_with(b"oba")); + assert!(!b"foobar".ends_with(b"foo")); + assert!(!b"foo".ends_with(b"foobar")); + assert!(!b"bar".ends_with(b"foobar")); + assert!(b"foobar".ends_with(b"foobar")); let empty: &[u8] = []; assert!(empty.ends_with(empty)); - assert!(!empty.ends_with(bytes!("foo"))); - assert!(bytes!("foobar").ends_with(empty)); + assert!(!empty.ends_with(b"foo")); + assert!(b"foobar".ends_with(empty)); } #[test] diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 83601be83dec0..642e7cfc9a36f 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -382,7 +382,7 @@ static TAG_CONT_U8: u8 = 128u8; /// # Example /// /// ```rust -/// let input = bytes!("Hello ", 0xF0, 0x90, 0x80, "World"); +/// let input = b"Hello \xF0\x90\x80World"; /// let output = std::str::from_utf8_lossy(input); /// assert_eq!(output.as_slice(), "Hello \uFFFDWorld"); /// ``` @@ -391,7 +391,7 @@ pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> { return Slice(unsafe { mem::transmute(v) }) } - static REPLACEMENT: &'static [u8] = bytes!(0xEF, 0xBF, 0xBD); // U+FFFD in UTF-8 + static REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 let mut i = 0; let total = v.len(); fn unsafe_get(xs: &[u8], i: uint) -> u8 { @@ -994,7 +994,7 @@ mod tests { fn test_into_bytes() { let data = "asdf".to_string(); let buf = data.into_bytes(); - assert_eq!(bytes!("asdf"), buf.as_slice()); + assert_eq!(b"asdf", buf.as_slice()); } #[test] @@ -2050,58 +2050,58 @@ mod tests { #[test] fn test_str_from_utf8() { - let xs = bytes!("hello"); + let xs = b"hello"; assert_eq!(from_utf8(xs), Some("hello")); - let xs = bytes!("ศไทย中华Việt Nam"); + let xs = "ศไทย中华Việt Nam".as_bytes(); assert_eq!(from_utf8(xs), Some("ศไทย中华Việt Nam")); - let xs = bytes!("hello", 0xff); + let xs = b"hello\xFF"; assert_eq!(from_utf8(xs), None); } #[test] fn test_str_from_utf8_owned() { - let xs = Vec::from_slice(bytes!("hello")); + let xs = Vec::from_slice(b"hello"); assert_eq!(from_utf8_owned(xs), Ok("hello".to_string())); - let xs = Vec::from_slice(bytes!("ศไทย中华Việt Nam")); + let xs = Vec::from_slice("ศไทย中华Việt Nam".as_bytes()); assert_eq!(from_utf8_owned(xs), Ok("ศไทย中华Việt Nam".to_string())); - let xs = Vec::from_slice(bytes!("hello", 0xff)); + let xs = Vec::from_slice(b"hello\xFF"); assert_eq!(from_utf8_owned(xs), - Err(Vec::from_slice(bytes!("hello", 0xff)))); + Err(Vec::from_slice(b"hello\xFF"))); } #[test] fn test_str_from_utf8_lossy() { - let xs = bytes!("hello"); + let xs = b"hello"; assert_eq!(from_utf8_lossy(xs), Slice("hello")); - let xs = bytes!("ศไทย中华Việt Nam"); + let xs = "ศไทย中华Việt Nam".as_bytes(); assert_eq!(from_utf8_lossy(xs), Slice("ศไทย中华Việt Nam")); - let xs = bytes!("Hello", 0xC2, " There", 0xFF, " Goodbye"); + let xs = b"Hello\xC2 There\xFF Goodbye"; assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD There\uFFFD Goodbye".to_string())); - let xs = bytes!("Hello", 0xC0, 0x80, " There", 0xE6, 0x83, " Goodbye"); + let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; assert_eq!(from_utf8_lossy(xs), Owned("Hello\uFFFD\uFFFD There\uFFFD Goodbye".to_string())); - let xs = bytes!(0xF5, "foo", 0xF5, 0x80, "bar"); + let xs = b"\xF5foo\xF5\x80bar"; assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFD\uFFFDbar".to_string())); - let xs = bytes!(0xF1, "foo", 0xF1, 0x80, "bar", 0xF1, 0x80, 0x80, "baz"); + let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFDbaz".to_string())); - let xs = bytes!(0xF4, "foo", 0xF4, 0x80, "bar", 0xF4, 0xBF, "baz"); + let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; assert_eq!(from_utf8_lossy(xs), Owned("\uFFFDfoo\uFFFDbar\uFFFD\uFFFDbaz".to_string())); - let xs = bytes!(0xF0, 0x80, 0x80, 0x80, "foo", 0xF0, 0x90, 0x80, 0x80, "bar"); + let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFD\uFFFD\ foo\U00010000bar".to_string())); // surrogates - let xs = bytes!(0xED, 0xA0, 0x80, "foo", 0xED, 0xBF, 0xBF, "bar"); + let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; assert_eq!(from_utf8_lossy(xs), Owned("\uFFFD\uFFFD\uFFFDfoo\ \uFFFD\uFFFD\uFFFDbar".to_string())); } @@ -2298,8 +2298,8 @@ mod bench { #[bench] fn is_utf8_100_ascii(b: &mut Bencher) { - let s = bytes!("Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "); + let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; assert_eq!(100, s.len()); b.iter(|| { @@ -2309,7 +2309,7 @@ mod bench { #[bench] fn is_utf8_100_multibyte(b: &mut Bencher) { - let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰"); + let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); assert_eq!(100, s.len()); b.iter(|| { is_utf8(s) @@ -2318,8 +2318,8 @@ mod bench { #[bench] fn from_utf8_lossy_100_ascii(b: &mut Bencher) { - let s = bytes!("Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "); + let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; assert_eq!(100, s.len()); b.iter(|| { @@ -2329,7 +2329,7 @@ mod bench { #[bench] fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { - let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰"); + let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); assert_eq!(100, s.len()); b.iter(|| { let _ = from_utf8_lossy(s); @@ -2338,7 +2338,7 @@ mod bench { #[bench] fn from_utf8_lossy_invalid(b: &mut Bencher) { - let s = bytes!("Hello", 0xC0, 0x80, " There", 0xE6, 0x83, " Goodbye"); + let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; b.iter(|| { let _ = from_utf8_lossy(s); }); diff --git a/src/libdebug/repr.rs b/src/libdebug/repr.rs index d27b0f0de7e30..4744d92436f2b 100644 --- a/src/libdebug/repr.rs +++ b/src/libdebug/repr.rs @@ -75,13 +75,13 @@ macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = self.to_str(); writer.write(s.as_bytes()).and_then(|()| { - writer.write(bytes!($suffix)) + writer.write($suffix) }) } })) -num_repr!(f32, "f32") -num_repr!(f64, "f64") +num_repr!(f32, b"f32") +num_repr!(f64, b"f64") // New implementation using reflect::MovePtr diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index 93938e3d5b860..edf2becc77760 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -360,7 +360,7 @@ pub fn readdir(p: &CString) -> IoResult> { let root = Path::new(root); dirs.move_iter().filter(|path| { - path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..") + path.as_vec() != b"." && path.as_vec() != b".." }).map(|path| root.join(path).to_c_str()).collect() } @@ -529,7 +529,7 @@ mod tests { let mut reader = FileDesc::new(reader, true); let mut writer = FileDesc::new(writer, true); - writer.inner_write(bytes!("test")).ok().unwrap(); + writer.inner_write(b"test").ok().unwrap(); let mut buf = [0u8, ..4]; match reader.inner_read(buf) { Ok(4) => { @@ -552,7 +552,7 @@ mod tests { assert!(!f.is_null()); let mut file = CFile::new(f); - file.write(bytes!("test")).ok().unwrap(); + file.write(b"test").ok().unwrap(); let mut buf = [0u8, ..4]; let _ = file.seek(0, SeekSet).ok().unwrap(); match file.read(buf) { diff --git a/src/libnative/io/file_win32.rs b/src/libnative/io/file_win32.rs index 41ef5e31a91f6..cd9abc70a4ee8 100644 --- a/src/libnative/io/file_win32.rs +++ b/src/libnative/io/file_win32.rs @@ -351,7 +351,7 @@ pub fn readdir(p: &CString) -> IoResult> { let root = Path::new(root); dirs.move_iter().filter(|path| { - path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..") + path.as_vec() != b"." && path.as_vec() != b".." }).map(|path| root.join(path).to_c_str()).collect() } diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 5a9b949be251a..048e44cd55d78 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -292,9 +292,9 @@ pub struct AsciiGenerator<'a, R> { impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> { fn next(&mut self) -> Option { static GEN_ASCII_STR_CHARSET: &'static [u8] = - bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789"); + b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; Some(*self.rng.choose(GEN_ASCII_STR_CHARSET).unwrap() as char) } } diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index ec46e7f8592d3..c15148f75df22 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -214,7 +214,7 @@ pub fn rust_path() -> Vec { env_rust_path.push(cwd.clone()); } loop { - if { let f = cwd.filename(); f.is_none() || f.unwrap() == bytes!("..") } { + if { let f = cwd.filename(); f.is_none() || f.unwrap() == b".." } { break } cwd.set_filename(".rust"); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 11166f92b1cc2..783fdfa4aaec9 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -1411,7 +1411,7 @@ fn compile_unit_metadata(cx: &CrateContext) { match abs_path.path_relative_from(work_dir) { Some(ref p) if p.is_relative() => { // prepend "./" if necessary - let dotdot = bytes!(".."); + let dotdot = b".."; let prefix = &[dotdot[0], ::std::path::SEP_BYTE]; let mut path_bytes = Vec::from_slice(p.as_vec()); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c6a6eb29addda..76e604ecfa287 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -602,7 +602,7 @@ fn mkdir(path: &Path) -> io::IoResult<()> { // FIXME (#9639): The closure should deal with &[u8] instead of &str fn clean_srcpath(src: &[u8], f: |&str|) { let p = Path::new(src); - if p.as_vec() != bytes!(".") { + if p.as_vec() != b"." { for c in p.str_components().map(|x|x.unwrap()) { if ".." == c { f("up"); @@ -714,7 +714,7 @@ impl<'a> SourceCollector<'a> { }); cur.push(Vec::from_slice(p.filename().expect("source has no filename")) - .append(bytes!(".html"))); + .append(b".html")); let mut w = BufferedWriter::new(try!(File::create(&cur))); let title = format!("{} -- source", cur.filename_display()); diff --git a/src/librustrt/args.rs b/src/librustrt/args.rs index d6d4b18051bf3..09ae2b31f6368 100644 --- a/src/librustrt/args.rs +++ b/src/librustrt/args.rs @@ -123,8 +123,8 @@ mod imp { let saved_value = take(); let expected = vec![ - Vec::from_slice(bytes!("happy")), - Vec::from_slice(bytes!("today?")), + Vec::from_slice(b"happy"), + Vec::from_slice(b"today?"), ]; put(expected.clone()); diff --git a/src/librustrt/c_str.rs b/src/librustrt/c_str.rs index b4d9ac7efbebc..4a7ac97beed8d 100644 --- a/src/librustrt/c_str.rs +++ b/src/librustrt/c_str.rs @@ -463,7 +463,7 @@ mod tests { #[test] fn test_str_multistring_parsing() { unsafe { - let input = bytes!("zero", "\x00", "one", "\x00", "\x00"); + let input = b"zero\0one\0\0"; let ptr = input.as_ptr(); let expected = ["zero", "one"]; let mut it = expected.iter(); @@ -505,7 +505,7 @@ mod tests { } }); - let _ = bytes!("hello").to_c_str().with_ref(|buf| { + let _ = b"hello".to_c_str().with_ref(|buf| { unsafe { assert_eq!(*buf.offset(0), 'h' as libc::c_char); assert_eq!(*buf.offset(1), 'e' as libc::c_char); @@ -516,7 +516,7 @@ mod tests { } }); - let _ = bytes!("foo", 0xff).to_c_str().with_ref(|buf| { + let _ = b"foo\xFF".to_c_str().with_ref(|buf| { unsafe { assert_eq!(*buf.offset(0), 'f' as libc::c_char); assert_eq!(*buf.offset(1), 'o' as libc::c_char); @@ -595,22 +595,22 @@ mod tests { #[test] fn test_as_bytes() { let c_str = "hello".to_c_str(); - assert_eq!(c_str.as_bytes(), bytes!("hello", 0)); + assert_eq!(c_str.as_bytes(), b"hello\0"); let c_str = "".to_c_str(); - assert_eq!(c_str.as_bytes(), bytes!(0)); - let c_str = bytes!("foo", 0xff).to_c_str(); - assert_eq!(c_str.as_bytes(), bytes!("foo", 0xff, 0)); + assert_eq!(c_str.as_bytes(), b"\0"); + let c_str = b"foo\xFF".to_c_str(); + assert_eq!(c_str.as_bytes(), b"foo\xFF\0"); } #[test] fn test_as_bytes_no_nul() { let c_str = "hello".to_c_str(); - assert_eq!(c_str.as_bytes_no_nul(), bytes!("hello")); + assert_eq!(c_str.as_bytes_no_nul(), b"hello"); let c_str = "".to_c_str(); let exp: &[u8] = []; assert_eq!(c_str.as_bytes_no_nul(), exp); - let c_str = bytes!("foo", 0xff).to_c_str(); - assert_eq!(c_str.as_bytes_no_nul(), bytes!("foo", 0xff)); + let c_str = b"foo\xFF".to_c_str(); + assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF"); } #[test] @@ -633,7 +633,7 @@ mod tests { assert_eq!(c_str.as_str(), Some("hello")); let c_str = "".to_c_str(); assert_eq!(c_str.as_str(), Some("")); - let c_str = bytes!("foo", 0xff).to_c_str(); + let c_str = b"foo\xFF".to_c_str(); assert_eq!(c_str.as_str(), None); } diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 5a8759540c8b5..5c4da38989f11 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -42,13 +42,13 @@ pub static URL_SAFE: Config = pub static MIME: Config = Config {char_set: Standard, pad: true, line_length: Some(76)}; -static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "abcdefghijklmnopqrstuvwxyz", - "0123456789+/"); +static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789+/"; -static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "abcdefghijklmnopqrstuvwxyz", - "0123456789-_"); +static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789-_"; /// A trait for converting a value to base64 encoding. pub trait ToBase64 { @@ -193,7 +193,7 @@ impl<'a> FromBase64 for &'a str { * use serialize::base64::{ToBase64, FromBase64, STANDARD}; * * fn main () { - * let hello_str = bytes!("Hello, World").to_base64(STANDARD); + * let hello_str = b"Hello, World".to_base64(STANDARD); * println!("base64 output: {}", hello_str); * let res = hello_str.as_slice().from_base64(); * if res.is_ok() { diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 8ae3336c342b4..44d0606185345 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -19,7 +19,7 @@ pub trait ToHex { fn to_hex(&self) -> String; } -static CHARS: &'static[u8] = bytes!("0123456789abcdef"); +static CHARS: &'static[u8] = b"0123456789abcdef"; impl<'a> ToHex for &'a [u8] { /** diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 9450f7798edcf..4f355502eb88d 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -535,7 +535,7 @@ mod test { #[test] fn test_read_line() { - let in_buf = MemReader::new(Vec::from_slice(bytes!("a\nb\nc"))); + let in_buf = MemReader::new(Vec::from_slice(b"a\nb\nc")); let mut reader = BufferedReader::with_capacity(2, in_buf); assert_eq!(reader.read_line(), Ok("a\n".to_string())); assert_eq!(reader.read_line(), Ok("b\n".to_string())); @@ -545,7 +545,7 @@ mod test { #[test] fn test_lines() { - let in_buf = MemReader::new(Vec::from_slice(bytes!("a\nb\nc"))); + let in_buf = MemReader::new(Vec::from_slice(b"a\nb\nc")); let mut reader = BufferedReader::with_capacity(2, in_buf); let mut it = reader.lines(); assert_eq!(it.next(), Some(Ok("a\n".to_string()))); diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 20187a6dcde6b..a801dd0e7cb35 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -35,7 +35,7 @@ let path = Path::new("foo.txt"); // create the file, whether it exists or not let mut file = File::create(&path); -file.write(bytes!("foobar")); +file.write(b"foobar"); # drop(file); // open the file in read-only mode @@ -186,7 +186,7 @@ impl File { /// use std::io::File; /// /// let mut f = File::create(&Path::new("foo.txt")); - /// f.write(bytes!("This is a sample file")); + /// f.write(b"This is a sample file"); /// # drop(f); /// # ::std::io::fs::unlink(&Path::new("foo.txt")); /// ``` @@ -1141,7 +1141,7 @@ mod test { iotest!(fn file_test_fileinfo_check_exists_before_and_after_file_creation() { let tmpdir = tmpdir(); let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt"); - check!(File::create(file).write(bytes!("foo"))); + check!(File::create(file).write(b"foo")); assert!(file.exists()); check!(unlink(file)); assert!(!file.exists()); @@ -1253,7 +1253,7 @@ mod test { let canary = d2.join("do_not_delete"); check!(mkdir_recursive(&dtt, io::UserRWX)); check!(mkdir_recursive(&d2, io::UserRWX)); - check!(File::create(&canary).write(bytes!("foo"))); + check!(File::create(&canary).write(b"foo")); check!(symlink(&d2, &dt.join("d2"))); check!(rmdir_recursive(&d1)); @@ -1314,10 +1314,10 @@ mod test { let input = tmpdir.join("in.txt"); let out = tmpdir.join("out.txt"); - check!(File::create(&input).write(bytes!("hello"))); + check!(File::create(&input).write(b"hello")); check!(copy(&input, &out)); let contents = check!(File::open(&out).read_to_end()); - assert_eq!(contents.as_slice(), bytes!("hello")); + assert_eq!(contents.as_slice(), b"hello"); assert_eq!(check!(input.stat()).perm, check!(out.stat()).perm); }) @@ -1342,7 +1342,7 @@ mod test { check!(copy(&input, &output)); assert_eq!(check!(File::open(&output).read_to_end()), - (Vec::from_slice(bytes!("foo")))); + (Vec::from_slice(b"foo"))); }) iotest!(fn copy_file_src_dir() { @@ -1383,7 +1383,7 @@ mod test { } assert_eq!(check!(stat(&out)).size, check!(stat(&input)).size); assert_eq!(check!(File::open(&out).read_to_end()), - (Vec::from_slice(bytes!("foobar")))); + (Vec::from_slice(b"foobar"))); }) #[cfg(not(windows))] // apparently windows doesn't like symlinks @@ -1418,7 +1418,7 @@ mod test { assert_eq!(check!(stat(&out)).size, check!(stat(&input)).size); assert_eq!(check!(stat(&out)).size, check!(input.stat()).size); assert_eq!(check!(File::open(&out).read_to_end()), - (Vec::from_slice(bytes!("foobar")))); + (Vec::from_slice(b"foobar"))); // can't link to yourself match link(&input, &input) { @@ -1456,7 +1456,7 @@ mod test { let mut file = check!(File::open_mode(&path, io::Open, io::ReadWrite)); check!(file.fsync()); check!(file.datasync()); - check!(file.write(bytes!("foo"))); + check!(file.write(b"foo")); check!(file.fsync()); check!(file.datasync()); drop(file); @@ -1467,29 +1467,29 @@ mod test { let path = tmpdir.join("in.txt"); let mut file = check!(File::open_mode(&path, io::Open, io::ReadWrite)); - check!(file.write(bytes!("foo"))); + check!(file.write(b"foo")); check!(file.fsync()); // Do some simple things with truncation assert_eq!(check!(file.stat()).size, 3); check!(file.truncate(10)); assert_eq!(check!(file.stat()).size, 10); - check!(file.write(bytes!("bar"))); + check!(file.write(b"bar")); check!(file.fsync()); assert_eq!(check!(file.stat()).size, 10); assert_eq!(check!(File::open(&path).read_to_end()), - (Vec::from_slice(bytes!("foobar", 0, 0, 0, 0)))); + (Vec::from_slice(b"foobar\0\0\0\0"))); // Truncate to a smaller length, don't seek, and then write something. // Ensure that the intermediate zeroes are all filled in (we're seeked // past the end of the file). check!(file.truncate(2)); assert_eq!(check!(file.stat()).size, 2); - check!(file.write(bytes!("wut"))); + check!(file.write(b"wut")); check!(file.fsync()); assert_eq!(check!(file.stat()).size, 9); assert_eq!(check!(File::open(&path).read_to_end()), - (Vec::from_slice(bytes!("fo", 0, 0, 0, 0, "wut")))); + (Vec::from_slice(b"fo\0\0\0\0wut"))); drop(file); }) diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 71a967bb8dc5f..5eca5361835e3 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -474,7 +474,7 @@ mod test { #[test] fn test_read_char() { - let b = bytes!("Việt"); + let b = b"Vi\xE1\xBB\x87t"; let mut r = BufReader::new(b); assert_eq!(r.read_char(), Ok('V')); assert_eq!(r.read_char(), Ok('i')); @@ -485,7 +485,7 @@ mod test { #[test] fn test_read_bad_char() { - let b = bytes!(0x80); + let b = b"\x80"; let mut r = BufReader::new(b); assert!(r.read_char().is_err()); } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index a7f84899a622e..d9755cdce1a4f 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -50,7 +50,7 @@ Some examples of obvious things you might want to do use std::io::File; let mut file = File::create(&Path::new("message.txt")); - file.write(bytes!("hello, file!\n")); + file.write(b"hello, file!\n"); # drop(file); # ::std::io::fs::unlink(&Path::new("message.txt")); ``` @@ -90,7 +90,7 @@ Some examples of obvious things you might want to do # // just stop it running (#11576) # if false { let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap(); - socket.write(bytes!("GET / HTTP/1.0\n\n")); + socket.write(b"GET / HTTP/1.0\n\n"); let response = socket.read_to_end(); # } ``` @@ -151,7 +151,7 @@ while still providing feedback about errors. The basic strategy: to be 'unwrapped' before use. These features combine in the API to allow for expressions like -`File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n"))` +`File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")` without having to worry about whether "diary.txt" exists or whether the write succeeds. As written, if either `new` or `write_line` encounters an error then the result of the entire expression will @@ -163,7 +163,7 @@ If you wanted to handle the error though you might write: # #![allow(unused_must_use)] use std::io::File; -match File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")) { +match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") { Ok(()) => (), // succeeded Err(e) => println!("failed to write to my diary: {}", e), } @@ -1839,55 +1839,55 @@ mod tests { #[test] fn test_read_at_least() { - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([GoodBehavior(uint::MAX)])); let mut buf = [0u8, ..5]; assert!(r.read_at_least(1, buf).unwrap() >= 1); assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least assert!(r.read_at_least(0, buf).is_ok()); - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([BadBehavior(50), GoodBehavior(uint::MAX)])); assert!(r.read_at_least(1, buf).unwrap() >= 1); - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([BadBehavior(1), GoodBehavior(1), BadBehavior(50), GoodBehavior(uint::MAX)])); assert!(r.read_at_least(1, buf).unwrap() >= 1); assert!(r.read_at_least(1, buf).unwrap() >= 1); - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([BadBehavior(uint::MAX)])); assert_eq!(r.read_at_least(1, buf).unwrap_err().kind, NoProgress); - let mut r = MemReader::new(Vec::from_slice(bytes!("hello, world!"))); + let mut r = MemReader::new(Vec::from_slice(b"hello, world!")); assert_eq!(r.read_at_least(5, buf).unwrap(), 5); assert_eq!(r.read_at_least(6, buf).unwrap_err().kind, InvalidInput); } #[test] fn test_push_at_least() { - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([GoodBehavior(uint::MAX)])); let mut buf = Vec::new(); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); assert!(r.push_at_least(0, 5, &mut buf).is_ok()); - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([BadBehavior(50), GoodBehavior(uint::MAX)])); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([BadBehavior(1), GoodBehavior(1), BadBehavior(50), GoodBehavior(uint::MAX)])); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); - let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))), + let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")), Vec::from_slice([BadBehavior(uint::MAX)])); assert_eq!(r.push_at_least(1, 5, &mut buf).unwrap_err().kind, NoProgress); - let mut r = MemReader::new(Vec::from_slice(bytes!("hello, world!"))); + let mut r = MemReader::new(Vec::from_slice(b"hello, world!")); assert_eq!(r.push_at_least(5, 1, &mut buf).unwrap_err().kind, InvalidInput); } } diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs index 84d388c113630..a968f41a91563 100644 --- a/src/libstd/io/pipe.rs +++ b/src/libstd/io/pipe.rs @@ -52,7 +52,7 @@ impl PipeStream { /// /// fn main() { /// let mut pipe = PipeStream::open(libc::STDERR_FILENO); - /// pipe.write(bytes!("Hello, stderr!")); + /// pipe.write(b"Hello, stderr!"); /// } /// ``` pub fn open(fd: libc::c_int) -> IoResult { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index c989dcc3d2945..e5a64f785ce96 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -22,7 +22,7 @@ about the stream or terminal to which it is attached. use std::io; let mut out = io::stdout(); -out.write(bytes!("Hello, world!")); +out.write(b"Hello, world!"); ``` */ diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 58f65c90b3b10..dad162d82ad47 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -463,7 +463,7 @@ pub mod builtin { /// # Example /// /// ``` - /// let rust = bytes!("r", 'u', "st", 255); + /// let rust = b"rust\xFF"; /// assert_eq!(rust[1], 'u' as u8); /// assert_eq!(rust[4], 255); /// ``` diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 7d15893af241e..e55dc16589516 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -219,7 +219,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { let dot = '.' as u8; match name.rposition_elem(&dot) { None | Some(0) => name, - Some(1) if name == bytes!("..") => name, + Some(1) if name == b".." => name, Some(pos) => name.slice_to(pos) } }) @@ -242,7 +242,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe { let dot = '.' as u8; match name.rposition_elem(&dot) { None | Some(0) => None, - Some(1) if name == bytes!("..") => None, + Some(1) if name == b".." => None, Some(pos) => Some(name.slice_from(pos+1)) } } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 494428de3a5c4..d98cfb7d8eece 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -142,7 +142,7 @@ impl GenericPathUnsafe for Path { unsafe fn set_filename_unchecked(&mut self, filename: T) { let filename = filename.container_as_bytes(); match self.sepidx { - None if bytes!("..") == self.repr.as_slice() => { + None if b".." == self.repr.as_slice() => { let mut v = Vec::with_capacity(3 + filename.len()); v.push_all(dot_dot_static); v.push(SEP_BYTE); @@ -153,7 +153,7 @@ impl GenericPathUnsafe for Path { None => { self.repr = Path::normalize(filename); } - Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => { + Some(idx) if self.repr.slice_from(idx+1) == b".." => { let mut v = Vec::with_capacity(self.repr.len() + 1 + filename.len()); v.push_all(self.repr.as_slice()); v.push(SEP_BYTE); @@ -202,20 +202,20 @@ impl GenericPath for Path { fn dirname<'a>(&'a self) -> &'a [u8] { match self.sepidx { - None if bytes!("..") == self.repr.as_slice() => self.repr.as_slice(), + None if b".." == self.repr.as_slice() => self.repr.as_slice(), None => dot_static, Some(0) => self.repr.slice_to(1), - Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => self.repr.as_slice(), + Some(idx) if self.repr.slice_from(idx+1) == b".." => self.repr.as_slice(), Some(idx) => self.repr.slice_to(idx) } } fn filename<'a>(&'a self) -> Option<&'a [u8]> { match self.sepidx { - None if bytes!(".") == self.repr.as_slice() || - bytes!("..") == self.repr.as_slice() => None, + None if b"." == self.repr.as_slice() || + b".." == self.repr.as_slice() => None, None => Some(self.repr.as_slice()), - Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => None, + Some(idx) if self.repr.slice_from(idx+1) == b".." => None, Some(0) if self.repr.slice_from(1).is_empty() => None, Some(idx) => Some(self.repr.slice_from(idx+1)) } @@ -223,13 +223,13 @@ impl GenericPath for Path { fn pop(&mut self) -> bool { match self.sepidx { - None if bytes!(".") == self.repr.as_slice() => false, + None if b"." == self.repr.as_slice() => false, None => { self.repr = vec!['.' as u8]; self.sepidx = None; true } - Some(0) if bytes!("/") == self.repr.as_slice() => false, + Some(0) if b"/" == self.repr.as_slice() => false, Some(idx) => { if idx == 0 { self.repr.truncate(idx+1); @@ -261,19 +261,19 @@ impl GenericPath for Path { } else { let mut ita = self.components(); let mut itb = other.components(); - if bytes!(".") == self.repr.as_slice() { + if b"." == self.repr.as_slice() { return match itb.next() { None => true, - Some(b) => b != bytes!("..") + Some(b) => b != b".." }; } loop { match (ita.next(), itb.next()) { (None, _) => break, (Some(a), Some(b)) if a == b => { continue }, - (Some(a), _) if a == bytes!("..") => { + (Some(a), _) if a == b".." => { // if ita contains only .. components, it's an ancestor - return ita.all(|x| x == bytes!("..")); + return ita.all(|x| x == b".."); } _ => return false } @@ -303,8 +303,8 @@ impl GenericPath for Path { } (None, _) => comps.push(dot_dot_static), (Some(a), Some(b)) if comps.is_empty() && a == b => (), - (Some(a), Some(b)) if b == bytes!(".") => comps.push(a), - (Some(_), Some(b)) if b == bytes!("..") => return None, + (Some(a), Some(b)) if b == b"." => comps.push(a), + (Some(_), Some(b)) if b == b".." => return None, (Some(a), Some(_)) => { comps.push(dot_dot_static); for _ in itb { @@ -425,8 +425,8 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option> { let mut changed = false; for comp in v.split(is_sep_byte) { if comp.is_empty() { changed = true } - else if comp == bytes!(".") { changed = true } - else if comp == bytes!("..") { + else if comp == b"." { changed = true } + else if comp == b".." { if is_abs && comps.is_empty() { changed = true } else if comps.len() == n_up { comps.push(dot_dot_static); n_up += 1 } else { comps.pop().unwrap(); changed = true } @@ -434,7 +434,7 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option> { } if changed { if comps.is_empty() && !is_abs { - if v == bytes!(".") { + if v == b"." { return None; } comps.push(dot_static); @@ -445,8 +445,8 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option> { } } -static dot_static: &'static [u8] = bytes!("."); -static dot_dot_static: &'static [u8] = bytes!(".."); +static dot_static: &'static [u8] = b"."; +static dot_dot_static: &'static [u8] = b".."; #[cfg(test)] mod tests { @@ -470,24 +470,15 @@ mod tests { ) ) - macro_rules! b( - ($($arg:expr),+) => ( - { - static the_bytes: &'static [u8] = bytes!($($arg),+); - the_bytes - } - ) - ) - #[test] fn test_paths() { let empty: &[u8] = []; - t!(v: Path::new(empty), b!(".")); - t!(v: Path::new(b!("/")), b!("/")); - t!(v: Path::new(b!("a/b/c")), b!("a/b/c")); - t!(v: Path::new(b!("a/b/c", 0xff)), b!("a/b/c", 0xff)); - t!(v: Path::new(b!(0xff, "/../foo", 0x80)), b!("foo", 0x80)); - let p = Path::new(b!("a/b/c", 0xff)); + t!(v: Path::new(empty), b"."); + t!(v: Path::new(b"/"), b"/"); + t!(v: Path::new(b"a/b/c"), b"a/b/c"); + t!(v: Path::new(b"a/b/c\xFF"), b"a/b/c\xFF"); + t!(v: Path::new(b"\xFF/../foo\x80"), b"foo\x80"); + let p = Path::new(b"a/b/c\xFF"); assert!(p.as_str() == None); t!(s: Path::new(""), "."); @@ -513,18 +504,18 @@ mod tests { t!(s: Path::new("foo/../../.."), "../.."); t!(s: Path::new("foo/../../bar"), "../bar"); - assert_eq!(Path::new(b!("foo/bar")).into_vec().as_slice(), b!("foo/bar")); - assert_eq!(Path::new(b!("/foo/../../bar")).into_vec().as_slice(), - b!("/bar")); + assert_eq!(Path::new(b"foo/bar").into_vec().as_slice(), b"foo/bar"); + assert_eq!(Path::new(b"/foo/../../bar").into_vec().as_slice(), + b"/bar"); - let p = Path::new(b!("foo/bar", 0x80)); + let p = Path::new(b"foo/bar\x80"); assert!(p.as_str() == None); } #[test] fn test_opt_paths() { - assert!(Path::new_opt(b!("foo/bar", 0)) == None); - t!(v: Path::new_opt(b!("foo/bar")).unwrap(), b!("foo/bar")); + assert!(Path::new_opt(b"foo/bar\0") == None); + t!(v: Path::new_opt(b"foo/bar").unwrap(), b"foo/bar"); assert!(Path::new_opt("foo/bar\0") == None); t!(s: Path::new_opt("foo/bar").unwrap(), "foo/bar"); } @@ -533,17 +524,17 @@ mod tests { fn test_null_byte() { use task; let result = task::try(proc() { - Path::new(b!("foo/bar", 0)) + Path::new(b"foo/bar\0") }); assert!(result.is_err()); let result = task::try(proc() { - Path::new("test").set_filename(b!("f", 0, "o")) + Path::new("test").set_filename(b"f\0o") }); assert!(result.is_err()); let result = task::try(proc() { - Path::new("test").push(b!("f", 0, "o")); + Path::new("test").push(b"f\0o"); }); assert!(result.is_err()); } @@ -559,11 +550,11 @@ mod tests { ) ) t!("foo", display, "foo"); - t!(b!("foo", 0x80), display, "foo\uFFFD"); - t!(b!("foo", 0xff, "bar"), display, "foo\uFFFDbar"); - t!(b!("foo", 0xff, "/bar"), filename_display, "bar"); - t!(b!("foo/", 0xff, "bar"), filename_display, "\uFFFDbar"); - t!(b!("/"), filename_display, ""); + t!(b"foo\x80", display, "foo\uFFFD"); + t!(b"foo\xFFbar", display, "foo\uFFFDbar"); + t!(b"foo\xFF/bar", filename_display, "bar"); + t!(b"foo/\xFFbar", filename_display, "\uFFFDbar"); + t!(b"/", filename_display, ""); macro_rules! t( ($path:expr, $exp:expr) => ( @@ -583,11 +574,11 @@ mod tests { ) t!("foo", "foo"); - t!(b!("foo", 0x80), "foo\uFFFD"); - t!(b!("foo", 0xff, "bar"), "foo\uFFFDbar"); - t!(b!("foo", 0xff, "/bar"), "bar", filename); - t!(b!("foo/", 0xff, "bar"), "\uFFFDbar", filename); - t!(b!("/"), "", filename); + t!(b"foo\x80", "foo\uFFFD"); + t!(b"foo\xFFbar", "foo\uFFFDbar"); + t!(b"foo\xFF/bar", "bar", filename); + t!(b"foo/\xFFbar", "\uFFFDbar", filename); + t!(b"/", "", filename); } #[test] @@ -604,13 +595,13 @@ mod tests { ) ) - t!(b!("foo"), "foo", "foo"); - t!(b!("foo/bar"), "foo/bar", "bar"); - t!(b!("/"), "/", ""); - t!(b!("foo", 0xff), "foo\uFFFD", "foo\uFFFD"); - t!(b!("foo", 0xff, "/bar"), "foo\uFFFD/bar", "bar"); - t!(b!("foo/", 0xff, "bar"), "foo/\uFFFDbar", "\uFFFDbar"); - t!(b!(0xff, "foo/bar", 0xff), "\uFFFDfoo/bar\uFFFD", "bar\uFFFD"); + t!(b"foo", "foo", "foo"); + t!(b"foo/bar", "foo/bar", "bar"); + t!(b"/", "/", ""); + t!(b"foo\xFF", "foo\uFFFD", "foo\uFFFD"); + t!(b"foo\xFF/bar", "foo\uFFFD/bar", "bar"); + t!(b"foo/\xFFbar", "foo/\uFFFDbar", "\uFFFDbar"); + t!(b"\xFFfoo/bar\xFF", "\uFFFDfoo/bar\uFFFD", "bar\uFFFD"); } #[test] @@ -638,9 +629,9 @@ mod tests { ); ) - t!(v: b!("a/b/c"), filename, Some(b!("c"))); - t!(v: b!("a/b/c", 0xff), filename, Some(b!("c", 0xff))); - t!(v: b!("a/b", 0xff, "/c"), filename, Some(b!("c"))); + t!(v: b"a/b/c", filename, Some(b"c")); + t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF")); + t!(v: b"a/b\xFF/c", filename, Some(b"c")); t!(s: "a/b/c", filename, Some("c"), opt); t!(s: "/a/b/c", filename, Some("c"), opt); t!(s: "a", filename, Some("a"), opt); @@ -650,9 +641,9 @@ mod tests { t!(s: "..", filename, None, opt); t!(s: "../..", filename, None, opt); - t!(v: b!("a/b/c"), dirname, b!("a/b")); - t!(v: b!("a/b/c", 0xff), dirname, b!("a/b")); - t!(v: b!("a/b", 0xff, "/c"), dirname, b!("a/b", 0xff)); + t!(v: b"a/b/c", dirname, b"a/b"); + t!(v: b"a/b/c\xFF", dirname, b"a/b"); + t!(v: b"a/b\xFF/c", dirname, b"a/b\xFF"); t!(s: "a/b/c", dirname, "a/b"); t!(s: "/a/b/c", dirname, "/a/b"); t!(s: "a", dirname, "."); @@ -662,9 +653,9 @@ mod tests { t!(s: "..", dirname, ".."); t!(s: "../..", dirname, "../.."); - t!(v: b!("hi/there.txt"), filestem, Some(b!("there"))); - t!(v: b!("hi/there", 0x80, ".txt"), filestem, Some(b!("there", 0x80))); - t!(v: b!("hi/there.t", 0x80, "xt"), filestem, Some(b!("there"))); + t!(v: b"hi/there.txt", filestem, Some(b"there")); + t!(v: b"hi/there\x80.txt", filestem, Some(b"there\x80")); + t!(v: b"hi/there.t\x80xt", filestem, Some(b"there")); t!(s: "hi/there.txt", filestem, Some("there"), opt); t!(s: "hi/there", filestem, Some("there"), opt); t!(s: "there.txt", filestem, Some("there"), opt); @@ -678,11 +669,11 @@ mod tests { t!(s: "..", filestem, None, opt); t!(s: "../..", filestem, None, opt); - t!(v: b!("hi/there.txt"), extension, Some(b!("txt"))); - t!(v: b!("hi/there", 0x80, ".txt"), extension, Some(b!("txt"))); - t!(v: b!("hi/there.t", 0x80, "xt"), extension, Some(b!("t", 0x80, "xt"))); - t!(v: b!("hi/there"), extension, None); - t!(v: b!("hi/there", 0x80), extension, None); + t!(v: b"hi/there.txt", extension, Some(b"txt")); + t!(v: b"hi/there\x80.txt", extension, Some(b"txt")); + t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt")); + t!(v: b"hi/there", extension, None); + t!(v: b"hi/there\x80", extension, None); t!(s: "hi/there.txt", extension, Some("txt"), opt); t!(s: "hi/there", extension, None, opt); t!(s: "there.txt", extension, Some("txt"), opt); @@ -762,9 +753,9 @@ mod tests { t!(s: "a/b/c", ["d", "/e"], "/e"); t!(s: "a/b/c", ["d", "/e", "f"], "/e/f"); t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e"); - t!(v: b!("a/b/c"), [b!("d"), b!("e")], b!("a/b/c/d/e")); - t!(v: b!("a/b/c"), [b!("d"), b!("/e"), b!("f")], b!("/e/f")); - t!(v: b!("a/b/c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))], b!("a/b/c/d/e")); + t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e"); + t!(v: b"a/b/c", [b"d", b"/e", b"f"], b"/e/f"); + t!(v: b"a/b/c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")], b"a/b/c/d/e"); } #[test] @@ -778,25 +769,25 @@ mod tests { assert!(result == $right); } ); - (v: [$($path:expr),+], [$($left:expr),+], $right:expr) => ( + (b: $path:expr, $left:expr, $right:expr) => ( { - let mut p = Path::new(b!($($path),+)); + let mut p = Path::new($path); let result = p.pop(); - assert!(p.as_vec() == b!($($left),+)); + assert!(p.as_vec() == $left); assert!(result == $right); } ) ) - t!(v: ["a/b/c"], ["a/b"], true); - t!(v: ["a"], ["."], true); - t!(v: ["."], ["."], false); - t!(v: ["/a"], ["/"], true); - t!(v: ["/"], ["/"], false); - t!(v: ["a/b/c", 0x80], ["a/b"], true); - t!(v: ["a/b", 0x80, "/c"], ["a/b", 0x80], true); - t!(v: [0xff], ["."], true); - t!(v: ["/", 0xff], ["/"], true); + t!(b: b"a/b/c", b"a/b", true); + t!(b: b"a", b".", true); + t!(b: b".", b".", false); + t!(b: b"/a", b"/", true); + t!(b: b"/", b"/", false); + t!(b: b"a/b/c\x80", b"a/b", true); + t!(b: b"a/b\x80/c", b"a/b\x80", true); + t!(b: b"\xFF", b".", true); + t!(b: b"/\xFF", b"/", true); t!(s: "a/b/c", "a/b", true); t!(s: "a", ".", true); t!(s: ".", ".", false); @@ -806,15 +797,15 @@ mod tests { #[test] fn test_root_path() { - assert!(Path::new(b!("a/b/c")).root_path() == None); - assert!(Path::new(b!("/a/b/c")).root_path() == Some(Path::new("/"))); + assert!(Path::new(b"a/b/c").root_path() == None); + assert!(Path::new(b"/a/b/c").root_path() == Some(Path::new("/"))); } #[test] fn test_join() { - t!(v: Path::new(b!("a/b/c")).join(b!("..")), b!("a/b")); - t!(v: Path::new(b!("/a/b/c")).join(b!("d")), b!("/a/b/c/d")); - t!(v: Path::new(b!("a/", 0x80, "/c")).join(b!(0xff)), b!("a/", 0x80, "/c/", 0xff)); + t!(v: Path::new(b"a/b/c").join(b".."), b"a/b"); + t!(v: Path::new(b"/a/b/c").join(b"d"), b"/a/b/c/d"); + t!(v: Path::new(b"a/\x80/c").join(b"\xFF"), b"a/\x80/c/\xFF"); t!(s: Path::new("a/b/c").join(".."), "a/b"); t!(s: Path::new("/a/b/c").join("d"), "/a/b/c/d"); t!(s: Path::new("a/b").join("c/d"), "a/b/c/d"); @@ -867,18 +858,18 @@ mod tests { t!(s: "a/b/c", ["..", "d"], "a/b/d"); t!(s: "a/b/c", ["d", "/e", "f"], "/e/f"); t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e"); - t!(v: b!("a/b/c"), [b!("d"), b!("e")], b!("a/b/c/d/e")); - t!(v: b!("a/b/c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))], b!("a/b/c/d/e")); + t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e"); + t!(v: b"a/b/c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")], b"a/b/c/d/e"); } #[test] fn test_with_helpers() { let empty: &[u8] = []; - t!(v: Path::new(b!("a/b/c")).with_filename(b!("d")), b!("a/b/d")); - t!(v: Path::new(b!("a/b/c", 0xff)).with_filename(b!(0x80)), b!("a/b/", 0x80)); - t!(v: Path::new(b!("/", 0xff, "/foo")).with_filename(b!(0xcd)), - b!("/", 0xff, "/", 0xcd)); + t!(v: Path::new(b"a/b/c").with_filename(b"d"), b"a/b/d"); + t!(v: Path::new(b"a/b/c\xFF").with_filename(b"\x80"), b"a/b/\x80"); + t!(v: Path::new(b"/\xFF/foo").with_filename(b"\xCD"), + b"/\xFF/\xCD"); t!(s: Path::new("a/b/c").with_filename("d"), "a/b/d"); t!(s: Path::new(".").with_filename("foo"), "foo"); t!(s: Path::new("/a/b/c").with_filename("d"), "/a/b/d"); @@ -899,13 +890,13 @@ mod tests { t!(s: Path::new("..").with_filename(""), ".."); t!(s: Path::new("../..").with_filename(""), "../.."); - t!(v: Path::new(b!("hi/there", 0x80, ".txt")).with_extension(b!("exe")), - b!("hi/there", 0x80, ".exe")); - t!(v: Path::new(b!("hi/there.txt", 0x80)).with_extension(b!(0xff)), - b!("hi/there.", 0xff)); - t!(v: Path::new(b!("hi/there", 0x80)).with_extension(b!(0xff)), - b!("hi/there", 0x80, ".", 0xff)); - t!(v: Path::new(b!("hi/there.", 0xff)).with_extension(empty), b!("hi/there")); + t!(v: Path::new(b"hi/there\x80.txt").with_extension(b"exe"), + b"hi/there\x80.exe"); + t!(v: Path::new(b"hi/there.txt\x80").with_extension(b"\xFF"), + b"hi/there.\xFF"); + t!(v: Path::new(b"hi/there\x80").with_extension(b"\xFF"), + b"hi/there\x80.\xFF"); + t!(v: Path::new(b"hi/there.\xFF").with_extension(empty), b"hi/there"); t!(s: Path::new("hi/there.txt").with_extension("exe"), "hi/there.exe"); t!(s: Path::new("hi/there.txt").with_extension(""), "hi/there"); t!(s: Path::new("hi/there.txt").with_extension("."), "hi/there.."); @@ -947,17 +938,17 @@ mod tests { ) ) - t!(v: b!("a/b/c"), set_filename, with_filename, b!("d")); - t!(v: b!("/"), set_filename, with_filename, b!("foo")); - t!(v: b!(0x80), set_filename, with_filename, b!(0xff)); + t!(v: b"a/b/c", set_filename, with_filename, b"d"); + t!(v: b"/", set_filename, with_filename, b"foo"); + t!(v: b"\x80", set_filename, with_filename, b"\xFF"); t!(s: "a/b/c", set_filename, with_filename, "d"); t!(s: "/", set_filename, with_filename, "foo"); t!(s: ".", set_filename, with_filename, "foo"); t!(s: "a/b", set_filename, with_filename, ""); t!(s: "a", set_filename, with_filename, ""); - t!(v: b!("hi/there.txt"), set_extension, with_extension, b!("exe")); - t!(v: b!("hi/there.t", 0x80, "xt"), set_extension, with_extension, b!("exe", 0xff)); + t!(v: b"hi/there.txt", set_extension, with_extension, b"exe"); + t!(v: b"hi/there.t\x80xt", set_extension, with_extension, b"exe\xFF"); t!(s: "hi/there.txt", set_extension, with_extension, "exe"); t!(s: "hi/there.", set_extension, with_extension, "txt"); t!(s: "hi/there", set_extension, with_extension, "txt"); @@ -1001,10 +992,10 @@ mod tests { ) ) - t!(v: Path::new(b!("a/b/c")), Some(b!("c")), b!("a/b"), Some(b!("c")), None); - t!(v: Path::new(b!("a/b/", 0xff)), Some(b!(0xff)), b!("a/b"), Some(b!(0xff)), None); - t!(v: Path::new(b!("hi/there.", 0xff)), Some(b!("there.", 0xff)), b!("hi"), - Some(b!("there")), Some(b!(0xff))); + t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None); + t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None); + t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi", + Some(b"there"), Some(b"\xFF")); t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None); t!(s: Path::new("."), None, Some("."), None, None); t!(s: Path::new("/"), None, Some("/"), None, None); @@ -1018,16 +1009,16 @@ mod tests { t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None); t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"), Some("."), Some("there")); - t!(s: Path::new(b!("a/b/", 0xff)), None, Some("a/b"), None, None); - t!(s: Path::new(b!("a/b/", 0xff, ".txt")), None, Some("a/b"), None, Some("txt")); - t!(s: Path::new(b!("a/b/c.", 0x80)), None, Some("a/b"), Some("c"), None); - t!(s: Path::new(b!(0xff, "/b")), Some("b"), None, Some("b"), None); + t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None); + t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt")); + t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None); + t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None); } #[test] fn test_dir_path() { - t!(v: Path::new(b!("hi/there", 0x80)).dir_path(), b!("hi")); - t!(v: Path::new(b!("hi", 0xff, "/there")).dir_path(), b!("hi", 0xff)); + t!(v: Path::new(b"hi/there\x80").dir_path(), b"hi"); + t!(v: Path::new(b"hi\xFF/there").dir_path(), b"hi\xFF"); t!(s: Path::new("hi/there").dir_path(), "hi"); t!(s: Path::new("hi").dir_path(), "."); t!(s: Path::new("/hi").dir_path(), "/"); @@ -1125,9 +1116,9 @@ mod tests { t!(s: "/a/b/c", "d/e/f", false); t!(s: "a/b/c", "a/b", false); t!(s: "a/b/c", "b", false); - t!(v: b!("a/b/c"), b!("b/c"), true); - t!(v: b!("a/b/", 0xff), b!(0xff), true); - t!(v: b!("a/b/", 0xff), b!("b/", 0xff), true); + t!(v: b"a/b/c", b"b/c", true); + t!(v: b"a/b/\xFF", b"\xFF", true); + t!(v: b"a/b/\xFF", b"b/\xFF", true); } #[test] @@ -1192,11 +1183,11 @@ mod tests { comps, exps); } ); - (v: [$($arg:expr),+], [$([$($exp:expr),*]),*]) => ( + (b: $arg:expr, [$($exp:expr),*]) => ( { - let path = Path::new(b!($($arg),+)); + let path = Path::new($arg); let comps = path.components().collect::>(); - let exp: &[&[u8]] = [$(b!($($exp),*)),*]; + let exp: &[&[u8]] = [$($exp),*]; assert_eq!(comps.as_slice(), exp); let comps = path.components().rev().collect::>(); let exp = exp.iter().rev().map(|&x|x).collect::>(); @@ -1205,9 +1196,9 @@ mod tests { ) ) - t!(v: ["a/b/c"], [["a"], ["b"], ["c"]]); - t!(v: ["/", 0xff, "/a/", 0x80], [[0xff], ["a"], [0x80]]); - t!(v: ["../../foo", 0xcd, "bar"], [[".."], [".."], ["foo", 0xcd, "bar"]]); + t!(b: b"a/b/c", [b"a", b"b", b"c"]); + t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]); + t!(b: b"../../foo\xCDbar", [b"..", b"..", b"foo\xCDbar"]); t!(s: "a/b/c", ["a", "b", "c"]); t!(s: "a/b/d", ["a", "b", "d"]); t!(s: "a/b/cd", ["a", "b", "cd"]); @@ -1224,9 +1215,9 @@ mod tests { #[test] fn test_str_components() { macro_rules! t( - (v: [$($arg:expr),+], $exp:expr) => ( + (b: $arg:expr, $exp:expr) => ( { - let path = Path::new(b!($($arg),+)); + let path = Path::new($arg); let comps = path.str_components().collect::>>(); let exp: &[Option<&str>] = $exp; assert_eq!(comps.as_slice(), exp); @@ -1237,9 +1228,9 @@ mod tests { ) ) - t!(v: ["a/b/c"], [Some("a"), Some("b"), Some("c")]); - t!(v: ["/", 0xff, "/a/", 0x80], [None, Some("a"), None]); - t!(v: ["../../foo", 0xcd, "bar"], [Some(".."), Some(".."), None]); + t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]); + t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]); + t!(b: b"../../foo\xCDbar", [Some(".."), Some(".."), None]); // str_components is a wrapper around components, so no need to do // the full set of tests } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 553c7af18cb26..4d6f8d0888f3e 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1123,15 +1123,6 @@ mod tests { ) ) - macro_rules! b( - ($($arg:expr),+) => ( - { - static the_bytes: &'static [u8] = bytes!($($arg),+); - the_bytes - } - ) - ) - #[test] fn test_parse_prefix() { macro_rules! t( @@ -1196,9 +1187,9 @@ mod tests { #[test] fn test_paths() { let empty: &[u8] = []; - t!(v: Path::new(empty), b!(".")); - t!(v: Path::new(b!("\\")), b!("\\")); - t!(v: Path::new(b!("a\\b\\c")), b!("a\\b\\c")); + t!(v: Path::new(empty), b"."); + t!(v: Path::new(b"\\"), b"\\"); + t!(v: Path::new(b"a\\b\\c"), b"a\\b\\c"); t!(s: Path::new(""), "."); t!(s: Path::new("\\"), "\\"); @@ -1230,8 +1221,8 @@ mod tests { t!(s: Path::new("foo\\..\\..\\.."), "..\\.."); t!(s: Path::new("foo\\..\\..\\bar"), "..\\bar"); - assert_eq!(Path::new(b!("foo\\bar")).into_vec().as_slice(), b!("foo\\bar")); - assert_eq!(Path::new(b!("\\foo\\..\\..\\bar")).into_vec().as_slice(), b!("\\bar")); + assert_eq!(Path::new(b"foo\\bar").into_vec().as_slice(), b"foo\\bar"); + assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec().as_slice(), b"\\bar"); t!(s: Path::new("\\\\a"), "\\a"); t!(s: Path::new("\\\\a\\"), "\\a"); @@ -1284,9 +1275,9 @@ mod tests { #[test] fn test_opt_paths() { - assert!(Path::new_opt(b!("foo\\bar", 0)) == None); - assert!(Path::new_opt(b!("foo\\bar", 0x80)) == None); - t!(v: Path::new_opt(b!("foo\\bar")).unwrap(), b!("foo\\bar")); + assert!(Path::new_opt(b"foo\\bar\0") == None); + assert!(Path::new_opt(b"foo\\bar\x80") == None); + t!(v: Path::new_opt(b"foo\\bar").unwrap(), b"foo\\bar"); assert!(Path::new_opt("foo\\bar\0") == None); t!(s: Path::new_opt("foo\\bar").unwrap(), "foo\\bar"); } @@ -1295,17 +1286,17 @@ mod tests { fn test_null_byte() { use task; let result = task::try(proc() { - Path::new(b!("foo/bar", 0)) + Path::new(b"foo/bar\0") }); assert!(result.is_err()); let result = task::try(proc() { - Path::new("test").set_filename(b!("f", 0, "o")) + Path::new("test").set_filename(b"f\0o") }); assert!(result.is_err()); let result = task::try(proc() { - Path::new("test").push(b!("f", 0, "o")); + Path::new("test").push(b"f\0o"); }); assert!(result.is_err()); } @@ -1313,20 +1304,20 @@ mod tests { #[test] #[should_fail] fn test_not_utf8_fail() { - Path::new(b!("hello", 0x80, ".txt")); + Path::new(b"hello\x80.txt"); } #[test] fn test_display_str() { let path = Path::new("foo"); assert_eq!(path.display().to_str(), "foo".to_string()); - let path = Path::new(b!("\\")); + let path = Path::new(b"\\"); assert_eq!(path.filename_display().to_str(), "".to_string()); let path = Path::new("foo"); let mo = path.display().as_maybe_owned(); assert_eq!(mo.as_slice(), "foo"); - let path = Path::new(b!("\\")); + let path = Path::new(b"\\"); let mo = path.filename_display().as_maybe_owned(); assert_eq!(mo.as_slice(), ""); } @@ -1377,7 +1368,7 @@ mod tests { ) ) - t!(v: b!("a\\b\\c"), filename, Some(b!("c"))); + t!(v: b"a\\b\\c", filename, Some(b"c")); t!(s: "a\\b\\c", filename_str, "c"); t!(s: "\\a\\b\\c", filename_str, "c"); t!(s: "a", filename_str, "a"); @@ -1410,7 +1401,7 @@ mod tests { t!(s: "\\\\.\\", filename_str, None, opt); t!(s: "\\\\?\\a\\b\\", filename_str, "b"); - t!(v: b!("a\\b\\c"), dirname, b!("a\\b")); + t!(v: b"a\\b\\c", dirname, b"a\\b"); t!(s: "a\\b\\c", dirname_str, "a\\b"); t!(s: "\\a\\b\\c", dirname_str, "\\a\\b"); t!(s: "a", dirname_str, "."); @@ -1441,7 +1432,7 @@ mod tests { t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo"); t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a"); - t!(v: b!("hi\\there.txt"), filestem, Some(b!("there"))); + t!(v: b"hi\\there.txt", filestem, Some(b"there")); t!(s: "hi\\there.txt", filestem_str, "there"); t!(s: "hi\\there", filestem_str, "there"); t!(s: "there.txt", filestem_str, "there"); @@ -1456,8 +1447,8 @@ mod tests { t!(s: "..\\..", filestem_str, None, opt); // filestem is based on filename, so we don't need the full set of prefix tests - t!(v: b!("hi\\there.txt"), extension, Some(b!("txt"))); - t!(v: b!("hi\\there"), extension, None); + t!(v: b"hi\\there.txt", extension, Some(b"txt")); + t!(v: b"hi\\there", extension, None); t!(s: "hi\\there.txt", extension_str, Some("txt"), opt); t!(s: "hi\\there", extension_str, None, opt); t!(s: "there.txt", extension_str, Some("txt"), opt); @@ -1583,10 +1574,10 @@ mod tests { t!(s: "a\\b\\c", ["d", "\\e"], "\\e"); t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f"); t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e"); - t!(v: b!("a\\b\\c"), [b!("d"), b!("e")], b!("a\\b\\c\\d\\e")); - t!(v: b!("a\\b\\c"), [b!("d"), b!("\\e"), b!("f")], b!("\\e\\f")); - t!(v: b!("a\\b\\c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))], - b!("a\\b\\c\\d\\e")); + t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e"); + t!(v: b"a\\b\\c", [b"d", b"\\e", b"f"], b"\\e\\f"); + t!(v: b"a\\b\\c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")], + b"a\\b\\c\\d\\e"); } #[test] @@ -1604,11 +1595,11 @@ mod tests { assert!(result == $right); } ); - (v: [$($path:expr),+], [$($left:expr),+], $right:expr) => ( + (b: $path:expr, $left:expr, $right:expr) => ( { - let mut p = Path::new(b!($($path),+)); + let mut p = Path::new($path); let result = p.pop(); - assert_eq!(p.as_vec(), b!($($left),+)); + assert_eq!(p.as_vec(), $left); assert!(result == $right); } ) @@ -1619,11 +1610,11 @@ mod tests { t!(s: ".", ".", false); t!(s: "\\a", "\\", true); t!(s: "\\", "\\", false); - t!(v: ["a\\b\\c"], ["a\\b"], true); - t!(v: ["a"], ["."], true); - t!(v: ["."], ["."], false); - t!(v: ["\\a"], ["\\"], true); - t!(v: ["\\"], ["\\"], false); + t!(b: b"a\\b\\c", b"a\\b", true); + t!(b: b"a", b".", true); + t!(b: b".", b".", false); + t!(b: b"\\a", b"\\", true); + t!(b: b"\\", b"\\", false); t!(s: "C:\\a\\b", "C:\\a", true); t!(s: "C:\\a", "C:\\", true); @@ -1672,8 +1663,8 @@ mod tests { t!(s: Path::new("a\\b").join("\\c\\d"), "\\c\\d"); t!(s: Path::new(".").join("a\\b"), "a\\b"); t!(s: Path::new("\\").join("a\\b"), "\\a\\b"); - t!(v: Path::new(b!("a\\b\\c")).join(b!("..")), b!("a\\b")); - t!(v: Path::new(b!("\\a\\b\\c")).join(b!("d")), b!("\\a\\b\\c\\d")); + t!(v: Path::new(b"a\\b\\c").join(b".."), b"a\\b"); + t!(v: Path::new(b"\\a\\b\\c").join(b"d"), b"\\a\\b\\c\\d"); // full join testing is covered under test_push_path, so no need for // the full set of prefix tests } @@ -1724,9 +1715,9 @@ mod tests { t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d"); t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f"); t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e"); - t!(v: b!("a\\b\\c"), [b!("d"), b!("e")], b!("a\\b\\c\\d\\e")); - t!(v: b!("a\\b\\c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))], - b!("a\\b\\c\\d\\e")); + t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e"); + t!(v: b"a\\b\\c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")], + b"a\\b\\c\\d\\e"); } #[test] @@ -1839,15 +1830,15 @@ mod tests { ) ) - t!(v: b!("a\\b\\c"), set_filename, with_filename, b!("d")); - t!(v: b!("\\"), set_filename, with_filename, b!("foo")); + t!(v: b"a\\b\\c", set_filename, with_filename, b"d"); + t!(v: b"\\", set_filename, with_filename, b"foo"); t!(s: "a\\b\\c", set_filename, with_filename, "d"); t!(s: "\\", set_filename, with_filename, "foo"); t!(s: ".", set_filename, with_filename, "foo"); t!(s: "a\\b", set_filename, with_filename, ""); t!(s: "a", set_filename, with_filename, ""); - t!(v: b!("hi\\there.txt"), set_extension, with_extension, b!("exe")); + t!(v: b"hi\\there.txt", set_extension, with_extension, b"exe"); t!(s: "hi\\there.txt", set_extension, with_extension, "exe"); t!(s: "hi\\there.", set_extension, with_extension, "txt"); t!(s: "hi\\there", set_extension, with_extension, "txt"); @@ -1894,7 +1885,7 @@ mod tests { ) ) - t!(v: Path::new(b!("a\\b\\c")), Some(b!("c")), b!("a\\b"), Some(b!("c")), None); + t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None); t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None); t!(s: Path::new("."), None, Some("."), None, None); t!(s: Path::new("\\"), None, Some("\\"), None, None); @@ -2250,21 +2241,9 @@ mod tests { assert_eq!(comps, exp); } ); - (v: [$($arg:expr),+], $exp:expr) => ( - { - let path = Path::new(b!($($arg),+)); - let comps = path.str_components().map(|x|x.unwrap()).collect::>(); - let exp: &[&str] = $exp; - assert_eq!(comps.as_slice(), exp); - let comps = path.str_components().rev().map(|x|x.unwrap()) - .collect::>(); - let exp = exp.iter().rev().map(|&x|x).collect::>(); - assert_eq!(comps, exp); - } - ) ) - t!(v: ["a\\b\\c"], ["a", "b", "c"]); + t!(s: b"a\\b\\c", ["a", "b", "c"]); t!(s: "a\\b\\c", ["a", "b", "c"]); t!(s: "a\\b\\d", ["a", "b", "d"]); t!(s: "a\\b\\cd", ["a", "b", "cd"]); @@ -2320,8 +2299,8 @@ mod tests { ) ) - t!(s: "a\\b\\c", [b!("a"), b!("b"), b!("c")]); - t!(s: ".", [b!(".")]); + t!(s: "a\\b\\c", [b"a", b"b", b"c"]); + t!(s: ".", [b"."]); // since this is really a wrapper around str_components, those tests suffice } diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index b87a25d4a44a2..658c28f820272 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -19,6 +19,14 @@ use ext::build::AstBuilder; pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { + cx.span_warn(sp, "`bytes!` is deprecated, use `b\"foo\"` literals instead"); + cx.parse_sess.span_diagnostic.span_note(sp, + "see http://doc.rust-lang.org/rust.html#byte-and-byte-string-literals \ + for documentation"); + cx.parse_sess.span_diagnostic.span_note(sp, + "see https://github.com/rust-lang/rust/blob/master/src/etc/2014-06-rewrite-bytes-macros.py \ + for a automated migration"); + // Gather all argument expressions let exprs = match get_exprs_from_tts(cx, sp, tts) { None => return DummyResult::expr(sp), diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index b49c698486450..1a7063c495199 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -106,7 +106,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) *dst = (*src).clone(); } - for c in cap.iter().map(|&x| x) { + for &c in cap.iter() { let cur = c as char; let mut old_state = state; match state { @@ -575,25 +575,25 @@ mod test { #[test] fn test_basic_setabf() { - let s = bytes!("\\E[48;5;%p1%dm"); + let s = b"\\E[48;5;%p1%dm"; assert_eq!(expand(s, [Number(1)], &mut Variables::new()).unwrap(), - bytes!("\\E[48;5;1m").iter().map(|x| *x).collect()); + "\\E[48;5;1m".bytes().collect()); } #[test] fn test_multiple_int_constants() { - assert_eq!(expand(bytes!("%{1}%{2}%d%d"), [], &mut Variables::new()).unwrap(), - bytes!("21").iter().map(|x| *x).collect()); + assert_eq!(expand(b"%{1}%{2}%d%d", [], &mut Variables::new()).unwrap(), + "21".bytes().collect()); } #[test] fn test_op_i() { let mut vars = Variables::new(); - assert_eq!(expand(bytes!("%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d"), + assert_eq!(expand(b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d", [Number(1),Number(2),Number(3)], &mut vars), - Ok(bytes!("123233").iter().map(|x| *x).collect())); - assert_eq!(expand(bytes!("%p1%d%p2%d%i%p1%d%p2%d"), [], &mut vars), - Ok(bytes!("0011").iter().map(|x| *x).collect())); + Ok("123233".bytes().collect())); + assert_eq!(expand(b"%p1%d%p2%d%i%p1%d%p2%d", [], &mut vars), + Ok("0011".bytes().collect())); } #[test] @@ -610,7 +610,7 @@ mod test { } else { Number(97) }; - let res = expand(bytes!("%p1").iter().map(|x| *x).collect::>() + let res = expand("%p1".bytes().collect::>() .append(cap.as_bytes()).as_slice(), [p], vars); @@ -622,13 +622,13 @@ mod test { let res = expand(cap.as_bytes(), [], vars); assert!(res.is_err(), "Binop {} succeeded incorrectly with 0 stack entries", *cap); - let res = expand(bytes!("%{1}").iter().map(|x| *x).collect::>() + let res = expand("%{1}".bytes().collect::>() .append(cap.as_bytes()).as_slice(), [], vars); assert!(res.is_err(), "Binop {} succeeded incorrectly with 1 stack entry", *cap); - let res = expand(bytes!("%{1}%{2}").iter().map(|x| *x).collect::>() + let res = expand("%{1}%{2}".bytes().collect::>() .append(cap.as_bytes()).as_slice(), [], vars); @@ -639,7 +639,7 @@ mod test { #[test] fn test_push_bad_param() { - assert!(expand(bytes!("%pa"), [], &mut Variables::new()).is_err()); + assert!(expand(b"%pa", [], &mut Variables::new()).is_err()); } #[test] @@ -664,39 +664,37 @@ mod test { #[test] fn test_conditionals() { let mut vars = Variables::new(); - let s = bytes!("\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"); + let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"; let res = expand(s, [Number(1)], &mut vars); assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), - bytes!("\\E[31m").iter().map(|x| *x).collect()); + "\\E[31m".bytes().collect()); let res = expand(s, [Number(8)], &mut vars); assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), - bytes!("\\E[90m").iter().map(|x| *x).collect()); + "\\E[90m".bytes().collect()); let res = expand(s, [Number(42)], &mut vars); assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), - bytes!("\\E[38;5;42m").iter().map(|x| *x).collect()); + "\\E[38;5;42m".bytes().collect()); } #[test] fn test_format() { let mut varstruct = Variables::new(); let vars = &mut varstruct; - assert_eq!(expand(bytes!("%p1%s%p2%2s%p3%2s%p4%.2s"), + assert_eq!(expand(b"%p1%s%p2%2s%p3%2s%p4%.2s", [String("foo".to_string()), String("foo".to_string()), String("f".to_string()), String("foo".to_string())], vars), - Ok(bytes!("foofoo ffo").iter().map(|x| *x).collect())); - assert_eq!(expand(bytes!("%p1%:-4.2s"), [String("foo".to_string())], vars), - Ok(bytes!("fo ").iter().map(|x| *x).collect())); - - assert_eq!(expand(bytes!("%p1%d%p1%.3d%p1%5d%p1%:+d"), [Number(1)], vars), - Ok(bytes!("1001 1+1").iter().map(|x| *x).collect())); - assert_eq!(expand(bytes!("%p1%o%p1%#o%p2%6.4x%p2%#6.4X"), [Number(15), Number(27)], vars), - Ok(bytes!("17017 001b0X001B").iter() - .map(|x| *x) - .collect())); + Ok("foofoo ffo".bytes().collect())); + assert_eq!(expand(b"%p1%:-4.2s", [String("foo".to_string())], vars), + Ok("fo ".bytes().collect())); + + assert_eq!(expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", [Number(1)], vars), + Ok("1001 1+1".bytes().collect())); + assert_eq!(expand(b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X", [Number(15), Number(27)], vars), + Ok("17017 001b0X001B".bytes().collect())); } } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index b373753613d76..916342b67434e 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -315,10 +315,10 @@ pub fn parse(file: &mut io::Reader, longnames: bool) /// Create a dummy TermInfo struct for msys terminals pub fn msys_terminfo() -> Box { let mut strings = HashMap::new(); - strings.insert("sgr0".to_string(), Vec::from_slice(bytes!("\x1b[0m"))); - strings.insert("bold".to_string(), Vec::from_slice(bytes!("\x1b[1m"))); - strings.insert("setaf".to_string(), Vec::from_slice(bytes!("\x1b[3%p1%dm"))); - strings.insert("setab".to_string(), Vec::from_slice(bytes!("\x1b[4%p1%dm"))); + strings.insert("sgr0".to_string(), Vec::from_slice(b"\x1B[0m")); + strings.insert("bold".to_string(), Vec::from_slice(b"\x1B[1m")); + strings.insert("setaf".to_string(), Vec::from_slice(b"\x1B[3%p1%dm")); + strings.insert("setab".to_string(), Vec::from_slice(b"\x1B[4%p1%dm")); box TermInfo { names: vec!("cygwin".to_string()), // msys is a fork of an older cygwin version bools: HashMap::new(), diff --git a/src/snapshots.txt b/src/snapshots.txt index d528cb16e72dc..e46c99cf4f0dd 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2014-06-18 d6736a1 + freebsd-x86_64 c1479bb3dc0ae3d8ba9193ff2caf92c805a95c51 + linux-i386 bb1543b21235a51e81460b9419e112396ccf1d20 + linux-x86_64 08df93f138bc6c9d083d28bb71384fcebf0380c1 + macos-i386 d6c0039ad7cbd5959e69c980ecf822e5097bac2c + macos-x86_64 ee54924aa4103d35cf490da004d3cc4e48ca8fb0 + winnt-i386 943c99971e82847abe272df58bb7656ac3b91430 + S 2014-06-14 2c6caad freebsd-x86_64 0152ba43f238014f0aede7c29f1c684c21077b0b linux-i386 2eb1897c25abe0d5978ff03171ca943e92666046 diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs index df2c40657c814..5f8352d1e5229 100644 --- a/src/test/compile-fail/macros-nonfatal-errors.rs +++ b/src/test/compile-fail/macros-nonfatal-errors.rs @@ -22,7 +22,8 @@ enum CantDeriveThose {} fn main() { doesnt_exist!(); //~ ERROR - bytes!(invalid); //~ ERROR + bytes!(invalid); //~ ERROR non-literal in bytes! + //~^ WARN `bytes!` is deprecated asm!(invalid); //~ ERROR diff --git a/src/test/compile-fail/syntax-extension-bytes-non-ascii-char-literal.rs b/src/test/compile-fail/syntax-extension-bytes-non-ascii-char-literal.rs index f5b4342ceb749..d03696cbbbcc4 100644 --- a/src/test/compile-fail/syntax-extension-bytes-non-ascii-char-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-non-ascii-char-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!('λ'); //~ ERROR non-ascii char literal in bytes! + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/compile-fail/syntax-extension-bytes-non-literal.rs b/src/test/compile-fail/syntax-extension-bytes-non-literal.rs index 281a5630f82c9..3a2e104818fd2 100644 --- a/src/test/compile-fail/syntax-extension-bytes-non-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-non-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!(foo); //~ ERROR non-literal in bytes! + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/compile-fail/syntax-extension-bytes-too-large-integer-literal.rs b/src/test/compile-fail/syntax-extension-bytes-too-large-integer-literal.rs index 25688d7d17ab4..8e7c6147758ca 100644 --- a/src/test/compile-fail/syntax-extension-bytes-too-large-integer-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-too-large-integer-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!(1024); //~ ERROR too large integer literal in bytes! + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/compile-fail/syntax-extension-bytes-too-large-u8-literal.rs b/src/test/compile-fail/syntax-extension-bytes-too-large-u8-literal.rs index d1c8a2c091304..1a9aa3753eec7 100644 --- a/src/test/compile-fail/syntax-extension-bytes-too-large-u8-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-too-large-u8-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!(1024u8); //~ ERROR too large u8 literal in bytes! + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/compile-fail/syntax-extension-bytes-too-small-integer-literal.rs b/src/test/compile-fail/syntax-extension-bytes-too-small-integer-literal.rs index ef45ea06003d5..c2d4973594371 100644 --- a/src/test/compile-fail/syntax-extension-bytes-too-small-integer-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-too-small-integer-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!(-1024); //~ ERROR non-literal in bytes + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/compile-fail/syntax-extension-bytes-too-small-u8-literal.rs b/src/test/compile-fail/syntax-extension-bytes-too-small-u8-literal.rs index b8ba73559aa74..ac33ffb60e294 100644 --- a/src/test/compile-fail/syntax-extension-bytes-too-small-u8-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-too-small-u8-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!(-1024u8); //~ ERROR non-literal in bytes + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/compile-fail/syntax-extension-bytes-unsupported-literal.rs b/src/test/compile-fail/syntax-extension-bytes-unsupported-literal.rs index 142566fe8ab78..f6b3659354c5b 100644 --- a/src/test/compile-fail/syntax-extension-bytes-unsupported-literal.rs +++ b/src/test/compile-fail/syntax-extension-bytes-unsupported-literal.rs @@ -10,4 +10,5 @@ fn main() { let vec = bytes!(45f64); //~ ERROR unsupported literal in bytes! + //~^ WARN `bytes!` is deprecated } diff --git a/src/test/run-pass/issue-4333.rs b/src/test/run-pass/issue-4333.rs index 6fb66cd3b1580..fd67b767104d5 100644 --- a/src/test/run-pass/issue-4333.rs +++ b/src/test/run-pass/issue-4333.rs @@ -12,5 +12,5 @@ use std::io; pub fn main() { let stdout = &mut io::stdout() as &mut io::Writer; - stdout.write(bytes!("Hello!")); + stdout.write(b"Hello!"); } diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 316d1facb18ff..4355bf4127fc4 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -29,7 +29,7 @@ fn test_tempdir() { let path = { let p = TempDir::new_in(&Path::new("."), "foobar").unwrap(); let p = p.path(); - assert!(p.as_vec().ends_with(bytes!("foobar"))); + assert!(p.as_vec().ends_with(b"foobar")); p.clone() }; assert!(!path.exists()); diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs index 1d229a8ae8361..55beebbf2bc57 100644 --- a/src/test/run-pass/trait-coercion.rs +++ b/src/test/run-pass/trait-coercion.rs @@ -26,7 +26,7 @@ impl Trait for Struct { } fn foo(mut a: Box) { - a.write(bytes!("Hello\n")); + a.write(b"Hello\n"); } pub fn main() { From 72f0d4535715505c1cc429ef277a954ba26366bd Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 19 Jun 2014 00:59:40 +0200 Subject: [PATCH 24/25] Revert bytes!() docstring change, and fix a typo. --- src/libstd/macros.rs | 2 +- src/libsyntax/ext/bytes.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index dad162d82ad47..58f65c90b3b10 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -463,7 +463,7 @@ pub mod builtin { /// # Example /// /// ``` - /// let rust = b"rust\xFF"; + /// let rust = bytes!("r", 'u', "st", 255); /// assert_eq!(rust[1], 'u' as u8); /// assert_eq!(rust[4], 255); /// ``` diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index 658c28f820272..ce13fa2a7c6ee 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -25,7 +25,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) for documentation"); cx.parse_sess.span_diagnostic.span_note(sp, "see https://github.com/rust-lang/rust/blob/master/src/etc/2014-06-rewrite-bytes-macros.py \ - for a automated migration"); + for an automated migration"); // Gather all argument expressions let exprs = match get_exprs_from_tts(cx, sp, tts) { From 2c3bf8836f6f0cd18d8ac4f7189615f7f4098f5d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 18 Jun 2014 17:05:15 -0700 Subject: [PATCH 25/25] Merge conflicts from the rollup Closes #14480 (vim: Add :RustRun and associated commands) Closes #14917 (Deprecate free-standing endian conversions in favor of methods on Int. Merge Bitwise into Int and add more bit operations.) Closes #14981 (librustc: Use expr_ty_adjusted in trans_overloaded_call.) Closes #14989 (std::task - Revamp TaskBuilder API) Closes #14997 (Reject double moves out of array elements) Closes #14998 (Vim: highlight escapes for byte literals.) Closes #15002 (Fix FIXME #5275) Closes #15004 (Fix #14865) Closes #15007 (debuginfo: Add test case for issue #14411.) Closes #15012 ((doc) Change search placeholder text.) Closes #15013 (Update compiler-rt.) Closes #15017 (Deprecate the bytes!() macro.) --- src/liballoc/heap.rs | 2 +- src/librustc/middle/borrowck/move_data.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 79a616b9555aa..b4d0057778a1a 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -132,7 +132,7 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, mod imp { use core::option::{None, Option}; use core::ptr::{RawPtr, mut_null, null}; - use core::num::Bitwise; + use core::num::Int; use libc::{c_char, c_int, c_void, size_t}; #[link(name = "jemalloc", kind = "static")] diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index 9c2194c74f4a4..b61596908e60a 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -163,7 +163,7 @@ pub type AssignDataFlow<'a> = DataFlowContext<'a, AssignDataFlowOperator>; fn loan_path_is_precise(loan_path: &LoanPath) -> bool { match *loan_path { - LpVar(_) => { + LpVar(_) | LpUpvar(_) => { true } LpExtend(_, _, LpInterior(mc::InteriorElement(_))) => {