1
Fork 0

Auto merge of #55433 - kennytm:rollup, r=kennytm

Rollup of 11 pull requests

Successful merges:

 - #55148 (Implement FromStr for PathBuf)
 - #55185 (path suggestions in Rust 2018 should point out the change in semantics)
 - #55191 (Fix sub-variant doc display)
 - #55199 (Impl items have generics)
 - #55244 (Don't rerun MIR passes when inlining)
 - #55252 (Add MaybeUninit::new)
 - #55257 (Allow extern statics with an extern type)
 - #55389 (Remove unnecessary mut in iterator.find_map documentation example, R…)
 - #55406 (Update string.rs)
 - #55412 (Fix an ICE in the min_const_fn analysis)
 - #55421 (Add ManuallyDrop::take)
This commit is contained in:
bors 2018-10-28 16:00:00 +00:00
commit d492c6792c
37 changed files with 384 additions and 169 deletions

View file

@ -413,7 +413,7 @@ impl String {
///
/// // These are all done without reallocating...
/// let cap = s.capacity();
/// for i in 0..10 {
/// for _ in 0..10 {
/// s.push('a');
/// }
///

View file

@ -1857,7 +1857,7 @@ pub trait Iterator {
/// ```
/// let a = ["lol", "NaN", "2", "5"];
///
/// let mut first_number = a.iter().find_map(|s| s.parse().ok());
/// let first_number = a.iter().find_map(|s| s.parse().ok());
///
/// assert_eq!(first_number, Some(2));
/// ```

View file

@ -82,6 +82,7 @@
#![feature(const_fn)]
#![feature(const_int_ops)]
#![feature(const_fn_union)]
#![feature(const_manually_drop_new)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]

View file

@ -973,6 +973,26 @@ impl<T> ManuallyDrop<T> {
pub fn into_inner(slot: ManuallyDrop<T>) -> T {
slot.value
}
/// Takes the contained value out.
///
/// This method is primarily intended for moving out values in drop.
/// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
/// you can use this method to take the value and use it however desired.
/// `Drop` will be invoked on the returned value following normal end-of-scope rules.
///
/// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
///
/// # Safety
///
/// This function semantically moves out the contained value without preventing further usage.
/// It is up to the user of this method to ensure that this container is not used again.
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
#[unstable(feature = "manually_drop_take", issue = "55422")]
#[inline]
pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
ManuallyDrop::into_inner(ptr::read(slot))
}
}
impl<T: ?Sized> ManuallyDrop<T> {
@ -1021,6 +1041,15 @@ pub union MaybeUninit<T> {
}
impl<T> MaybeUninit<T> {
/// Create a new `MaybeUninit` initialized with the given value.
///
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
pub const fn new(val: T) -> MaybeUninit<T> {
MaybeUninit { value: ManuallyDrop::new(val) }
}
/// Create a new `MaybeUninit` in an uninitialized state.
///
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.

View file

@ -69,6 +69,24 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
}
}
/// The various "big phases" that MIR goes through.
///
/// Warning: ordering of variants is significant
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum MirPhase {
Build = 0,
Const = 1,
Validated = 2,
Optimized = 3,
}
impl MirPhase {
/// Gets the index of the current MirPhase within the set of all MirPhases.
pub fn phase_index(&self) -> usize {
*self as usize
}
}
/// Lowered representation of a single function.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Mir<'tcx> {
@ -76,6 +94,13 @@ pub struct Mir<'tcx> {
/// that indexes into this vector.
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
/// Records how far through the "desugaring and optimization" process this particular
/// MIR has traversed. This is particularly useful when inlining, since in that context
/// we instantiate the promoted constants and add them to our promoted vector -- but those
/// promoted items have already been optimized, whereas ours have not. This field allows
/// us to see the difference and forego optimization on the inlined promoted items.
pub phase: MirPhase,
/// List of source scopes; these are referenced by statements
/// and used for debuginfo. Indexed by a `SourceScope`.
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
@ -151,6 +176,7 @@ impl<'tcx> Mir<'tcx> {
);
Mir {
phase: MirPhase::Build,
basic_blocks,
source_scopes,
source_scope_local_data,
@ -368,6 +394,7 @@ pub enum Safety {
}
impl_stable_hash_for!(struct Mir<'tcx> {
phase,
basic_blocks,
source_scopes,
source_scope_local_data,
@ -616,6 +643,13 @@ impl_stable_hash_for!(enum self::ImplicitSelfKind {
None
});
impl_stable_hash_for!(enum self::MirPhase {
Build,
Const,
Validated,
Optimized,
});
mod binding_form_impl {
use ich::StableHashingContext;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
@ -2905,6 +2939,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
CloneTypeFoldableAndLiftImpls! {
BlockTailInfo,
MirPhase,
Mutability,
SourceInfo,
UpvarDecl,
@ -2917,6 +2952,7 @@ CloneTypeFoldableAndLiftImpls! {
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
phase,
basic_blocks,
source_scopes,
source_scope_local_data,

View file

@ -251,25 +251,17 @@ impl PrintContext {
fn parameterized<F: fmt::Write>(&mut self,
f: &mut F,
substs: &subst::Substs<'_>,
mut did: DefId,
did: DefId,
projections: &[ty::ProjectionPredicate<'_>])
-> fmt::Result {
let key = ty::tls::with(|tcx| tcx.def_key(did));
let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() {
Some(name)
} else {
did.index = key.parent.unwrap_or_else(
|| bug!("finding type for {:?}, encountered def-id {:?} with no parent",
did, did));
self.parameterized(f, substs, did, projections)?;
return write!(f, "::{}", key.disambiguated_data.data.as_interned_str());
};
let verbose = self.is_verbose;
let mut num_supplied_defaults = 0;
let mut has_self = false;
let mut own_counts: GenericParamCount = Default::default();
let mut is_value_path = false;
let mut item_name = Some(key.disambiguated_data.data.as_interned_str());
let fn_trait_kind = ty::tls::with(|tcx| {
// Unfortunately, some kinds of items (e.g., closures) don't have
// generics. So walk back up the find the closest parent that DOES
@ -282,6 +274,7 @@ impl PrintContext {
DefPathData::AssocTypeInImpl(_) |
DefPathData::AssocExistentialInImpl(_) |
DefPathData::Trait(_) |
DefPathData::Impl |
DefPathData::TypeNs(_) => {
break;
}
@ -292,7 +285,6 @@ impl PrintContext {
}
DefPathData::CrateRoot |
DefPathData::Misc |
DefPathData::Impl |
DefPathData::Module(_) |
DefPathData::MacroDef(_) |
DefPathData::ClosureExpr |

View file

@ -612,6 +612,13 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
other => return other,
}
}
// the first trace is for replicating an ice
// There's no tracking issue, but the next two lines concatenated link to the discussion on
// zulip. It's not really possible to test this, because it doesn't show up in diagnostics
// or MIR.
// https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
// subject/anon_const_instance_printing/near/135980032
trace!("const eval: {}", key.value.instance);
trace!("const eval: {:?}", key);
let cid = key.value;

View file

@ -184,7 +184,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
}
crate fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrow_set.borrows }
pub fn scope_tree(&self) -> &Lrc<region::ScopeTree> { &self.scope_tree }
pub fn location(&self, idx: BorrowIndex) -> &Location {
&self.borrow_set.borrows[idx].reserve_location

View file

@ -724,20 +724,6 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
}
}
}
pub fn new_from_sets(mir: &'a Mir<'tcx>,
dead_unwinds: &'a BitSet<mir::BasicBlock>,
sets: AllSets<D::Idx>,
denotation: D) -> Self {
DataflowAnalysis {
mir,
dead_unwinds,
flow_state: DataflowState {
sets: sets,
operator: denotation,
}
}
}
}
impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation

View file

@ -11,7 +11,7 @@
use borrow_check::nll::type_check;
use build;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::mir::{Mir, Promoted};
use rustc::mir::{Mir, MirPhase, Promoted};
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
use rustc::ty::steal::Steal;
@ -155,53 +155,69 @@ pub trait MirPass {
mir: &mut Mir<'tcx>);
}
pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{
let suite_index: usize = $suite_index;
let run_passes = |mir: &mut _, promoted| {
pub fn run_passes(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &mut Mir<'tcx>,
def_id: DefId,
mir_phase: MirPhase,
passes: &[&dyn MirPass],
) {
let phase_index = mir_phase.phase_index();
let run_passes = |mir: &mut Mir<'tcx>, promoted| {
if mir.phase >= mir_phase {
return;
}
let source = MirSource {
def_id: $def_id,
promoted
def_id,
promoted,
};
let mut index = 0;
let mut run_pass = |pass: &dyn MirPass| {
let run_hooks = |mir: &_, index, is_after| {
dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index),
dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index),
&pass.name(), source, mir, is_after);
};
run_hooks(mir, index, false);
pass.run_pass($tcx, source, mir);
pass.run_pass(tcx, source, mir);
run_hooks(mir, index, true);
index += 1;
};
$(run_pass(&$pass);)*
for pass in passes {
run_pass(*pass);
}
mir.phase = mir_phase;
};
run_passes(&mut $mir, None);
run_passes(mir, None);
for (index, promoted_mir) in $mir.promoted.iter_enumerated_mut() {
for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() {
run_passes(promoted_mir, Some(index));
// Let's make sure we don't miss any nested instances
assert!(promoted_mir.promoted.is_empty());
//Let's make sure we don't miss any nested instances
assert!(promoted_mir.promoted.is_empty())
}
}}
}
fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
// Unsafety check uses the raw mir, so make sure it is run
let _ = tcx.unsafety_check_result(def_id);
let mut mir = tcx.mir_built(def_id).steal();
run_passes![tcx, mir, def_id, 0;
run_passes(tcx, &mut mir, def_id, MirPhase::Const, &[
// Remove all `EndRegion` statements that are not involved in borrows.
cleanup_post_borrowck::CleanEndRegions,
&cleanup_post_borrowck::CleanEndRegions,
// What we need to do constant evaluation.
simplify::SimplifyCfg::new("initial"),
type_check::TypeckMir,
rustc_peek::SanityCheck,
uniform_array_move_out::UniformArrayMoveOut,
];
&simplify::SimplifyCfg::new("initial"),
&type_check::TypeckMir,
&rustc_peek::SanityCheck,
&uniform_array_move_out::UniformArrayMoveOut,
]);
tcx.alloc_steal_mir(mir)
}
@ -214,11 +230,11 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
}
let mut mir = tcx.mir_const(def_id).steal();
run_passes![tcx, mir, def_id, 1;
run_passes(tcx, &mut mir, def_id, MirPhase::Validated, &[
// What we need to run borrowck etc.
qualify_consts::QualifyAndPromoteConstants,
simplify::SimplifyCfg::new("qualify-consts"),
];
&qualify_consts::QualifyAndPromoteConstants,
&simplify::SimplifyCfg::new("qualify-consts"),
]);
tcx.alloc_steal_mir(mir)
}
@ -232,59 +248,59 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
}
let mut mir = tcx.mir_validated(def_id).steal();
run_passes![tcx, mir, def_id, 2;
run_passes(tcx, &mut mir, def_id, MirPhase::Optimized, &[
// Remove all things not needed by analysis
no_landing_pads::NoLandingPads,
simplify_branches::SimplifyBranches::new("initial"),
remove_noop_landing_pads::RemoveNoopLandingPads,
&no_landing_pads::NoLandingPads,
&simplify_branches::SimplifyBranches::new("initial"),
&remove_noop_landing_pads::RemoveNoopLandingPads,
// Remove all `AscribeUserType` statements.
cleanup_post_borrowck::CleanAscribeUserType,
&cleanup_post_borrowck::CleanAscribeUserType,
// Remove all `FakeRead` statements and the borrows that are only
// used for checking matches
cleanup_post_borrowck::CleanFakeReadsAndBorrows,
simplify::SimplifyCfg::new("early-opt"),
&cleanup_post_borrowck::CleanFakeReadsAndBorrows,
&simplify::SimplifyCfg::new("early-opt"),
// These next passes must be executed together
add_call_guards::CriticalCallEdges,
elaborate_drops::ElaborateDrops,
no_landing_pads::NoLandingPads,
&add_call_guards::CriticalCallEdges,
&elaborate_drops::ElaborateDrops,
&no_landing_pads::NoLandingPads,
// AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
// an AllCallEdges pass right before it.
add_call_guards::AllCallEdges,
add_validation::AddValidation,
&add_call_guards::AllCallEdges,
&add_validation::AddValidation,
// AddMovesForPackedDrops needs to run after drop
// elaboration.
add_moves_for_packed_drops::AddMovesForPackedDrops,
&add_moves_for_packed_drops::AddMovesForPackedDrops,
simplify::SimplifyCfg::new("elaborate-drops"),
&simplify::SimplifyCfg::new("elaborate-drops"),
// No lifetime analysis based on borrowing can be done from here on out.
// From here on out, regions are gone.
erase_regions::EraseRegions,
&erase_regions::EraseRegions,
lower_128bit::Lower128Bit,
&lower_128bit::Lower128Bit,
// Optimizations begin.
uniform_array_move_out::RestoreSubsliceArrayMoveOut,
inline::Inline,
&uniform_array_move_out::RestoreSubsliceArrayMoveOut,
&inline::Inline,
// Lowering generator control-flow and variables
// has to happen before we do anything else to them.
generator::StateTransform,
&generator::StateTransform,
instcombine::InstCombine,
const_prop::ConstProp,
simplify_branches::SimplifyBranches::new("after-const-prop"),
deaggregator::Deaggregator,
copy_prop::CopyPropagation,
remove_noop_landing_pads::RemoveNoopLandingPads,
simplify::SimplifyCfg::new("final"),
simplify::SimplifyLocals,
&instcombine::InstCombine,
&const_prop::ConstProp,
&simplify_branches::SimplifyBranches::new("after-const-prop"),
&deaggregator::Deaggregator,
&copy_prop::CopyPropagation,
&remove_noop_landing_pads::RemoveNoopLandingPads,
&simplify::SimplifyCfg::new("final"),
&simplify::SimplifyLocals,
add_call_guards::CriticalCallEdges,
dump_mir::Marker("PreCodegen"),
];
&add_call_guards::CriticalCallEdges,
&dump_mir::Marker("PreCodegen"),
]);
tcx.alloc_mir(mir)
}

View file

@ -317,7 +317,8 @@ fn check_terminator(
check_place(tcx, mir, location, span, PlaceMode::Read)?;
check_operand(tcx, mir, value, span)
},
TerminatorKind::SwitchInt { .. } => Err((
TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err((
span,
"`if`, `match`, `&&` and `||` are not stable in const fn".into(),
)),
@ -363,7 +364,7 @@ fn check_terminator(
cleanup: _,
} => check_operand(tcx, mir, cond, span),
| TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!(
| TerminatorKind::FalseUnwind { .. } => span_bug!(
terminator.source_info.span,
"min_const_fn encountered `{:#?}`",
terminator

View file

@ -26,7 +26,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
span: Span,
path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
) -> Option<(Vec<Segment>, Option<String>)> {
debug!("make_path_suggestion: span={:?} path={:?}", span, path);
// If we don't have a path to suggest changes to, then return.
if path.is_empty() {
@ -65,13 +65,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `self` and check if that is valid.
path[0].ident.name = keywords::SelfValue.name();
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some(path)
Some((path, None))
} else {
None
}
@ -89,13 +89,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = keywords::Crate.name();
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some(path)
Some((
path,
Some(
"`use` statements changed in Rust 2018; read more at \
<https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
clarity.html>".to_string()
),
))
} else {
None
}
@ -113,13 +120,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = keywords::Super.name();
let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some(path)
Some((path, None))
} else {
None
}
@ -140,7 +147,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<Vec<Segment>> {
) -> Option<(Vec<Segment>, Option<String>)> {
// Need to clone else we can't call `resolve_path` without a borrow error. We also store
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
// each time.
@ -162,7 +169,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result);
if let PathResult::Module(..) = result {
return Some(path)
return Some((path, None));
}
}

View file

@ -707,7 +707,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
}
});
} else if let Some((span, err)) = error {
} else if let Some((span, err, note)) = error {
errors = true;
if let SingleImport { source, ref result, .. } = import.subclass {
@ -737,7 +737,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
&import.subclass,
span,
);
error_vec.push((span, path, err));
error_vec.push((span, path, err, note));
seen_spans.insert(span);
prev_root_id = import.root_id;
}
@ -829,27 +829,45 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
}
fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>,
span: Option<MultiSpan>) {
fn throw_unresolved_import_error(
&self,
error_vec: Vec<(Span, String, String, Option<String>)>,
span: Option<MultiSpan>,
) {
let max_span_label_msg_count = 10; // upper limit on number of span_label message.
let (span, msg) = if error_vec.is_empty() {
(span.unwrap(), "unresolved import".to_string())
let (span, msg, note) = if error_vec.is_empty() {
(span.unwrap(), "unresolved import".to_string(), None)
} else {
let span = MultiSpan::from_spans(error_vec.clone().into_iter()
.map(|elem: (Span, String, String)| { elem.0 })
.collect());
let span = MultiSpan::from_spans(
error_vec.clone().into_iter()
.map(|elem: (Span, String, String, Option<String>)| elem.0)
.collect()
);
let note: Option<String> = error_vec.clone().into_iter()
.filter_map(|elem: (Span, String, String, Option<String>)| elem.3)
.last();
let path_vec: Vec<String> = error_vec.clone().into_iter()
.map(|elem: (Span, String, String)| { format!("`{}`", elem.1) })
.map(|elem: (Span, String, String, Option<String>)| format!("`{}`", elem.1))
.collect();
let path = path_vec.join(", ");
let msg = format!("unresolved import{} {}",
if path_vec.len() > 1 { "s" } else { "" }, path);
(span, msg)
let msg = format!(
"unresolved import{} {}",
if path_vec.len() > 1 { "s" } else { "" },
path
);
(span, msg, note)
};
let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
for span_error in error_vec.into_iter().take(max_span_label_msg_count) {
err.span_label(span_error.0, span_error.2);
}
if let Some(note) = note {
err.note(&note);
}
err.emit();
}
@ -945,7 +963,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
// If appropriate, returns an error to report.
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
fn finalize_import(
&mut self,
directive: &'b ImportDirective<'b>
) -> Option<(Span, String, Option<String>)> {
self.current_module = directive.parent_scope.module;
let ImportDirective { ref module_path, span, .. } = *directive;
@ -969,15 +990,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
return None;
}
PathResult::Failed(span, msg, true) => {
return if let Some(suggested_path) = self.make_path_suggestion(
return if let Some((suggested_path, note)) = self.make_path_suggestion(
span, module_path.clone(), &directive.parent_scope
) {
Some((
span,
format!("Did you mean `{}`?", Segment::names_to_string(&suggested_path))
format!("Did you mean `{}`?", Segment::names_to_string(&suggested_path)),
note,
))
} else {
Some((span, msg))
Some((span, msg, None))
};
},
_ => return None,
@ -1002,8 +1024,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
if let ModuleOrUniformRoot::Module(module) = module {
if module.def_id() == directive.parent_scope.module.def_id() {
// Importing a module into itself is not allowed.
return Some((directive.span,
"Cannot glob-import a module into itself.".to_string()));
return Some((
directive.span,
"Cannot glob-import a module into itself.".to_string(),
None,
));
}
}
if !is_prelude &&
@ -1101,7 +1126,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
}
};
Some((span, msg))
Some((span, msg, None))
} else {
// `resolve_ident_in_module` reported a privacy error.
self.import_dummy_binding(directive);

View file

@ -13,7 +13,7 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
use hir::def_id::DefId;
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable};
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::util::ExplicitSelf;
use rustc::util::nodemap::{FxHashSet, FxHashMap};
@ -119,14 +119,14 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def
check_item_fn(tcx, item);
}
hir::ItemKind::Static(ref ty, ..) => {
check_item_type(tcx, item.id, ty.span);
check_item_type(tcx, item.id, ty.span, false);
}
hir::ItemKind::Const(ref ty, ..) => {
check_item_type(tcx, item.id, ty.span);
check_item_type(tcx, item.id, ty.span, false);
}
hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() {
if let hir::ForeignItemKind::Static(ref ty, ..) = it.node {
check_item_type(tcx, it.id, ty.span);
check_item_type(tcx, it.id, ty.span, true);
}
},
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
@ -340,23 +340,33 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
})
}
fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, ty_span: Span) {
fn check_item_type<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
item_id: ast::NodeId,
ty_span: Span,
allow_foreign_ty: bool,
) {
debug!("check_item_type: {:?}", item_id);
for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| {
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id));
let item_ty = fcx.normalize_associated_types_in(ty_span, &ty);
let mut forbid_unsized = true;
if allow_foreign_ty {
if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty {
forbid_unsized = false;
}
}
fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation);
if forbid_unsized {
fcx.register_bound(
item_ty,
fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
traits::ObligationCause::new(
ty_span,
fcx.body_id,
traits::MiscObligation,
),
traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation),
);
}
vec![] // no implied bounds in a const etc
});

View file

@ -3379,10 +3379,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
let variant_id = cx.derive_id(format!("{}.{}.fields",
ItemType::Variant,
variant.name.as_ref().unwrap()));
write!(w, "<span class='docblock autohide sub-variant' id='{id}'>",
write!(w, "<span class='autohide sub-variant' id='{id}'>",
id = variant_id)?;
write!(w, "<h3 class='fields'>Fields of <code>{name}</code></h3>\n
<table>", name = variant.name.as_ref().unwrap())?;
write!(w, "<h3>Fields of <b>{name}</b></h3><div>",
name = variant.name.as_ref().unwrap())?;
for field in &s.fields {
use clean::StructFieldItem;
if let StructFieldItem(ref ty) = field.inner {
@ -3394,19 +3394,18 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
ItemType::Variant.name_space(),
field.name.as_ref().unwrap(),
ItemType::StructField.name_space()));
write!(w, "<tr><td \
id='{id}'>\
<span id='{ns_id}' class='invisible'>\
<code>{f}:&nbsp;{t}</code></span></td><td>",
write!(w, "<span id=\"{id}\" class=\"variant small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\"></a>\
<span id='{ns_id}' class='invisible'><code>{f}:&nbsp;{t}\
</code></span></span>",
id = id,
ns_id = ns_id,
f = field.name.as_ref().unwrap(),
t = *ty)?;
document(w, cx, field)?;
write!(w, "</td></tr>")?;
}
}
write!(w, "</table></span>")?;
write!(w, "</div></span>")?;
}
render_stability_since(w, variant, it)?;
}

View file

@ -1886,7 +1886,7 @@
if (hasClass(relatedDoc, "stability")) {
relatedDoc = relatedDoc.nextElementSibling;
}
if (hasClass(relatedDoc, "docblock")) {
if (hasClass(relatedDoc, "docblock") || hasClass(relatedDoc, "sub-variant")) {
var action = mode;
if (action === "toggle") {
if (hasClass(relatedDoc, "hidden-by-usual-hider")) {
@ -2094,15 +2094,13 @@
}
var hideItemDeclarations = getCurrentValue('rustdoc-item-declarations') === "false";
onEach(document.getElementsByClassName('docblock'), function(e) {
function buildToggleWrapper(e) {
if (hasClass(e, 'autohide')) {
var wrap = e.previousElementSibling;
if (wrap && hasClass(wrap, 'toggle-wrapper')) {
var toggle = wrap.childNodes[0];
var extra = false;
if (e.childNodes[0].tagName === 'H3') {
extra = true;
}
var extra = e.childNodes[0].tagName === 'H3';
e.style.display = 'none';
addClass(wrap, 'collapsed');
onEach(toggle.getElementsByClassName('inner'), function(e) {
@ -2127,6 +2125,8 @@
if (hideItemDeclarations === false) {
extraClass = 'collapsed';
}
} else if (hasClass(e, "sub-variant")) {
otherMessage = '&nbsp;Show&nbsp;fields';
} else if (hasClass(e, "non-exhaustive")) {
otherMessage = '&nbsp;This&nbsp;';
if (hasClass(e, "non-exhaustive-struct")) {
@ -2150,7 +2150,10 @@
collapseDocs(e.previousSibling.childNodes[0], "toggle");
}
}
});
}
onEach(document.getElementsByClassName('docblock'), buildToggleWrapper);
onEach(document.getElementsByClassName('sub-variant'), buildToggleWrapper);
function createToggleWrapper(tog) {
var span = document.createElement('span');

View file

@ -517,6 +517,10 @@ h4 > code, h3 > code, .invisible > code {
margin-top: -13px;
}
.sub-variant > div > .stability {
margin-top: initial;
}
.content .stability::before {
content: '˪';
font-size: 30px;
@ -866,7 +870,23 @@ span.since {
}
.sub-variant, .sub-variant > h3 {
margin-top: 0 !important;
margin-top: 1px !important;
}
#main > .sub-variant > h3 {
font-size: 15px;
margin-left: 25px;
margin-bottom: 5px;
}
.sub-variant > div {
margin-left: 20px;
margin-bottom: 10px;
}
.sub-variant > div > span {
display: block;
position: relative;
}
.toggle-label {

View file

@ -87,6 +87,8 @@ use io;
use iter::{self, FusedIterator};
use ops::{self, Deref};
use rc::Rc;
use str::FromStr;
use string::ParseError;
use sync::Arc;
use ffi::{OsStr, OsString};
@ -1443,6 +1445,15 @@ impl From<String> for PathBuf {
}
}
#[stable(feature = "path_from_str", since = "1.26.0")]
impl FromStr for PathBuf {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(PathBuf::from(s))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {

View file

@ -44,7 +44,7 @@ fn foo(i: i32) {
// let mut _5: i32;
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_2);
// _2 = const 0i32;

View file

@ -37,7 +37,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// let mut _4: &'18s D;
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_3);
// StorageLive(_4);

View file

@ -37,7 +37,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// let mut _4: &'24s D;
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_3);
// StorageLive(_4);

View file

@ -36,7 +36,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// let mut _3: [closure@NodeId(33) d:D];
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_3);
// _3 = [closure@NodeId(33)] { d: move _1 };

View file

@ -39,7 +39,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
// let mut _4: [closure@NodeId(33) r:&'24s D];
// bb0: {
// StorageLive(_1);
// _1 = D::{{constructor}}(const 0i32,);
// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_2);
// _2 = &'26_1rs _1;

View file

@ -79,16 +79,16 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> {
// StorageLive(_3);
// StorageLive(_4);
// StorageLive(_5);
// _5 = S1::{{constructor}}(const "ex1",);
// _5 = S1(const "ex1",);
// _4 = &'15ds _5;
// _3 = &'15ds (*_4);
// StorageLive(_6);
// StorageLive(_7);
// StorageLive(_8);
// _8 = S1::{{constructor}}(const "dang1",);
// _8 = S1(const "dang1",);
// _7 = &'13s _8;
// _6 = &'13s (*_7);
// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6);
// _2 = D1<'15ds, '13s>(move _3, move _6);
// EndRegion('13s);
// StorageDead(_6);
// StorageDead(_3);
@ -132,7 +132,7 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> {
// StorageLive(_7);
// _7 = &'13s (promoted[0]: S1);
// _6 = &'13s (*_7);
// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6);
// _2 = D1<'15ds, '13s>(move _3, move _6);
// EndRegion('13s);
// StorageDead(_6);
// StorageDead(_3);

View file

@ -42,7 +42,7 @@ impl Drop for Droppy {
// bb0: {
// StorageLive(_1);
// ...
// _1 = Packed::{{constructor}}(move _2,);
// _1 = Packed(move _2,);
// ...
// StorageLive(_6);
// _6 = move (_1.0: Aligned);

View file

@ -0,0 +1,15 @@
enum Foo {
Prob,
}
impl Foo {
pub const fn as_val(&self) -> u8 {
use self::Foo::*;
match *self {
Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
}
}
}
fn main() {}

View file

@ -0,0 +1,8 @@
error: `if`, `match`, `&&` and `||` are not stable in const fn
--> $DIR/single_variant_match_ice.rs:10:13
|
LL | Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
| ^^^^
error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error[E0606]: casting `fn(i32) -> Inches {Inches::{{constructor}}}` as `f32` is invalid
error[E0606]: casting `fn(i32) -> Inches {Inches}` as `f32` is invalid
--> $DIR/issue-21554.rs:14:5
|
LL | Inches as f32;

View file

@ -9,7 +9,7 @@ LL | fn test() -> Foo { Foo } //~ ERROR mismatched types
| expected `Foo` because of return type
|
= note: expected type `Foo`
found type `fn(u32) -> Foo {Foo::{{constructor}}}`
found type `fn(u32) -> Foo {Foo}`
error: aborting due to previous error

View file

@ -0,0 +1,11 @@
// Regression test for #50411: the MIR inliner was causing problems
// here because it would inline promoted code (which had already had
// elaborate-drops invoked on it) and then try to elaboate drops a
// second time. Uncool.
// compile-flags:-Zmir-opt-level=3
// compile-pass
fn main() {
let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
}

View file

@ -144,11 +144,11 @@ note: required by `check`
LL | fn check<T: Impossible>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `fn() -> c::TS {c::TS::{{constructor}}}: Impossible` is not satisfied
error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied
--> $DIR/namespace-mix.rs:66:5
|
LL | check(m3::TS); //~ ERROR c::TS
| ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS::{{constructor}}}`
| ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
|
note: required by `check`
--> $DIR/namespace-mix.rs:31:1
@ -192,11 +192,11 @@ note: required by `check`
LL | fn check<T: Impossible>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS::{{constructor}}}: Impossible` is not satisfied
error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied
--> $DIR/namespace-mix.rs:72:5
|
LL | check(xm3::TS); //~ ERROR c::TS
| ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS::{{constructor}}}`
| ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
|
note: required by `check`
--> $DIR/namespace-mix.rs:31:1

View file

@ -14,8 +14,8 @@
// error-pattern:static `PRIV_STATIC` is private
// error-pattern:type `ext::PrivEnum` is private
// error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr
// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private
// error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
#![feature(decl_macro)]

View file

@ -30,7 +30,7 @@ LL | ext::m!();
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is private
error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
--> $DIR/private-inferred-type-3.rs:26:5
|
LL | ext::m!();
@ -38,7 +38,7 @@ LL | ext::m!();
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is private
error: type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private
--> $DIR/private-inferred-type-3.rs:26:5
|
LL | ext::m!();

View file

@ -53,9 +53,9 @@ mod m {
<u8 as PrivTrait>::method; //~ ERROR type `fn() {<u8 as m::PrivTrait>::method}` is private
<u8 as PubTrait>::method; // OK
PrivTupleStruct;
//~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is priv
//~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private
PubTupleStruct;
//~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat
//~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private
Pub(0u8).priv_method();
//~^ ERROR type `for<'r> fn(&'r m::Pub<u8>) {<m::Pub<u8>>::priv_method}` is private
}

View file

@ -115,7 +115,7 @@ LL | <u8 as PrivTrait>::method; //~ ERROR type `fn() {<u8 as m::PrivTrai
LL | m::m!();
| -------- in this macro invocation
error: type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is private
error: type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private
--> $DIR/private-inferred-type.rs:55:9
|
LL | PrivTupleStruct;
@ -124,7 +124,7 @@ LL | PrivTupleStruct;
LL | m::m!();
| -------- in this macro invocation
error: type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is private
error: type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private
--> $DIR/private-inferred-type.rs:57:9
|
LL | PubTupleStruct;

View file

@ -3,6 +3,8 @@ error[E0432]: unresolved import `foo`
|
LL | use foo::Bar;
| ^^^ Did you mean `crate::foo`?
|
= note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
error[E0432]: unresolved import `foo`
--> $DIR/local-path-suggestions-2018.rs:27:5

View file

@ -0,0 +1,37 @@
// Copyright 2018 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.
// compile-pass
#![feature(extern_types)]
pub mod a {
extern "C" {
pub type StartFn;
pub static start: StartFn;
}
}
pub mod b {
#[repr(transparent)]
pub struct TransparentType(::a::StartFn);
extern "C" {
pub static start: TransparentType;
}
}
pub mod c {
#[repr(C)]
pub struct CType(u32, ::b::TransparentType);
extern "C" {
pub static start: CType;
}
}
fn main() {}