mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #42336 - Mark-Simulacrum:rollup, r=Mark-Simulacrum
Rollup of 7 pull requests - Successful merges: #42126, #42196, #42252, #42277, #42315, #42329, #42330 - Failed merges:
This commit is contained in:
commit
e0cc22b4ba
@ -169,6 +169,40 @@ pub trait AsMut<T: ?Sized> {
|
|||||||
/// - [`From<T>`][From]` for U` implies `Into<U> for T`
|
/// - [`From<T>`][From]` for U` implies `Into<U> for T`
|
||||||
/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
|
/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
|
||||||
///
|
///
|
||||||
|
/// # Implementing `Into`
|
||||||
|
///
|
||||||
|
/// There is one exception to implementing `Into`, and it's kind of esoteric.
|
||||||
|
/// If the destination type is not part of the current crate, and it uses a
|
||||||
|
/// generic variable, then you can't implement `From` directly. For example,
|
||||||
|
/// take this crate:
|
||||||
|
///
|
||||||
|
/// ```compile_fail
|
||||||
|
/// struct Wrapper<T>(Vec<T>);
|
||||||
|
/// impl<T> From<Wrapper<T>> for Vec<T> {
|
||||||
|
/// fn from(w: Wrapper<T>) -> Vec<T> {
|
||||||
|
/// w.0
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// To fix this, you can implement `Into` directly:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// struct Wrapper<T>(Vec<T>);
|
||||||
|
/// impl<T> Into<Vec<T>> for Wrapper<T> {
|
||||||
|
/// fn into(self) -> Vec<T> {
|
||||||
|
/// self.0
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This won't always allow the conversion: for example, `try!` and `?`
|
||||||
|
/// always use `From`. However, in most cases, people use `Into` to do the
|
||||||
|
/// conversions, and this will allow that.
|
||||||
|
///
|
||||||
|
/// In almost all cases, you should try to implement `From`, then fall back
|
||||||
|
/// to `Into` if `From` can't be implemented.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// [`String`] implements `Into<Vec<u8>>`:
|
/// [`String`] implements `Into<Vec<u8>>`:
|
||||||
@ -285,9 +319,11 @@ pub trait From<T>: Sized {
|
|||||||
/// Library authors should not directly implement this trait, but should prefer
|
/// Library authors should not directly implement this trait, but should prefer
|
||||||
/// implementing the [`TryFrom`] trait, which offers greater flexibility and
|
/// implementing the [`TryFrom`] trait, which offers greater flexibility and
|
||||||
/// provides an equivalent `TryInto` implementation for free, thanks to a
|
/// provides an equivalent `TryInto` implementation for free, thanks to a
|
||||||
/// blanket implementation in the standard library.
|
/// blanket implementation in the standard library. For more information on this,
|
||||||
|
/// see the documentation for [`Into`].
|
||||||
///
|
///
|
||||||
/// [`TryFrom`]: trait.TryFrom.html
|
/// [`TryFrom`]: trait.TryFrom.html
|
||||||
|
/// [`Into`]: trait.Into.html
|
||||||
#[unstable(feature = "try_from", issue = "33417")]
|
#[unstable(feature = "try_from", issue = "33417")]
|
||||||
pub trait TryInto<T>: Sized {
|
pub trait TryInto<T>: Sized {
|
||||||
/// The type returned in the event of a conversion error.
|
/// The type returned in the event of a conversion error.
|
||||||
|
@ -130,9 +130,10 @@ pub trait Iterator {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// // an infinite iterator has no upper bound
|
/// // an infinite iterator has no upper bound
|
||||||
|
/// // and the maximum possible lower bound
|
||||||
/// let iter = 0..;
|
/// let iter = 0..;
|
||||||
///
|
///
|
||||||
/// assert_eq!((0, None), iter.size_hint());
|
/// assert_eq!((usize::max_value(), None), iter.size_hint());
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -543,6 +543,11 @@ impl<A: Step> Iterator for ops::RangeFrom<A> where
|
|||||||
mem::swap(&mut n, &mut self.start);
|
mem::swap(&mut n, &mut self.start);
|
||||||
Some(n)
|
Some(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
(usize::MAX, None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "fused", issue = "35602")]
|
#[unstable(feature = "fused", issue = "35602")]
|
||||||
|
@ -109,7 +109,7 @@ pub trait FromIterator<A>: Sized {
|
|||||||
///
|
///
|
||||||
/// See the [module-level documentation] for more.
|
/// See the [module-level documentation] for more.
|
||||||
///
|
///
|
||||||
/// [module-level documentation]: trait.FromIterator.html
|
/// [module-level documentation]: index.html
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -219,7 +219,7 @@ pub trait IntoIterator {
|
|||||||
///
|
///
|
||||||
/// See the [module-level documentation] for more.
|
/// See the [module-level documentation] for more.
|
||||||
///
|
///
|
||||||
/// [module-level documentation]: trait.IntoIterator.html
|
/// [module-level documentation]: index.html
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -220,7 +220,7 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
|
|||||||
|
|
||||||
/// Returns the [ABI]-required minimum alignment of a type.
|
/// Returns the [ABI]-required minimum alignment of a type.
|
||||||
///
|
///
|
||||||
/// Every valid address of a value of the type `T` must be a multiple of this number.
|
/// Every reference to a value of the type `T` must be a multiple of this number.
|
||||||
///
|
///
|
||||||
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
|
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
|
||||||
///
|
///
|
||||||
@ -243,7 +243,7 @@ pub fn min_align_of<T>() -> usize {
|
|||||||
|
|
||||||
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
|
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
|
||||||
///
|
///
|
||||||
/// Every valid address of a value of the type `T` must be a multiple of this number.
|
/// Every reference to a value of the type `T` must be a multiple of this number.
|
||||||
///
|
///
|
||||||
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
|
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
|
||||||
///
|
///
|
||||||
@ -264,7 +264,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
|
|||||||
|
|
||||||
/// Returns the [ABI]-required minimum alignment of a type.
|
/// Returns the [ABI]-required minimum alignment of a type.
|
||||||
///
|
///
|
||||||
/// Every valid address of a value of the type `T` must be a multiple of this number.
|
/// Every reference to a value of the type `T` must be a multiple of this number.
|
||||||
///
|
///
|
||||||
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
|
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
|
||||||
///
|
///
|
||||||
@ -285,7 +285,7 @@ pub fn align_of<T>() -> usize {
|
|||||||
|
|
||||||
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
|
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
|
||||||
///
|
///
|
||||||
/// Every valid address of a value of the type `T` must be a multiple of this number.
|
/// Every reference to a value of the type `T` must be a multiple of this number.
|
||||||
///
|
///
|
||||||
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
|
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
|
||||||
///
|
///
|
||||||
|
@ -764,6 +764,7 @@ fn test_iterator_size_hint() {
|
|||||||
let v2 = &[10, 11, 12];
|
let v2 = &[10, 11, 12];
|
||||||
let vi = v.iter();
|
let vi = v.iter();
|
||||||
|
|
||||||
|
assert_eq!((0..).size_hint(), (usize::MAX, None));
|
||||||
assert_eq!(c.size_hint(), (usize::MAX, None));
|
assert_eq!(c.size_hint(), (usize::MAX, None));
|
||||||
assert_eq!(vi.clone().size_hint(), (10, Some(10)));
|
assert_eq!(vi.clone().size_hint(), (10, Some(10)));
|
||||||
|
|
||||||
|
@ -1682,7 +1682,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
{
|
{
|
||||||
if let InferTables::InProgress(tables) = self.tables {
|
if let InferTables::InProgress(tables) = self.tables {
|
||||||
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
||||||
return tables.borrow().closure_kinds.get(&id).cloned();
|
return tables.borrow()
|
||||||
|
.closure_kinds
|
||||||
|
.get(&id)
|
||||||
|
.cloned()
|
||||||
|
.map(|(kind, _)| kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1354,7 +1354,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
|||||||
};
|
};
|
||||||
|
|
||||||
let unparsed_crate_types = matches.opt_strs("crate-type");
|
let unparsed_crate_types = matches.opt_strs("crate-type");
|
||||||
let (crate_types, emit_metadata) = parse_crate_types_from_list(unparsed_crate_types)
|
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
|
||||||
.unwrap_or_else(|e| early_error(error_format, &e[..]));
|
.unwrap_or_else(|e| early_error(error_format, &e[..]));
|
||||||
|
|
||||||
let mut lint_opts = vec![];
|
let mut lint_opts = vec![];
|
||||||
@ -1402,9 +1402,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if emit_metadata {
|
if output_types.is_empty() {
|
||||||
output_types.insert(OutputType::Metadata, None);
|
|
||||||
} else if output_types.is_empty() {
|
|
||||||
output_types.insert(OutputType::Exe, None);
|
output_types.insert(OutputType::Exe, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1629,9 +1627,8 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_crate_types_from_list(list_list: Vec<String>)
|
pub fn parse_crate_types_from_list(list_list: Vec<String>)
|
||||||
-> Result<(Vec<CrateType>, bool), String> {
|
-> Result<Vec<CrateType>, String> {
|
||||||
let mut crate_types: Vec<CrateType> = Vec::new();
|
let mut crate_types: Vec<CrateType> = Vec::new();
|
||||||
let mut emit_metadata = false;
|
|
||||||
for unparsed_crate_type in &list_list {
|
for unparsed_crate_type in &list_list {
|
||||||
for part in unparsed_crate_type.split(',') {
|
for part in unparsed_crate_type.split(',') {
|
||||||
let new_part = match part {
|
let new_part = match part {
|
||||||
@ -1642,13 +1639,6 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>)
|
|||||||
"cdylib" => CrateTypeCdylib,
|
"cdylib" => CrateTypeCdylib,
|
||||||
"bin" => CrateTypeExecutable,
|
"bin" => CrateTypeExecutable,
|
||||||
"proc-macro" => CrateTypeProcMacro,
|
"proc-macro" => CrateTypeProcMacro,
|
||||||
// FIXME(#38640) remove this when Cargo is fixed.
|
|
||||||
"metadata" => {
|
|
||||||
early_warn(ErrorOutputType::default(), "--crate-type=metadata is deprecated, \
|
|
||||||
prefer --emit=metadata");
|
|
||||||
emit_metadata = true;
|
|
||||||
CrateTypeRlib
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(format!("unknown crate type: `{}`",
|
return Err(format!("unknown crate type: `{}`",
|
||||||
part));
|
part));
|
||||||
@ -1660,7 +1650,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok((crate_types, emit_metadata));
|
Ok(crate_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod nightly_options {
|
pub mod nightly_options {
|
||||||
|
@ -58,6 +58,7 @@ use syntax::abi;
|
|||||||
use syntax::ast::{self, Name, NodeId};
|
use syntax::ast::{self, Name, NodeId};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::{Symbol, keywords};
|
||||||
|
use syntax_pos::Span;
|
||||||
|
|
||||||
use hir;
|
use hir;
|
||||||
|
|
||||||
@ -229,8 +230,9 @@ pub struct TypeckTables<'tcx> {
|
|||||||
/// Records the type of each closure.
|
/// Records the type of each closure.
|
||||||
pub closure_tys: NodeMap<ty::PolyFnSig<'tcx>>,
|
pub closure_tys: NodeMap<ty::PolyFnSig<'tcx>>,
|
||||||
|
|
||||||
/// Records the kind of each closure.
|
/// Records the kind of each closure and the span and name of the variable
|
||||||
pub closure_kinds: NodeMap<ty::ClosureKind>,
|
/// that caused the closure to be this kind.
|
||||||
|
pub closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||||
|
|
||||||
/// For each fn, records the "liberated" types of its arguments
|
/// For each fn, records the "liberated" types of its arguments
|
||||||
/// and return type. Liberated means that all bound regions
|
/// and return type. Liberated means that all bound regions
|
||||||
|
@ -39,8 +39,6 @@ use rustc::middle::free_region::RegionRelations;
|
|||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::ty::maps::Providers;
|
use rustc::ty::maps::Providers;
|
||||||
|
|
||||||
use syntax_pos::DUMMY_SP;
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@ -587,9 +585,15 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||||||
verb, msg, nl);
|
verb, msg, nl);
|
||||||
let need_note = match lp.ty.sty {
|
let need_note = match lp.ty.sty {
|
||||||
ty::TypeVariants::TyClosure(id, _) => {
|
ty::TypeVariants::TyClosure(id, _) => {
|
||||||
if let Ok(ty::ClosureKind::FnOnce) =
|
let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
|
||||||
ty::queries::closure_kind::try_get(self.tcx, DUMMY_SP, id) {
|
if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) =
|
||||||
err.help("closure was moved because it only implements `FnOnce`");
|
self.tables.closure_kinds.get(&node_id)
|
||||||
|
{
|
||||||
|
err.span_note(span, &format!(
|
||||||
|
"closure cannot be invoked more than once because \
|
||||||
|
it moves the variable `{}` out of its environment",
|
||||||
|
name
|
||||||
|
));
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
self.tables.borrow_mut().closure_tys.insert(expr.id, sig);
|
self.tables.borrow_mut().closure_tys.insert(expr.id, sig);
|
||||||
match opt_kind {
|
match opt_kind {
|
||||||
Some(kind) => {
|
Some(kind) => {
|
||||||
self.tables.borrow_mut().closure_kinds.insert(expr.id, kind);
|
self.tables.borrow_mut().closure_kinds.insert(expr.id, (kind, None));
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
let closure_kinds = &self.tables.borrow().closure_kinds;
|
let closure_kinds = &self.tables.borrow().closure_kinds;
|
||||||
let closure_kind = match closure_kinds.get(&closure_id) {
|
let closure_kind = match closure_kinds.get(&closure_id) {
|
||||||
Some(&k) => k,
|
Some(&(k, _)) => k,
|
||||||
None => {
|
None => {
|
||||||
return Err(MethodError::ClosureAmbiguity(trait_def_id));
|
return Err(MethodError::ClosureAmbiguity(trait_def_id));
|
||||||
}
|
}
|
||||||
|
@ -702,7 +702,7 @@ fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> ty::ClosureKind {
|
-> ty::ClosureKind {
|
||||||
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||||
tcx.typeck_tables_of(def_id).closure_kinds[&node_id]
|
tcx.typeck_tables_of(def_id).closure_kinds[&node_id].0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||||
temp_closure_kinds: NodeMap<ty::ClosureKind>,
|
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
|
||||||
@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
capture_clause: hir::CaptureClause)
|
capture_clause: hir::CaptureClause)
|
||||||
{
|
{
|
||||||
if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) {
|
if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) {
|
||||||
self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn);
|
self.temp_closure_kinds.insert(expr.id, (ty::ClosureKind::Fn, None));
|
||||||
debug!("check_closure: adding closure {:?} as Fn", expr.id);
|
debug!("check_closure: adding closure {:?} as Fn", expr.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +143,12 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||||
temp_closure_kinds: NodeMap<ty::ClosureKind>,
|
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||||
fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||||
temp_closure_kinds: NodeMap<ty::ClosureKind>)
|
temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>)
|
||||||
-> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
-> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||||
AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
|
AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds }
|
||||||
}
|
}
|
||||||
@ -211,8 +211,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
// If we are also inferred the closure kind here, update the
|
// If we are also inferred the closure kind here, update the
|
||||||
// main table and process any deferred resolutions.
|
// main table and process any deferred resolutions.
|
||||||
if let Some(&kind) = self.temp_closure_kinds.get(&id) {
|
if let Some(&(kind, context)) = self.temp_closure_kinds.get(&id) {
|
||||||
self.fcx.tables.borrow_mut().closure_kinds.insert(id, kind);
|
self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, context));
|
||||||
let closure_def_id = self.fcx.tcx.hir.local_def_id(id);
|
let closure_def_id = self.fcx.tcx.hir.local_def_id(id);
|
||||||
debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
|
debug!("closure_kind({:?}) = {:?}", closure_def_id, kind);
|
||||||
|
|
||||||
@ -272,6 +272,8 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
euv::Move(_) => { }
|
euv::Move(_) => { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tcx = self.fcx.tcx;
|
||||||
|
|
||||||
// watch out for a move of the deref of a borrowed pointer;
|
// watch out for a move of the deref of a borrowed pointer;
|
||||||
// for that to be legal, the upvar would have to be borrowed
|
// for that to be legal, the upvar would have to be borrowed
|
||||||
// by value instead
|
// by value instead
|
||||||
@ -289,7 +291,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
// to move out of an upvar, this must be a FnOnce closure
|
// to move out of an upvar, this must be a FnOnce closure
|
||||||
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||||
ty::ClosureKind::FnOnce);
|
ty::ClosureKind::FnOnce,
|
||||||
|
guarantor.span,
|
||||||
|
tcx.hir.name(upvar_id.var_id));
|
||||||
|
|
||||||
let upvar_capture_map =
|
let upvar_capture_map =
|
||||||
&mut self.fcx.tables.borrow_mut().upvar_capture_map;
|
&mut self.fcx.tables.borrow_mut().upvar_capture_map;
|
||||||
@ -303,7 +307,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
// to be a FnOnce closure to permit moves out
|
// to be a FnOnce closure to permit moves out
|
||||||
// of the environment.
|
// of the environment.
|
||||||
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||||
ty::ClosureKind::FnOnce);
|
ty::ClosureKind::FnOnce,
|
||||||
|
guarantor.span,
|
||||||
|
tcx.hir.name(upvar_id.var_id));
|
||||||
}
|
}
|
||||||
mc::NoteNone => {
|
mc::NoteNone => {
|
||||||
}
|
}
|
||||||
@ -331,7 +337,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
|
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
|
||||||
Categorization::Deref(base, _, mc::Implicit(..)) => {
|
Categorization::Deref(base, _, mc::Implicit(..)) => {
|
||||||
if !self.try_adjust_upvar_deref(&cmt.note, ty::MutBorrow) {
|
if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
|
||||||
// assignment to deref of an `&mut`
|
// assignment to deref of an `&mut`
|
||||||
// borrowed pointer implies that the
|
// borrowed pointer implies that the
|
||||||
// pointer itself must be unique, but not
|
// pointer itself must be unique, but not
|
||||||
@ -365,7 +371,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
|
Categorization::Deref(base, _, mc::BorrowedPtr(..)) |
|
||||||
Categorization::Deref(base, _, mc::Implicit(..)) => {
|
Categorization::Deref(base, _, mc::Implicit(..)) => {
|
||||||
if !self.try_adjust_upvar_deref(&cmt.note, ty::UniqueImmBorrow) {
|
if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
|
||||||
// for a borrowed pointer to be unique, its
|
// for a borrowed pointer to be unique, its
|
||||||
// base must be unique
|
// base must be unique
|
||||||
self.adjust_upvar_borrow_kind_for_unique(base);
|
self.adjust_upvar_borrow_kind_for_unique(base);
|
||||||
@ -382,7 +388,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn try_adjust_upvar_deref(&mut self,
|
fn try_adjust_upvar_deref(&mut self,
|
||||||
note: &mc::Note,
|
cmt: mc::cmt<'tcx>,
|
||||||
borrow_kind: ty::BorrowKind)
|
borrow_kind: ty::BorrowKind)
|
||||||
-> bool
|
-> bool
|
||||||
{
|
{
|
||||||
@ -394,7 +400,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
ty::ImmBorrow => false,
|
ty::ImmBorrow => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
match *note {
|
let tcx = self.fcx.tcx;
|
||||||
|
|
||||||
|
match cmt.note {
|
||||||
mc::NoteUpvarRef(upvar_id) => {
|
mc::NoteUpvarRef(upvar_id) => {
|
||||||
// if this is an implicit deref of an
|
// if this is an implicit deref of an
|
||||||
// upvar, then we need to modify the
|
// upvar, then we need to modify the
|
||||||
@ -407,7 +415,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// also need to be in an FnMut closure since this is not an ImmBorrow
|
// also need to be in an FnMut closure since this is not an ImmBorrow
|
||||||
self.adjust_closure_kind(upvar_id.closure_expr_id, ty::ClosureKind::FnMut);
|
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||||
|
ty::ClosureKind::FnMut,
|
||||||
|
cmt.span,
|
||||||
|
tcx.hir.name(upvar_id.var_id));
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -415,7 +426,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
// this kind of deref occurs in a `move` closure, or
|
// this kind of deref occurs in a `move` closure, or
|
||||||
// for a by-value upvar; in either case, to mutate an
|
// for a by-value upvar; in either case, to mutate an
|
||||||
// upvar, we need to be an FnMut closure
|
// upvar, we need to be an FnMut closure
|
||||||
self.adjust_closure_kind(upvar_id.closure_expr_id, ty::ClosureKind::FnMut);
|
self.adjust_closure_kind(upvar_id.closure_expr_id,
|
||||||
|
ty::ClosureKind::FnMut,
|
||||||
|
cmt.span,
|
||||||
|
tcx.hir.name(upvar_id.var_id));
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -462,11 +476,13 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
fn adjust_closure_kind(&mut self,
|
fn adjust_closure_kind(&mut self,
|
||||||
closure_id: ast::NodeId,
|
closure_id: ast::NodeId,
|
||||||
new_kind: ty::ClosureKind) {
|
new_kind: ty::ClosureKind,
|
||||||
debug!("adjust_closure_kind(closure_id={}, new_kind={:?})",
|
upvar_span: Span,
|
||||||
closure_id, new_kind);
|
var_name: ast::Name) {
|
||||||
|
debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})",
|
||||||
|
closure_id, new_kind, upvar_span, var_name);
|
||||||
|
|
||||||
if let Some(&existing_kind) = self.temp_closure_kinds.get(&closure_id) {
|
if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) {
|
||||||
debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
|
debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
|
||||||
closure_id, existing_kind, new_kind);
|
closure_id, existing_kind, new_kind);
|
||||||
|
|
||||||
@ -482,7 +498,10 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
|||||||
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
|
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
|
||||||
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
|
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
|
||||||
// new kind is stronger than the old kind
|
// new kind is stronger than the old kind
|
||||||
self.temp_closure_kinds.insert(closure_id, new_kind);
|
self.temp_closure_kinds.insert(
|
||||||
|
closure_id,
|
||||||
|
(new_kind, Some((upvar_span, var_name)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -698,24 +698,6 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_contextual_keyword(&mut self, ident: Ident) -> bool {
|
|
||||||
self.expected_tokens.push(TokenType::Token(token::Ident(ident)));
|
|
||||||
if let token::Ident(ref cur_ident) = self.token {
|
|
||||||
cur_ident.name == ident.name
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eat_contextual_keyword(&mut self, ident: Ident) -> bool {
|
|
||||||
if self.check_contextual_keyword(ident) {
|
|
||||||
self.bump();
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If the given word is not a keyword, signal an error.
|
/// If the given word is not a keyword, signal an error.
|
||||||
/// If the next token is not the given word, signal an error.
|
/// If the next token is not the given word, signal an error.
|
||||||
/// Otherwise, eat it.
|
/// Otherwise, eat it.
|
||||||
@ -3755,6 +3737,28 @@ impl<'a> Parser<'a> {
|
|||||||
self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
|
self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_defaultness(&self) -> bool {
|
||||||
|
// `pub` is included for better error messages
|
||||||
|
self.token.is_keyword(keywords::Default) &&
|
||||||
|
self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
|
||||||
|
t.is_keyword(keywords::Const) ||
|
||||||
|
t.is_keyword(keywords::Fn) ||
|
||||||
|
t.is_keyword(keywords::Unsafe) ||
|
||||||
|
t.is_keyword(keywords::Extern) ||
|
||||||
|
t.is_keyword(keywords::Type) ||
|
||||||
|
t.is_keyword(keywords::Pub))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat_defaultness(&mut self) -> bool {
|
||||||
|
let is_defaultness = self.is_defaultness();
|
||||||
|
if is_defaultness {
|
||||||
|
self.bump()
|
||||||
|
} else {
|
||||||
|
self.expected_tokens.push(TokenType::Keyword(keywords::Default));
|
||||||
|
}
|
||||||
|
is_defaultness
|
||||||
|
}
|
||||||
|
|
||||||
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility)
|
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility)
|
||||||
-> PResult<'a, Option<P<Item>>> {
|
-> PResult<'a, Option<P<Item>>> {
|
||||||
let lo = self.span;
|
let lo = self.span;
|
||||||
@ -5229,7 +5233,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
/// Parse defaultness: DEFAULT or nothing
|
/// Parse defaultness: DEFAULT or nothing
|
||||||
fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
|
fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
|
||||||
if self.eat_contextual_keyword(keywords::Default.ident()) {
|
if self.eat_defaultness() {
|
||||||
Ok(Defaultness::Default)
|
Ok(Defaultness::Default)
|
||||||
} else {
|
} else {
|
||||||
Ok(Defaultness::Final)
|
Ok(Defaultness::Final)
|
||||||
|
27
src/test/run-pass/macro-named-default.rs
Normal file
27
src/test/run-pass/macro-named-default.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
macro_rules! default {
|
||||||
|
($($x:tt)*) => { $($x)* }
|
||||||
|
}
|
||||||
|
|
||||||
|
default! {
|
||||||
|
struct A;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl A {
|
||||||
|
default! {
|
||||||
|
fn foo(&self) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
A.foo();
|
||||||
|
}
|
@ -20,5 +20,6 @@ fn main() {
|
|||||||
debug_dump_dict();
|
debug_dump_dict();
|
||||||
debug_dump_dict();
|
debug_dump_dict();
|
||||||
//~^ ERROR use of moved value: `debug_dump_dict`
|
//~^ ERROR use of moved value: `debug_dump_dict`
|
||||||
//~| NOTE closure was moved because it only implements `FnOnce`
|
//~| NOTE closure cannot be invoked more than once because it moves the
|
||||||
|
//~| variable `dict` out of its environment
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,11 @@ error[E0382]: use of moved value: `debug_dump_dict`
|
|||||||
21 | debug_dump_dict();
|
21 | debug_dump_dict();
|
||||||
| ^^^^^^^^^^^^^^^ value used here after move
|
| ^^^^^^^^^^^^^^^ value used here after move
|
||||||
|
|
|
|
||||||
= help: closure was moved because it only implements `FnOnce`
|
note: closure cannot be invoked more than once because it moves the variable `dict` out of its environment
|
||||||
|
--> $DIR/fn_once-moved.rs:16:29
|
||||||
|
|
|
||||||
|
16 | for (key, value) in dict {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to previous error(s)
|
error: aborting due to previous error(s)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user