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 #64466

Merged
merged 11 commits into from
Sep 15, 2019
Merged
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
11 changes: 2 additions & 9 deletions src/librustc_interface/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ use syntax::mut_visit::MutVisitor;
use syntax::parse::{self, PResult};
use syntax::util::node_count::NodeCounter;
use syntax::symbol::Symbol;
use syntax::feature_gate::AttributeType;
use syntax_pos::FileName;
use syntax_ext;

Expand Down Expand Up @@ -219,7 +218,6 @@ impl BoxedResolver {

pub struct PluginInfo {
syntax_exts: Vec<NamedSyntaxExtension>,
attributes: Vec<(Symbol, AttributeType)>,
}

pub fn register_plugins<'a>(
Expand Down Expand Up @@ -312,12 +310,9 @@ pub fn register_plugins<'a>(
}

*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
*sess.plugin_attributes.borrow_mut() = attributes.clone();
*sess.plugin_attributes.borrow_mut() = attributes;

Ok((krate, PluginInfo {
syntax_exts,
attributes,
}))
Ok((krate, PluginInfo { syntax_exts }))
}

fn configure_and_expand_inner<'a>(
Expand All @@ -329,7 +324,6 @@ fn configure_and_expand_inner<'a>(
crate_loader: &'a mut CrateLoader<'a>,
plugin_info: PluginInfo,
) -> Result<(ast::Crate, Resolver<'a>)> {
let attributes = plugin_info.attributes;
time(sess, "pre ast expansion lint checks", || {
lint::check_ast_crate(
sess,
Expand Down Expand Up @@ -522,7 +516,6 @@ fn configure_and_expand_inner<'a>(
&krate,
&sess.parse_sess,
&sess.features_untracked(),
&attributes,
sess.opts.unstable_features,
);
});
Expand Down
20 changes: 19 additions & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,8 @@ fn check_fn<'a, 'tcx>(

let span = body.value.span;

fn_maybe_err(fcx.tcx, span, fn_sig.abi);

if body.generator_kind.is_some() && can_be_generator.is_some() {
let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
Expand Down Expand Up @@ -1439,6 +1441,14 @@ fn check_opaque_for_cycles<'tcx>(
}
}

// Forbid defining intrinsics in Rust code,
// as they must always be defined by the compiler.
fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
}
}

pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
debug!(
"check_item_type(it.hir_id={}, it.name={})",
Expand Down Expand Up @@ -1475,9 +1485,17 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
check_on_unimplemented(tcx, trait_def_id, it);
}
}
hir::ItemKind::Trait(..) => {
hir::ItemKind::Trait(_, _, _, _, ref items) => {
let def_id = tcx.hir().local_def_id(it.hir_id);
check_on_unimplemented(tcx, def_id, it);

for item in items.iter() {
let item = tcx.hir().trait_item(item.id);
if let hir::TraitItemKind::Method(sig, _) = &item.node {
let abi = sig.header.abi;
fn_maybe_err(tcx, item.ident.span, abi);
}
}
}
hir::ItemKind::Struct(..) => {
check_struct(tcx, it.hir_id, it.span);
Expand Down
15 changes: 3 additions & 12 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use syntax_pos::{Span, DUMMY_SP, FileName};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use std::io::ErrorKind;
use std::{iter, mem};
use std::{iter, mem, slice};
use std::ops::DerefMut;
use std::rc::Rc;
use std::path::PathBuf;
Expand Down Expand Up @@ -1019,7 +1019,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
let features = self.cx.ecfg.features.unwrap();
for attr in attrs.iter() {
self.check_attribute_inner(attr, features);
feature_gate::check_attribute(attr, self.cx.parse_sess, features);

// macros are expanded before any lint passes so this warning has to be hardcoded
if attr.path == sym::derive {
Expand All @@ -1029,15 +1029,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
}
}
}

fn check_attribute(&mut self, at: &ast::Attribute) {
let features = self.cx.ecfg.features.unwrap();
self.check_attribute_inner(at, features);
}

fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
feature_gate::check_attribute(at, self.cx.parse_sess, features);
}
}

impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
Expand Down Expand Up @@ -1445,7 +1436,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {

if let Some(file) = it.value_str() {
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
self.check_attribute(&at);
self.check_attributes(slice::from_ref(at));
if self.cx.parse_sess.span_diagnostic.err_count() > err_count {
// avoid loading the file if they haven't enabled the feature
return noop_visit_attribute(at, self);
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/feature_gate/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub enum AttributeType {
CrateLevel,
}

#[derive(Clone, Copy)]
pub enum AttributeGate {
/// Is gated by a given feature gate, reason
/// and function to check if enabled
Expand Down
Loading