Auto merge of #38148 - frewsxcv:rollup, r=frewsxcv

Rollup of 15 pull requests

- Successful merges: #37859, #37919, #38020, #38028, #38029, #38065, #38073, #38077, #38089, #38090, #38096, #38112, #38113, #38130, #38141
- Failed merges:
This commit is contained in:
bors 2016-12-03 20:59:08 +00:00
commit 28d6623bcc
21 changed files with 738 additions and 93 deletions

View File

@ -32,7 +32,7 @@ The script accepts commands, flags, and filters to determine what to do:
# build the whole compiler
./x.py build
# build the stage1 compier
# build the stage1 compiler
./x.py build --stage 1
# build stage0 libstd

View File

@ -589,11 +589,11 @@ please see the [Documentation chapter](documentation.html).
# Testing and concurrency
One thing that is important to note when writing tests are run concurrently
using threads. For this reason you should take care that your tests are written
in such a way as to not depend on each-other, or on any shared state. "Shared
state" can also include the environment, such as the current working directory,
or environment variables.
One thing that is important to note when writing tests is that they may be run
concurrently using threads. For this reason you should take care that your tests
are written in such a way as to not depend on each-other, or on any shared
state. "Shared state" can also include the environment, such as the current
working directory, or environment variables.
If this is an issue it is possible to control this concurrency, either by
setting the environment variable `RUST_TEST_THREADS`, or by passing the argument

View File

@ -740,13 +740,14 @@ There are several kinds of item:
* [`extern crate` declarations](#extern-crate-declarations)
* [`use` declarations](#use-declarations)
* [modules](#modules)
* [functions](#functions)
* [function definitions](#functions)
* [`extern` blocks](#external-blocks)
* [type definitions](grammar.html#type-definitions)
* [structs](#structs)
* [enumerations](#enumerations)
* [struct definitions](#structs)
* [enumeration definitions](#enumerations)
* [constant items](#constant-items)
* [static items](#static-items)
* [traits](#traits)
* [trait definitions](#traits)
* [implementations](#implementations)
Some items form an implicit scope for the declaration of sub-items. In other

View File

@ -23,7 +23,6 @@ use std::fs::File;
use std::io::{BufRead, Read};
use std::path::Path;
use syntax::parse;
use syntax::parse::lexer;
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config};
@ -31,15 +30,16 @@ use rustc::middle::cstore::DummyCrateStore;
use std::rc::Rc;
use syntax::ast;
use syntax::ast::Name;
use syntax::codemap;
use syntax::parse::token::{self, BinOpToken, DelimToken, Lit, Token};
use syntax::parse::lexer::TokenAndSpan;
use syntax_pos::Pos;
use syntax::symbol::{Symbol, keywords};
fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
fn id() -> token::Token {
Token::Ident(ast::Ident::with_empty_ctxt(Name(0)))
Token::Ident(ast::Ident::with_empty_ctxt(keywords::Invalid.name()))
}
let mut res = HashMap::new();
@ -65,7 +65,7 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"SHL" => Token::BinOp(BinOpToken::Shl),
"LBRACE" => Token::OpenDelim(DelimToken::Brace),
"RARROW" => Token::RArrow,
"LIT_STR" => Token::Literal(Lit::Str_(Name(0)), None),
"LIT_STR" => Token::Literal(Lit::Str_(keywords::Invalid.name()), None),
"DOTDOT" => Token::DotDot,
"MOD_SEP" => Token::ModSep,
"DOTDOTDOT" => Token::DotDotDot,
@ -75,21 +75,22 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"ANDAND" => Token::AndAnd,
"AT" => Token::At,
"LBRACKET" => Token::OpenDelim(DelimToken::Bracket),
"LIT_STR_RAW" => Token::Literal(Lit::StrRaw(Name(0), 0), None),
"LIT_STR_RAW" => Token::Literal(Lit::StrRaw(keywords::Invalid.name(), 0), None),
"RPAREN" => Token::CloseDelim(DelimToken::Paren),
"SLASH" => Token::BinOp(BinOpToken::Slash),
"COMMA" => Token::Comma,
"LIFETIME" => Token::Lifetime(ast::Ident::with_empty_ctxt(Name(0))),
"LIFETIME" => Token::Lifetime(
ast::Ident::with_empty_ctxt(keywords::Invalid.name())),
"CARET" => Token::BinOp(BinOpToken::Caret),
"TILDE" => Token::Tilde,
"IDENT" => id(),
"PLUS" => Token::BinOp(BinOpToken::Plus),
"LIT_CHAR" => Token::Literal(Lit::Char(Name(0)), None),
"LIT_BYTE" => Token::Literal(Lit::Byte(Name(0)), None),
"LIT_CHAR" => Token::Literal(Lit::Char(keywords::Invalid.name()), None),
"LIT_BYTE" => Token::Literal(Lit::Byte(keywords::Invalid.name()), None),
"EQ" => Token::Eq,
"RBRACKET" => Token::CloseDelim(DelimToken::Bracket),
"COMMENT" => Token::Comment,
"DOC_COMMENT" => Token::DocComment(Name(0)),
"DOC_COMMENT" => Token::DocComment(keywords::Invalid.name()),
"DOT" => Token::Dot,
"EQEQ" => Token::EqEq,
"NE" => Token::Ne,
@ -99,9 +100,9 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"BINOP" => Token::BinOp(BinOpToken::Plus),
"POUND" => Token::Pound,
"OROR" => Token::OrOr,
"LIT_INTEGER" => Token::Literal(Lit::Integer(Name(0)), None),
"LIT_INTEGER" => Token::Literal(Lit::Integer(keywords::Invalid.name()), None),
"BINOPEQ" => Token::BinOpEq(BinOpToken::Plus),
"LIT_FLOAT" => Token::Literal(Lit::Float(Name(0)), None),
"LIT_FLOAT" => Token::Literal(Lit::Float(keywords::Invalid.name()), None),
"WHITESPACE" => Token::Whitespace,
"UNDERSCORE" => Token::Underscore,
"MINUS" => Token::BinOp(BinOpToken::Minus),
@ -111,10 +112,11 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"OR" => Token::BinOp(BinOpToken::Or),
"GT" => Token::Gt,
"LE" => Token::Le,
"LIT_BINARY" => Token::Literal(Lit::ByteStr(Name(0)), None),
"LIT_BINARY_RAW" => Token::Literal(Lit::ByteStrRaw(Name(0), 0), None),
"LIT_BINARY" => Token::Literal(Lit::ByteStr(keywords::Invalid.name()), None),
"LIT_BINARY_RAW" => Token::Literal(
Lit::ByteStrRaw(keywords::Invalid.name(), 0), None),
"QUESTION" => Token::Question,
"SHEBANG" => Token::Shebang(Name(0)),
"SHEBANG" => Token::Shebang(keywords::Invalid.name()),
_ => continue,
};
@ -158,7 +160,7 @@ fn fix(mut lit: &str) -> ast::Name {
let leading_hashes = count(lit);
// +1/-1 to adjust for single quotes
parse::token::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1])
Symbol::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1])
}
/// Assuming a char/byte literal, strip the 'b' prefix and the single quotes.
@ -168,7 +170,7 @@ fn fixchar(mut lit: &str) -> ast::Name {
lit = &lit[1..];
}
parse::token::intern(&lit[1..lit.len() - 1])
Symbol::intern(&lit[1..lit.len() - 1])
}
fn count(lit: &str) -> usize {
@ -196,7 +198,7 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>, surrogate_
let not_found = format!("didn't find token {:?} in the map", toknum);
let proto_tok = tokens.get(toknum).expect(&not_found[..]);
let nm = parse::token::intern(content);
let nm = Symbol::intern(content);
debug!("What we got: content (`{}`), proto: {:?}", content, proto_tok);

View File

@ -659,6 +659,16 @@ impl<T> Option<T> {
impl<'a, T: Clone> Option<&'a T> {
/// Maps an `Option<&T>` to an `Option<T>` by cloning the contents of the
/// option.
///
/// # Examples
///
/// ```
/// let x = 12;
/// let opt_x = Some(&x);
/// assert_eq!(opt_x, Some(&12));
/// let cloned = opt_x.cloned();
/// assert_eq!(cloned, Some(12));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn cloned(self) -> Option<T> {
self.map(|t| t.clone())

View File

@ -886,6 +886,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"enable incremental compilation (experimental)"),
incremental_info: bool = (false, parse_bool, [UNTRACKED],
"print high-level information about incremental reuse (or the lack thereof)"),
incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
"dump hash information in textual format to stdout"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],

View File

@ -24,6 +24,7 @@ use std::path::Path;
use std::fs::File;
use std::env;
use rustc::session::Session;
use rustc::session::config::nightly_options;
/// The first few bytes of files generated by incremental compilation
@ -59,7 +60,7 @@ pub fn write_file_header<W: io::Write>(stream: &mut W) -> io::Result<()> {
/// incompatible version of the compiler.
/// - Returns `Err(..)` if some kind of IO error occurred while reading the
/// file.
pub fn read_file(path: &Path) -> io::Result<Option<Vec<u8>>> {
pub fn read_file(sess: &Session, path: &Path) -> io::Result<Option<Vec<u8>>> {
if !path.exists() {
return Ok(None);
}
@ -72,6 +73,7 @@ pub fn read_file(path: &Path) -> io::Result<Option<Vec<u8>>> {
let mut file_magic = [0u8; 4];
file.read_exact(&mut file_magic)?;
if file_magic != FILE_MAGIC {
report_format_mismatch(sess, path, "Wrong FILE_MAGIC");
return Ok(None)
}
}
@ -85,6 +87,7 @@ pub fn read_file(path: &Path) -> io::Result<Option<Vec<u8>>> {
((header_format_version[1] as u16) << 8);
if header_format_version != HEADER_FORMAT_VERSION {
report_format_mismatch(sess, path, "Wrong HEADER_FORMAT_VERSION");
return Ok(None)
}
}
@ -99,6 +102,7 @@ pub fn read_file(path: &Path) -> io::Result<Option<Vec<u8>>> {
file.read_exact(&mut buffer[..])?;
if &buffer[..] != rustc_version().as_bytes() {
report_format_mismatch(sess, path, "Different compiler version");
return Ok(None);
}
}
@ -109,6 +113,16 @@ pub fn read_file(path: &Path) -> io::Result<Option<Vec<u8>>> {
Ok(Some(data))
}
fn report_format_mismatch(sess: &Session, file: &Path, message: &str) {
debug!("read_file: {}", message);
if sess.opts.debugging_opts.incremental_info {
println!("incremental: ignoring cache artifact `{}`: {}",
file.file_name().unwrap().to_string_lossy(),
message);
}
}
fn rustc_version() -> String {
if nightly_options::is_nightly_build() {
if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") {

View File

@ -435,8 +435,8 @@ fn copy_files(target_dir: &Path,
}
if print_stats_on_success {
println!("incr. comp. session directory: {} files hard-linked", files_linked);
println!("incr. comp. session directory: {} files copied", files_copied);
println!("incremental: session directory: {} files hard-linked", files_linked);
println!("incremental: session directory: {} files copied", files_copied);
}
Ok(files_linked > 0 || files_copied == 0)

View File

@ -156,7 +156,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
let hashes_file_path = metadata_hash_import_path(&session_dir);
match file_format::read_file(&hashes_file_path)
match file_format::read_file(self.tcx.sess, &hashes_file_path)
{
Ok(Some(data)) => {
match self.load_from_data(cnum, &data, svh) {

View File

@ -93,7 +93,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
match file_format::read_file(path) {
match file_format::read_file(sess, path) {
Ok(Some(data)) => return Some(data),
Ok(None) => {
// The file either didn't exist or was produced by an incompatible
@ -132,6 +132,10 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let prev_commandline_args_hash = u64::decode(&mut dep_graph_decoder)?;
if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() {
if tcx.sess.opts.debugging_opts.incremental_info {
println!("incremental: completely ignoring cache because of \
differing commandline arguments");
}
// We can't reuse the cache, purge it.
debug!("decode_dep_graph: differing commandline arg hashes");
for swp in work_products {
@ -192,7 +196,8 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if tcx.sess.opts.debugging_opts.incremental_info {
// It'd be nice to pretty-print these paths better than just
// using the `Debug` impls, but wev.
println!("module {:?} is dirty because {:?} changed or was removed",
println!("incremental: module {:?} is dirty because {:?} \
changed or was removed",
target_node,
raw_source_node.map_def(|&index| {
Some(directory.def_path_string(tcx, index))
@ -250,11 +255,24 @@ fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
current_hash);
continue;
}
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
println!("node {:?} is dirty as hash is {:?} was {:?}",
dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
current_hash,
hash.hash);
}
debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
current_hash,
hash.hash);
} else {
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
println!("node {:?} is dirty as it was removed",
hash.dep_node);
}
debug!("initial_dirty_nodes: {:?} is dirty as it was removed",
hash.dep_node);
}
@ -277,14 +295,19 @@ fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
delete_dirty_work_product(tcx, swp);
} else {
let all_files_exist =
swp.work_product
.saved_files
.iter()
.all(|&(_, ref file_name)| {
let path = in_incr_comp_dir_sess(tcx.sess, &file_name);
path.exists()
});
let mut all_files_exist = true;
for &(_, ref file_name) in swp.work_product.saved_files.iter() {
let path = in_incr_comp_dir_sess(tcx.sess, file_name);
if !path.exists() {
all_files_exist = false;
if tcx.sess.opts.debugging_opts.incremental_info {
println!("incremental: could not find file for up-to-date work product: {}",
path.display());
}
}
}
if all_files_exist {
debug!("reconcile_work_products: all files for {:?} exist", swp);
tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product);
@ -331,7 +354,7 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
debug!("load_prev_metadata_hashes() - File: {}", file_path.display());
let data = match file_format::read_file(&file_path) {
let data = match file_format::read_file(tcx.sess, &file_path) {
Ok(Some(data)) => data,
Ok(None) => {
debug!("load_prev_metadata_hashes() - File produced by incompatible \

View File

@ -159,6 +159,12 @@ pub fn encode_dep_graph(preds: &Predecessors,
}
}
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
for (dep_node, hash) in &preds.hashes {
println!("HIR hash for {:?} is {}", dep_node, hash);
}
}
// Create the serialized dep-graph.
let graph = SerializedDepGraph {
edges: edges,
@ -248,6 +254,15 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
let hash = state.finish();
debug!("save: metadata hash for {:?} is {}", def_id, hash);
if tcx.sess.opts.debugging_opts.incremental_dump_hash {
println!("metadata hash for {:?} is {}", def_id, hash);
for dep_node in sources {
println!("metadata hash for {:?} depends on {:?} with hash {}",
def_id, dep_node, preds.hashes[dep_node]);
}
}
serialized_hashes.hashes.push(SerializedMetadataHash {
def_index: def_id.index,
hash: hash,

View File

@ -1981,6 +1981,11 @@ fn trans_reuse_previous_work_products(tcx: TyCtxt,
debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
return Some(work_product);
} else {
if tcx.sess.opts.debugging_opts.incremental_info {
println!("incremental: CGU `{}` invalidated because of \
changed partitioning hash.",
cgu.name());
}
debug!("trans_reuse_previous_work_products: \
not reusing {:?} because hash changed to {:?}",
work_product, hash);

View File

@ -884,10 +884,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// those that do.
self.ensure_super_predicates(binding.span, trait_ref.def_id())?;
let candidates: Vec<ty::PolyTraitRef> =
let candidates =
traits::supertraits(tcx, trait_ref.clone())
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name))
.collect();
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name));
let candidate = self.one_bound_for_assoc_type(candidates,
&trait_ref.to_string(),
@ -1191,10 +1190,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// Check that there is exactly one way to find an associated type with the
// correct name.
let suitable_bounds: Vec<_> =
let suitable_bounds =
traits::transitive_bounds(tcx, &bounds)
.filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name))
.collect();
.filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name));
self.one_bound_for_assoc_type(suitable_bounds,
&ty_param_name.as_str(),
@ -1205,31 +1203,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// Checks that bounds contains exactly one element and reports appropriate
// errors otherwise.
fn one_bound_for_assoc_type(&self,
bounds: Vec<ty::PolyTraitRef<'tcx>>,
fn one_bound_for_assoc_type<I>(&self,
mut bounds: I,
ty_param_name: &str,
assoc_name: &str,
span: Span)
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
where I: Iterator<Item=ty::PolyTraitRef<'tcx>>
{
if bounds.is_empty() {
struct_span_err!(self.tcx().sess, span, E0220,
"associated type `{}` not found for `{}`",
assoc_name,
ty_param_name)
.span_label(span, &format!("associated type `{}` not found", assoc_name))
.emit();
return Err(ErrorReported);
}
if bounds.len() > 1 {
let spans = bounds.iter().map(|b| {
self.tcx().associated_items(b.def_id()).find(|item| {
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
})
.and_then(|item| self.tcx().map.span_if_local(item.def_id))
});
let bound = match bounds.next() {
Some(bound) => bound,
None => {
struct_span_err!(self.tcx().sess, span, E0220,
"associated type `{}` not found for `{}`",
assoc_name,
ty_param_name)
.span_label(span, &format!("associated type `{}` not found", assoc_name))
.emit();
return Err(ErrorReported);
}
};
if let Some(bound2) = bounds.next() {
let bounds = iter::once(bound).chain(iter::once(bound2)).chain(bounds);
let mut err = struct_span_err!(
self.tcx().sess, span, E0221,
"ambiguous associated type `{}` in bounds of `{}`",
@ -1237,22 +1233,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
ty_param_name);
err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name));
for span_and_bound in spans.zip(&bounds) {
if let Some(span) = span_and_bound.0 {
for bound in bounds {
let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| {
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
})
.and_then(|item| self.tcx().map.span_if_local(item.def_id));
if let Some(span) = bound_span {
err.span_label(span, &format!("ambiguous `{}` from `{}`",
assoc_name,
span_and_bound.1));
bound));
} else {
span_note!(&mut err, span,
"associated type `{}` could derive from `{}`",
ty_param_name,
span_and_bound.1);
bound);
}
}
err.emit();
}
Ok(bounds[0].clone())
return Ok(bound);
}
// Create a type from a path to an associated type.
@ -1293,11 +1294,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
return (tcx.types.err, Def::Err);
}
let candidates: Vec<ty::PolyTraitRef> =
let candidates =
traits::supertraits(tcx, ty::Binder(trait_ref))
.filter(|r| self.trait_defines_associated_type_named(r.def_id(),
assoc_name))
.collect();
assoc_name));
match self.one_bound_for_assoc_type(candidates,
"Self",

View File

@ -1101,7 +1101,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} else {
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0323,
"item `{}` is an associated const, \
which doesn't match its trait `{:?}`",
which doesn't match its trait `{}`",
ty_impl_item.name,
impl_trait_ref);
err.span_label(impl_item.span, &format!("does not match trait"));
@ -1139,7 +1139,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} else {
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324,
"item `{}` is an associated method, \
which doesn't match its trait `{:?}`",
which doesn't match its trait `{}`",
ty_impl_item.name,
impl_trait_ref);
err.span_label(impl_item.span, &format!("does not match trait"));
@ -1157,7 +1157,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} else {
let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325,
"item `{}` is an associated type, \
which doesn't match its trait `{:?}`",
which doesn't match its trait `{}`",
ty_impl_item.name,
impl_trait_ref);
err.span_label(impl_item.span, &format!("does not match trait"));

View File

@ -79,8 +79,18 @@ pub enum Ipv6MulticastScope {
impl IpAddr {
/// Returns true for the special 'unspecified' address ([IPv4], [IPv6]).
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
///
/// # Examples
///
/// ```
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
/// ```
#[stable(feature = "ip_shared", since = "1.12.0")]
pub fn is_unspecified(&self) -> bool {
match *self {
@ -90,8 +100,18 @@ impl IpAddr {
}
/// Returns true if this is a loopback address ([IPv4], [IPv6]).
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
///
/// # Examples
///
/// ```
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
/// ```
#[stable(feature = "ip_shared", since = "1.12.0")]
pub fn is_loopback(&self) -> bool {
match *self {
@ -101,8 +121,23 @@ impl IpAddr {
}
/// Returns true if the address appears to be globally routable ([IPv4], [IPv6]).
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// fn main() {
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(),
/// true);
/// }
/// ```
pub fn is_global(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_global(),
@ -111,8 +146,18 @@ impl IpAddr {
}
/// Returns true if this is a multicast address ([IPv4], [IPv6]).
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
///
/// # Examples
///
/// ```
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
/// ```
#[stable(feature = "ip_shared", since = "1.12.0")]
pub fn is_multicast(&self) -> bool {
match *self {
@ -122,8 +167,23 @@ impl IpAddr {
}
/// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]).
///
/// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
/// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// fn main() {
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0))
/// .is_documentation(), true);
/// }
/// ```
pub fn is_documentation(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_documentation(),
@ -132,6 +192,20 @@ impl IpAddr {
}
/// Returns true if this address is a valid IPv4 address, false if it's a valid IPv6 address.
///
/// # Examples
///
/// ```
/// #![feature(ipaddr_checker)]
///
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// fn main() {
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(),
/// false);
/// }
/// ```
#[unstable(feature = "ipaddr_checker", issue = "36949")]
pub fn is_ipv4(&self) -> bool {
match *self {
@ -141,6 +215,20 @@ impl IpAddr {
}
/// Returns true if this address is a valid IPv6 address, false if it's a valid IPv4 address.
///
/// # Examples
///
/// ```
/// #![feature(ipaddr_checker)]
///
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// fn main() {
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(),
/// true);
/// }
/// ```
#[unstable(feature = "ipaddr_checker", issue = "36949")]
pub fn is_ipv6(&self) -> bool {
match *self {
@ -522,6 +610,14 @@ impl Ipv6Addr {
/// Creates a new IPv6 address from eight 16-bit segments.
///
/// The result will represent the IP address a:b:c:d:e:f:g:h.
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
///
/// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
h: u16) -> Ipv6Addr {
@ -538,6 +634,15 @@ impl Ipv6Addr {
}
/// Returns the eight 16-bit segments that make up this address.
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
///
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
/// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn segments(&self) -> [u16; 8] {
let arr = &self.inner.s6_addr;
@ -558,6 +663,15 @@ impl Ipv6Addr {
/// This property is defined in [RFC 4291].
///
/// [RFC 4291]: https://tools.ietf.org/html/rfc4291
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
///
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_unspecified(&self) -> bool {
self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
@ -568,6 +682,15 @@ impl Ipv6Addr {
/// This property is defined in [RFC 4291].
///
/// [RFC 4291]: https://tools.ietf.org/html/rfc4291
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
///
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_loopback(&self) -> bool {
self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
@ -580,6 +703,20 @@ impl Ipv6Addr {
/// - the loopback address
/// - link-local, site-local, and unique local unicast addresses
/// - interface-, link-, realm-, admin- and site-local multicast addresses
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
/// }
/// ```
pub fn is_global(&self) -> bool {
match self.multicast_scope() {
Some(Ipv6MulticastScope::Global) => true,
@ -593,6 +730,20 @@ impl Ipv6Addr {
/// This property is defined in [RFC 4193].
///
/// [RFC 4193]: https://tools.ietf.org/html/rfc4193
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(),
/// false);
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
/// }
/// ```
pub fn is_unique_local(&self) -> bool {
(self.segments()[0] & 0xfe00) == 0xfc00
}
@ -602,12 +753,40 @@ impl Ipv6Addr {
/// This property is defined in [RFC 4291].
///
/// [RFC 4291]: https://tools.ietf.org/html/rfc4291
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
/// false);
/// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
/// }
/// ```
pub fn is_unicast_link_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfe80
}
/// Returns true if this is a deprecated unicast site-local address
/// (fec0::/10).
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
/// false);
/// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
/// }
/// ```
pub fn is_unicast_site_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfec0
}
@ -618,6 +797,20 @@ impl Ipv6Addr {
/// This property is defined in [RFC 3849].
///
/// [RFC 3849]: https://tools.ietf.org/html/rfc3849
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(),
/// false);
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
/// }
/// ```
pub fn is_documentation(&self) -> bool {
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
}
@ -632,6 +825,20 @@ impl Ipv6Addr {
/// - unique local addresses
/// - the unspecified address
/// - the address range reserved for documentation
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(),
/// true);
/// }
/// ```
pub fn is_unicast_global(&self) -> bool {
!self.is_multicast()
&& !self.is_loopback() && !self.is_unicast_link_local()
@ -640,6 +847,20 @@ impl Ipv6Addr {
}
/// Returns the address's multicast scope if the address is multicast.
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::{Ipv6Addr, Ipv6MulticastScope};
///
/// fn main() {
/// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
/// Some(Ipv6MulticastScope::Global));
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
/// }
/// ```
pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
if self.is_multicast() {
match self.segments()[0] & 0x000f {
@ -662,6 +883,14 @@ impl Ipv6Addr {
/// This property is defined by [RFC 4291].
///
/// [RFC 4291]: https://tools.ietf.org/html/rfc4291
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
///
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_multicast(&self) -> bool {
(self.segments()[0] & 0xff00) == 0xff00
@ -671,6 +900,16 @@ impl Ipv6Addr {
/// neither IPv4-compatible or IPv4-mapped.
///
/// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
///
/// ```
/// use std::net::{Ipv4Addr, Ipv6Addr};
///
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
/// Some(Ipv4Addr::new(0, 0, 0, 1)));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
match self.segments() {
@ -683,6 +922,13 @@ impl Ipv6Addr {
}
/// Returns the sixteen eight-bit integers the IPv6 address consists of.
///
/// ```
/// use std::net::Ipv6Addr;
///
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
/// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
/// ```
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
pub fn octets(&self) -> [u8; 16] {
self.inner.s6_addr

View File

@ -48,8 +48,18 @@ pub struct UdpSocket(net_imp::UdpSocket);
impl UdpSocket {
/// Creates a UDP socket from the given address.
///
/// The address type can be any implementor of `ToSocketAddr` trait. See
/// The address type can be any implementor of [`ToSocketAddrs`] trait. See
/// its documentation for concrete examples.
///
/// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
@ -57,6 +67,17 @@ impl UdpSocket {
/// Receives data from the socket. On success, returns the number of bytes
/// read and the address from whence the data came.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// let mut buf = [0; 10];
/// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf)
/// .expect("Didn't receive data");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.0.recv_from(buf)
@ -65,11 +86,24 @@ impl UdpSocket {
/// Sends data on the socket to the given address. On success, returns the
/// number of bytes written.
///
/// Address type can be any implementor of `ToSocketAddrs` trait. See its
/// Address type can be any implementor of [`ToSocketAddrs`] trait. See its
/// documentation for concrete examples.
///
/// This will return an error when the IP version of the local socket
/// does not match that returned from `ToSocketAddrs`
/// does not match that returned from [`ToSocketAddrs`].
///
/// See https://github.com/rust-lang/rust/issues/34202 for more details.
///
/// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
-> io::Result<usize> {
@ -81,6 +115,16 @@ impl UdpSocket {
}
/// Returns the socket address that this socket was created from.
///
/// # Examples
///
/// ```no_run
/// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// assert_eq!(socket.local_addr().unwrap(),
/// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 34254)));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.0.socket_addr()
@ -91,6 +135,15 @@ impl UdpSocket {
/// The returned `UdpSocket` is a reference to the same socket that this
/// object references. Both handles will read and write the same port, and
/// options set on one socket will be propagated to the other.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// let socket_clone = socket.try_clone().expect("couldn't clone the socket");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_clone(&self) -> io::Result<UdpSocket> {
self.0.duplicate().map(UdpSocket)
@ -98,15 +151,30 @@ impl UdpSocket {
/// Sets the read timeout to the timeout specified.
///
/// If the value specified is `None`, then `read` calls will block
/// indefinitely. It is an error to pass the zero `Duration` to this
/// If the value specified is [`None`], then [`read()`] calls will block
/// indefinitely. It is an error to pass the zero [`Duration`] to this
/// method.
///
/// # Note
///
/// Platforms may return a different error code whenever a read times out as
/// a result of setting this option. For example Unix typically returns an
/// error of the kind `WouldBlock`, but Windows may return `TimedOut`.
/// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`read()`]: ../../std/io/trait.Read.html#tymethod.read
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
/// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_read_timeout(None).expect("set_read_timeout call failed");
/// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_read_timeout(dur)
@ -114,15 +182,30 @@ impl UdpSocket {
/// Sets the write timeout to the timeout specified.
///
/// If the value specified is `None`, then `write` calls will block
/// indefinitely. It is an error to pass the zero `Duration` to this
/// If the value specified is [`None`], then [`write()`] calls will block
/// indefinitely. It is an error to pass the zero [`Duration`] to this
/// method.
///
/// # Note
///
/// Platforms may return a different error code whenever a write times out
/// as a result of setting this option. For example Unix typically returns
/// an error of the kind `WouldBlock`, but Windows may return `TimedOut`.
/// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`write()`]: ../../std/io/trait.Write.html#tymethod.write
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
/// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_write_timeout(None).expect("set_write_timeout call failed");
/// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_write_timeout(dur)
@ -130,7 +213,20 @@ impl UdpSocket {
/// Returns the read timeout of this socket.
///
/// If the timeout is `None`, then `read` calls will block indefinitely.
/// If the timeout is [`None`], then [`read()`] calls will block indefinitely.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`read()`]: ../../std/io/trait.Read.html#tymethod.read
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_read_timeout(None).expect("set_read_timeout call failed");
/// assert_eq!(socket.read_timeout().unwrap(), None);
/// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.0.read_timeout()
@ -138,7 +234,20 @@ impl UdpSocket {
/// Returns the write timeout of this socket.
///
/// If the timeout is `None`, then `write` calls will block indefinitely.
/// If the timeout is [`None`], then [`write()`] calls will block indefinitely.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`write()`]: ../../std/io/trait.Write.html#tymethod.write
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_write_timeout(None).expect("set_write_timeout call failed");
/// assert_eq!(socket.write_timeout().unwrap(), None);
/// ```
#[stable(feature = "socket_timeout", since = "1.4.0")]
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.0.write_timeout()
@ -148,6 +257,15 @@ impl UdpSocket {
///
/// When enabled, this socket is allowed to send packets to a broadcast
/// address.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_broadcast(false).expect("set_broadcast call failed");
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
self.0.set_broadcast(broadcast)
@ -159,6 +277,16 @@ impl UdpSocket {
/// [`set_broadcast`][link].
///
/// [link]: #method.set_broadcast
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_broadcast(false).expect("set_broadcast call failed");
/// assert_eq!(socket.broadcast().unwrap(), false);
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn broadcast(&self) -> io::Result<bool> {
self.0.broadcast()
@ -168,6 +296,15 @@ impl UdpSocket {
///
/// If enabled, multicast packets will be looped back to the local socket.
/// Note that this may not have any affect on IPv6 sockets.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed");
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
self.0.set_multicast_loop_v4(multicast_loop_v4)
@ -179,6 +316,16 @@ impl UdpSocket {
/// [`set_multicast_loop_v4`][link].
///
/// [link]: #method.set_multicast_loop_v4
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed");
/// assert_eq!(socket.multicast_loop_v4().unwrap(), false);
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
self.0.multicast_loop_v4()
@ -191,6 +338,15 @@ impl UdpSocket {
/// don't leave the local network unless explicitly requested.
///
/// Note that this may not have any affect on IPv6 sockets.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed");
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
self.0.set_multicast_ttl_v4(multicast_ttl_v4)
@ -202,6 +358,16 @@ impl UdpSocket {
/// [`set_multicast_ttl_v4`][link].
///
/// [link]: #method.set_multicast_ttl_v4
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed");
/// assert_eq!(socket.multicast_ttl_v4().unwrap(), 42);
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
self.0.multicast_ttl_v4()
@ -211,6 +377,15 @@ impl UdpSocket {
///
/// Controls whether this socket sees the multicast packets it sends itself.
/// Note that this may not have any affect on IPv4 sockets.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed");
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
self.0.set_multicast_loop_v6(multicast_loop_v6)
@ -222,6 +397,16 @@ impl UdpSocket {
/// [`set_multicast_loop_v6`][link].
///
/// [link]: #method.set_multicast_loop_v6
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed");
/// assert_eq!(socket.multicast_loop_v6().unwrap(), false);
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
self.0.multicast_loop_v6()
@ -231,6 +416,15 @@ impl UdpSocket {
///
/// This value sets the time-to-live field that is used in every packet sent
/// from this socket.
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_ttl(42).expect("set_ttl call failed");
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.0.set_ttl(ttl)
@ -241,6 +435,16 @@ impl UdpSocket {
/// For more information about this option, see [`set_ttl`][link].
///
/// [link]: #method.set_ttl
///
/// # Examples
///
/// ```no_run
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// socket.set_ttl(42).expect("set_ttl call failed");
/// assert_eq!(socket.ttl().unwrap(), 42);
/// ```
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn ttl(&self) -> io::Result<u32> {
self.0.ttl()

View File

@ -457,7 +457,17 @@ pub enum Component<'a> {
}
impl<'a> Component<'a> {
/// Extracts the underlying `OsStr` slice
/// Extracts the underlying `OsStr` slice.
///
/// # Examples
///
/// ```
/// use std::path::Path;
///
/// let path = Path::new("./tmp/foo/bar.txt");
/// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();
/// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_os_str(self) -> &'a OsStr {
match self {

View File

@ -10,6 +10,7 @@
// ignore-windows
// ignore-android
// ignore-aarch64
// min-lldb-version: 310
// aux-build:macro-stepping.rs

View File

@ -0,0 +1,28 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct Point {
pub x: f32,
pub y: f32,
}
#[cfg(rpass2)]
fn unused_helper() {
}
pub fn distance_squared(this: &Point) -> f32 {
return this.x * this.x + this.y * this.y;
}
impl Point {
pub fn distance_from_origin(&self) -> f32 {
distance_squared(self).sqrt()
}
}

View File

@ -0,0 +1,84 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test where we add a private item into the root of an external.
// crate. This should not cause anything we use to be invalidated.
// Regression test for #36168.
// revisions:rpass1 rpass2
// compile-flags: -Z query-dep-graph
// aux-build:point.rs
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![allow(dead_code)]
#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="rpass2")]
#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
extern crate point;
/// A fn item that calls (public) methods on `Point` from the same impl
mod fn_calls_methods_in_same_impl {
use point::Point;
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
pub fn check() {
let x = Point { x: 2.0, y: 2.0 };
x.distance_from_origin();
}
}
/// A fn item that calls (public) methods on `Point` from another impl
mod fn_calls_free_fn {
use point::{self, Point};
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
pub fn check() {
let x = Point { x: 2.0, y: 2.0 };
point::distance_squared(&x);
}
}
/// A fn item that makes an instance of `Point` but does not invoke methods
mod fn_make_struct {
use point::Point;
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
pub fn make_origin() -> Point {
Point { x: 2.0, y: 2.0 }
}
}
/// A fn item that reads fields from `Point` but does not invoke methods
mod fn_read_field {
use point::Point;
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
pub fn get_x(p: Point) -> f32 {
p.x
}
}
/// A fn item that writes to a field of `Point` but does not invoke methods
mod fn_write_field {
use point::Point;
#[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
pub fn inc_x(p: &mut Point) {
p.x += 1.0;
}
}
fn main() {
}

View File

@ -1,4 +1,4 @@
error[E0323]: item `bar` is an associated const, which doesn't match its trait `<FooConstForMethod as Foo>`
error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo`
--> $DIR/impl-wrong-item-for-trait.rs:25:5
|
16 | fn bar(&self);
@ -24,7 +24,7 @@ error[E0046]: not all trait items implemented, missing: `bar`
29 | | }
| |_^ ...ending here: missing `bar` in implementation
error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `<FooMethodForConst as Foo>`
error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo`
--> $DIR/impl-wrong-item-for-trait.rs:37:5
|
17 | const MY_CONST: u32;
@ -50,7 +50,7 @@ error[E0046]: not all trait items implemented, missing: `MY_CONST`
40 | | }
| |_^ ...ending here: missing `MY_CONST` in implementation
error[E0325]: item `bar` is an associated type, which doesn't match its trait `<FooTypeForMethod as Foo>`
error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo`
--> $DIR/impl-wrong-item-for-trait.rs:47:5
|
16 | fn bar(&self);