///
/// // These are all done without reallocating...
/// let cap = s.capacity();
- /// for i in 0..10 {
+ /// for _ in 0..10 {
/// s.push('a');
/// }
///
/// ```
/// 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));
/// ```
#![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)]
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> {
}
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.
}
}
+/// 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> {
/// 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>,
);
Mir {
+ phase: MirPhase::Build,
basic_blocks,
source_scopes,
source_scope_local_data,
}
impl_stable_hash_for!(struct Mir<'tcx> {
+ phase,
basic_blocks,
source_scopes,
source_scope_local_data,
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};
CloneTypeFoldableAndLiftImpls! {
BlockTailInfo,
+ MirPhase,
Mutability,
SourceInfo,
UpvarDecl,
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
+ phase,
basic_blocks,
source_scopes,
source_scope_local_data,
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
DefPathData::AssocTypeInImpl(_) |
DefPathData::AssocExistentialInImpl(_) |
DefPathData::Trait(_) |
+ DefPathData::Impl |
DefPathData::TypeNs(_) => {
break;
}
}
DefPathData::CrateRoot |
DefPathData::Misc |
- DefPathData::Impl |
DefPathData::Module(_) |
DefPathData::MacroDef(_) |
DefPathData::ClosureExpr |
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;
}
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
}
}
}
-
- 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
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;
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)
}
}
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)
}
}
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,
-
- 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"),
- ];
+ &generator::StateTransform,
+
+ &instcombine::InstCombine,
+ &const_prop::ConstProp,
+ &simplify_branches::SimplifyBranches::new("after-const-prop"),
+ &deaggregator::Deaggregator,
+ ©_prop::CopyPropagation,
+ &remove_noop_landing_pads::RemoveNoopLandingPads,
+ &simplify::SimplifyCfg::new("final"),
+ &simplify::SimplifyLocals,
+
+ &add_call_guards::CriticalCallEdges,
+ &dump_mir::Marker("PreCodegen"),
+ ]);
tcx.alloc_mir(mir)
}
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(),
)),
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
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() {
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
}
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
}
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
}
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.
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result);
if let PathResult::Module(..) = result {
- return Some(path)
+ return Some((path, None));
}
}
}
}
});
- } 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 {
&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;
}
}
}
- 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(¬e);
+ }
err.emit();
}
}
// 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;
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,
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 &&
}
}
};
- Some((span, msg))
+ Some((span, msg, None))
} else {
// `resolve_ident_in_module` reported a privacy error.
self.import_dummy_binding(directive);
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};
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) => {
})
}
-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);
- fcx.register_bound(
- item_ty,
- fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
- traits::ObligationCause::new(
- ty_span,
- fcx.body_id,
- traits::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),
+ );
+ }
vec![] // no implied bounds in a const etc
});
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 {
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}: {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}: {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)?;
}
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")) {
}
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) {
if (hideItemDeclarations === false) {
extraClass = 'collapsed';
}
+ } else if (hasClass(e, "sub-variant")) {
+ otherMessage = ' Show fields';
} else if (hasClass(e, "non-exhaustive")) {
otherMessage = ' This ';
if (hasClass(e, "non-exhaustive-struct")) {
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');
margin-top: -13px;
}
+.sub-variant > div > .stability {
+ margin-top: initial;
+}
+
.content .stability::before {
content: '˪';
font-size: 30px;
}
.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 {
use iter::{self, FusedIterator};
use ops::{self, Deref};
use rc::Rc;
+use str::FromStr;
+use string::ParseError;
use sync::Arc;
use ffi::{OsStr, OsString};
}
}
+#[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 {
self.directory.path.to_mut().push(&path.as_str());
self.directory.ownership = DirectoryOwnership::Owned { relative: None };
} else {
+ // We have to push on the current module name in the case of relative
+ // paths in order to ensure that any additional module paths from inline
+ // `mod x { ... }` come after the relative extension.
+ //
+ // For example, a `mod z { ... }` inside `x/y.rs` should set the current
+ // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
+ if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
+ if let Some(ident) = relative.take() { // remove the relative offset
+ self.directory.path.to_mut().push(ident.as_str());
+ }
+ }
self.directory.path.to_mut().push(&id.as_str());
}
}
// let mut _5: i32;
// bb0: {
// StorageLive(_1);
-// _1 = D::{{constructor}}(const 0i32,);
+// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_2);
// _2 = const 0i32;
// let mut _4: &'18s D;
// bb0: {
// StorageLive(_1);
-// _1 = D::{{constructor}}(const 0i32,);
+// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_3);
// StorageLive(_4);
// let mut _4: &'24s D;
// bb0: {
// StorageLive(_1);
-// _1 = D::{{constructor}}(const 0i32,);
+// _1 = D(const 0i32,);
// FakeRead(ForLet, _1);
// StorageLive(_3);
// StorageLive(_4);
// 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 };
// 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;
// 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);
// 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);
// bb0: {
// StorageLive(_1);
// ...
-// _1 = Packed::{{constructor}}(move _2,);
+// _1 = Packed(move _2,);
// ...
// StorageLive(_6);
// _6 = move (_1.0: Aligned);
--- /dev/null
+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() {}
--- /dev/null
+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
+
-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;
| 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
--- /dev/null
+// 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();
+}
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
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
--- /dev/null
+// compile-pass
+
+mod x;
+
+fn main() {}
--- /dev/null
+// ignore-test: not a test
+
+pub mod y {
+ pub mod z;
+}
--- /dev/null
+// ignore-test: not a test
// 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)]
|
= 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!();
|
= 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!();
<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
}
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;
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;
|
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
--- /dev/null
+// 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() {}