Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #64461

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d86516d
Stabilise weak_ptr_eq
Thomasdezeeuw Aug 25, 2019
307804a
Update {rc, sync}::Weak::ptr_eq doc about comparing Weak::new
Thomasdezeeuw Aug 25, 2019
417b5f1
[const-prop] Replace `eval_place()` with use of `InterpCx`
wesleywiser Sep 4, 2019
600b9d1
[const-prop] Replace `Use` handling with use of `InterpCx`
wesleywiser Sep 6, 2019
1befe27
[const-prop] Replace `Cast` handling with use of `InterpCx`
wesleywiser Sep 6, 2019
c97347d
[const-prop] Replace `NullaryOp` handling with use of `InterpCx`
wesleywiser Sep 6, 2019
ec15579
[const-prop] Replace most `UnaryOp` handling with use of `InterpCx`
wesleywiser Sep 6, 2019
b5c28e0
[const-prop] Replace `CheckedBinaryOp` handling with use of `InterpCx`
wesleywiser Sep 9, 2019
a1053a9
[const-prop] Replace some `Binaryp` handling with use of `InterpCx`
wesleywiser Sep 10, 2019
72050c8
[const-prop] Replace `Ref` handling with use of `InterpCx`
wesleywiser Sep 11, 2019
fe323d4
Don't run the ConstProp MIR pass on generators
wesleywiser Sep 13, 2019
039fc48
Respond to code review feedback and fix tidy
wesleywiser Sep 13, 2019
0b333ef
Move Ref-from-arg checking from `step.rs` to `const_prop.rs`
wesleywiser Sep 14, 2019
b7f20d0
Provide a span if main function is not present in crate
Mark-Simulacrum Sep 8, 2019
7b3adc2
Ban non-extern rust intrinsics
Mark-Simulacrum Sep 12, 2019
2286a45
Rollup merge of #61797 - Thomasdezeeuw:stablise-weak_ptr_eq, r=RalfJung
Centril Sep 14, 2019
30b46ef
Rollup merge of #64290 - Mark-Simulacrum:span-no-main, r=estebank
Centril Sep 14, 2019
1fb2f4a
Rollup merge of #64406 - Mark-Simulacrum:error-unknown-intrinsic, r=C…
Centril Sep 14, 2019
8e00329
Rollup merge of #64419 - wesleywiser:const_prop_use_ecx, r=oli-obk
Centril Sep 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1832,8 +1832,9 @@ impl<T: ?Sized> Weak<T> {
}
}

/// Returns `true` if the two `Weak`s point to the same value (not just values
/// that compare as equal).
/// Returns `true` if the two `Weak`s point to the same value (not just
/// values that compare as equal), or if both don't point to any value
/// (because they were created with `Weak::new()`).
///
/// # Notes
///
Expand All @@ -1843,7 +1844,6 @@ impl<T: ?Sized> Weak<T> {
/// # Examples
///
/// ```
/// #![feature(weak_ptr_eq)]
/// use std::rc::Rc;
///
/// let first_rc = Rc::new(5);
Expand All @@ -1861,7 +1861,6 @@ impl<T: ?Sized> Weak<T> {
/// Comparing `Weak::new`.
///
/// ```
/// #![feature(weak_ptr_eq)]
/// use std::rc::{Rc, Weak};
///
/// let first = Weak::new();
Expand All @@ -1873,7 +1872,7 @@ impl<T: ?Sized> Weak<T> {
/// assert!(!first.ptr_eq(&third));
/// ```
#[inline]
#[unstable(feature = "weak_ptr_eq", issue = "55981")]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
self.ptr.as_ptr() == other.ptr.as_ptr()
}
Expand Down
10 changes: 4 additions & 6 deletions src/liballoc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1550,19 +1550,18 @@ impl<T: ?Sized> Weak<T> {
}
}

/// Returns `true` if the two `Weak`s point to the same value (not just values
/// that compare as equal).
/// Returns `true` if the two `Weak`s point to the same value (not just
/// values that compare as equal), or if both don't point to any value
/// (because they were created with `Weak::new()`).
///
/// # Notes
///
/// Since this compares pointers it means that `Weak::new()` will equal each
/// other, even though they don't point to any value.
///
///
/// # Examples
///
/// ```
/// #![feature(weak_ptr_eq)]
/// use std::sync::Arc;
///
/// let first_rc = Arc::new(5);
Expand All @@ -1580,7 +1579,6 @@ impl<T: ?Sized> Weak<T> {
/// Comparing `Weak::new`.
///
/// ```
/// #![feature(weak_ptr_eq)]
/// use std::sync::{Arc, Weak};
///
/// let first = Weak::new();
Expand All @@ -1592,7 +1590,7 @@ impl<T: ?Sized> Weak<T> {
/// assert!(!first.ptr_eq(&third));
/// ```
#[inline]
#[unstable(feature = "weak_ptr_eq", issue = "55981")]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
self.ptr.as_ptr() == other.ptr.as_ptr()
}
Expand Down
74 changes: 44 additions & 30 deletions src/librustc/middle/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ struct EntryContext<'a, 'tcx> {

map: &'a hir_map::Map<'tcx>,

/// The top-level function called 'main'.
/// The top-level function called `main`.
main_fn: Option<(HirId, Span)>,

/// The function that has attribute named 'main'.
/// The function that has attribute named `main`.
attr_main_fn: Option<(HirId, Span)>,

/// The function that has the attribute 'start' on it.
start_fn: Option<(HirId, Span)>,

/// The functions that one might think are 'main' but aren't, e.g.
/// The functions that one might think are `main` but aren't, e.g.
/// main functions not defined at the top level. For diagnostics.
non_main_fns: Vec<(HirId, Span)> ,
}
Expand Down Expand Up @@ -88,7 +88,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
EntryPointType::MainAttr
} else if item.ident.name == sym::main {
if at_root {
// This is a top-level function so can be 'main'.
// This is a top-level function so can be `main`.
EntryPointType::MainNamed
} else {
EntryPointType::OtherMain
Expand All @@ -109,7 +109,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
ctxt.main_fn = Some((item.hir_id, item.span));
} else {
span_err!(ctxt.session, item.span, E0136,
"multiple 'main' functions");
"multiple `main` functions");
}
},
EntryPointType::OtherMain => {
Expand All @@ -130,7 +130,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((item.hir_id, item.span));
} else {
struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions")
struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions")
.span_label(ctxt.start_fn.unwrap().1, "previous `start` function here")
.span_label(item.span, "multiple `start` functions")
.emit();
Expand All @@ -148,34 +148,48 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
} else if let Some((hir_id, _)) = visitor.main_fn {
Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
} else {
// There is no main function.
let mut err = struct_err!(tcx.sess, E0601,
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
if !visitor.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
err.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named 'main'");
}
err.emit();
} else {
if let Some(ref filename) = tcx.sess.local_crate_source_file {
err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
}
if tcx.sess.teach(&err.get_code().unwrap()) {
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/");
}
err.emit();
}

no_main_err(tcx, visitor);
None
}
}

fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
// There is no main function.
let mut err = struct_err!(tcx.sess, E0601,
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
let filename = &tcx.sess.local_crate_source_file;
let note = if !visitor.non_main_fns.is_empty() {
for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named `main`");
}
err.note("you have one or more functions named `main` not defined at the crate level");
err.help("either move the `main` function definitions or attach the `#[main]` attribute \
to one of them");
// There were some functions named `main` though. Try to give the user a hint.
format!("the main function must be defined at the crate level{}",
filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default())
} else if let Some(filename) = filename {
format!("consider adding a `main` function to `{}`", filename.display())
} else {
String::from("consider adding a `main` function at the crate level")
};
let sp = tcx.hir().krate().span;
// The file may be empty, which leads to the diagnostic machinery not emitting this
// note. This is a relatively simple way to detect that case and emit a span-less
// note instead.
if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) {
err.set_span(sp);
err.span_label(sp, &note);
} else {
err.note(&note);
}
if tcx.sess.teach(&err.get_code().unwrap()) {
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/");
}
err.emit();
}

pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> {
tcx.entry_fn(LOCAL_CRATE)
}
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ pub enum UnsupportedOpInfo<'tcx> {
InvalidPointerMath,
ReadUndefBytes(Size),
DeadLocal,
UninitializedLocal,
InvalidBoolOp(mir::BinOp),
UnimplementedTraitSelection,
CalledClosureAsFunction,
Expand Down Expand Up @@ -420,6 +421,7 @@ pub enum UnsupportedOpInfo<'tcx> {
HeapAllocNonPowerOfTwoAlignment(u64),
ReadFromReturnPointer,
PathNotFound(Vec<String>),
ReadOfStaticInConst,
}

impl fmt::Debug for UnsupportedOpInfo<'tcx> {
Expand Down Expand Up @@ -491,6 +493,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
addresses, e.g., comparing pointers into different allocations"),
DeadLocal =>
write!(f, "tried to access a dead local variable"),
UninitializedLocal =>
write!(f, "tried to access an uninitialized local variable"),
DerefFunctionPointer =>
write!(f, "tried to dereference a function pointer"),
ExecuteMemory =>
Expand Down Expand Up @@ -532,6 +536,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
not a power of two"),
Unsupported(ref msg) =>
write!(f, "{}", msg),
ReadOfStaticInConst =>
write!(f, "tried to read from a static during const evaluation"),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
match self.value {
LocalValue::Dead => throw_unsup!(DeadLocal),
LocalValue::Uninitialized =>
bug!("The type checker should prevent reading from a never-written local"),
// this is reachable from ConstProp
throw_unsup!(UninitializedLocal),
LocalValue::Live(val) => Ok(val),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

// Evaluate a place with the goal of reading from it. This lets us sometimes
// avoid allocations.
pub(super) fn eval_place_to_op(
pub fn eval_place_to_op(
&self,
place: &mir::Place<'tcx>,
layout: Option<TyLayout<'tcx>>,
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_mir/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,14 @@ where
}

StaticKind::Static => {
//if the first frame on the stack isn't a static item, then we shouldn't
//eval any static places
if let ty::InstanceDef::Item(item_def_id) = self.stack[0].instance.def {
if !self.tcx.is_static(item_def_id) {
trace!("eval_static_to_mplace: can't eval static in constant");
throw_unsup!(ReadOfStaticInConst);
}
}
let ty = place_static.ty;
assert!(!ty.needs_subst());
let layout = self.layout_of(ty)?;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
///
/// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
/// type writes its results directly into the memory specified by the place.
fn eval_rvalue_into_place(
pub fn eval_rvalue_into_place(
&mut self,
rvalue: &mir::Rvalue<'tcx>,
place: &mir::Place<'tcx>,
Expand Down
Loading